@@ -9,40 +9,40 @@ def initialize(n, c)
9
9
@weights = Array . new ( n ) { rand ( 0 ..1.0 ) }
10
10
@c = c
11
11
end
12
-
12
+
13
13
# Function to train the Perceptron
14
14
# Weights are adjusted based on vehicle's error
15
15
def train ( forces , error )
16
16
trained = @weights . zip ( forces . map { |f | f . to_a }
17
17
. map { |a , b | ( a * error . x + b * error . y ) * @c } )
18
- . map { |w , c | constrain ( w + c , 0 , 1.0 ) }
18
+ . map { |w , c | ( w + c ) . clamp ( 0 , 1.0 ) }
19
19
@weights = trained
20
20
end
21
-
21
+
22
22
# Give me a steering result
23
23
def feedforward ( forces )
24
24
# Sum all values
25
25
forces . zip ( @weights ) . map { |a , b | a * b } . reduce ( Vec2D . new , :+ )
26
26
# forces.zip(@weights).map { |a, b| a * b }.reduce(:+)
27
27
end
28
- end
28
+ end
29
29
# Seek
30
30
# Daniel Shiffman <http://www.shiffman.net>
31
-
31
+
32
32
class Vehicle
33
33
MAX_SPEED = 4
34
34
MAX_FORCE = 0.1
35
35
36
36
attr_reader :brain , :sz , :location , :targets , :desired
37
-
37
+
38
38
def initialize ( n , x , y )
39
39
@brain = Perceptron . new ( n , 0.001 )
40
40
@acceleration = Vec2D . new
41
41
@velocity = Vec2D . new
42
42
@location = Vec2D . new ( x , y )
43
43
@sz = 6.0
44
44
end
45
-
45
+
46
46
# Method to update location
47
47
def update ( width , height )
48
48
# Update velocity
@@ -52,15 +52,15 @@ def update(width, height)
52
52
@location += @velocity
53
53
# Reset acceleration to 0 each cycle
54
54
@acceleration *= 0
55
- @location . x = constrain ( location . x , 0 , width )
56
- @location . y = constrain ( location . y , 0 , height )
55
+ @location . x = location . x . clamp ( 0 , width )
56
+ @location . y = location . y . clamp ( 0 , height )
57
57
end
58
-
58
+
59
59
def apply_force ( force )
60
60
# We could add mass here if we want A = F / M
61
61
@acceleration += force
62
62
end
63
-
63
+
64
64
# Here is where the brain processes everything
65
65
def steer ( targets , desired )
66
66
# Steer towards all targets
@@ -73,7 +73,7 @@ def steer(targets, desired)
73
73
error = desired - location
74
74
brain . train ( forces , error )
75
75
end
76
-
76
+
77
77
# A method that calculates a steering force towards a target
78
78
# STEER = DESIRED MINUS VELOCITY
79
79
def seek ( target )
@@ -86,8 +86,8 @@ def seek(target)
86
86
steer . set_mag ( MAX_FORCE ) { steer . mag > MAX_FORCE } # Limit to a maximum steering force
87
87
steer
88
88
end
89
-
90
- def display
89
+
90
+ def display
91
91
# Draw a triangle rotated in the direction of velocity
92
92
theta = @velocity . heading + PI / 2
93
93
fill ( 175 )
@@ -103,7 +103,7 @@ def display
103
103
end_shape ( CLOSE )
104
104
pop_matrix
105
105
end
106
- end
106
+ end
107
107
end
108
108
109
109
include SeekingNeural
@@ -114,9 +114,9 @@ def display
114
114
def setup
115
115
sketch_title 'Seeking Neural'
116
116
# The Vehicle's desired location
117
- @desired = Vec2D . new ( width / 2 , height / 2 )
117
+ @desired = Vec2D . new ( width / 2 , height / 2 )
118
118
# Create a list of targets
119
- make_targets
119
+ make_targets
120
120
# Create the Vehicle (it has to know about the number of targets
121
121
# in order to configure its brain)
122
122
@v = Vehicle . new ( targets . size , rand ( width ) , rand ( height ) )
@@ -128,12 +128,12 @@ def make_targets
128
128
end
129
129
130
130
def draw
131
- background ( 255 )
131
+ background ( 255 )
132
132
# Draw a circle to show the Vehicle's goal
133
133
stroke ( 0 )
134
134
stroke_weight ( 2 )
135
135
fill ( 0 , 100 )
136
- ellipse ( desired . x , desired . y , 36 , 36 )
136
+ ellipse ( desired . x , desired . y , 36 , 36 )
137
137
# Draw the targets
138
138
targets . each do |target |
139
139
no_fill
@@ -142,7 +142,7 @@ def draw
142
142
ellipse ( target . x , target . y , 16 , 16 )
143
143
line ( target . x , target . y - 16 , target . x , target . y + 16 )
144
144
line ( target . x - 16 , target . y , target . x + 16 , target . y )
145
- end
145
+ end
146
146
# Update the Vehicle
147
147
v . steer ( targets , desired )
148
148
v . update ( width , height )
0 commit comments