breed [ whales a_whale ]
breed [ boats a_boat ]
boats-own
[
whale
wx wy wh wdx wdy ws
gx gy gh
max-speed
max-turn
safe-distance
speed
accel
safe-range
]
whales-own
[ speed
spook-zone
]
to startup setup end
to setup
ca
create-whales 1
[ set shape "whale"
setxy 0 0
rt random 360
set speed 0
set size 10
set spook-zone 15
set color blue
]
create-boats 1
[ set shape "boat"
set color yellow
set max-speed .2
set max-turn 1
setxy 0 0
rt random 360
jump world-width * .4
rt random 360
set whale one-of whales
set safe-distance 30
set safe-range 10
set size 10
set speed 0
set accel .02
pd
]
end
to go
every .01 [
ask whales
[ ;; whale meanders...
set speed speed + .02 - random-float .04
set speed (min list (max list speed 0 ) .1)
let turn 5 * (.2 - speed)
rt turn - random-float (turn * 2)
jump speed
let boat one-of boats
if distance boat < spook-zone
[ let attack-heading 180 + towards boat
let heading-diff subtract-headings attack-heading heading
rt .5 * heading-diff
]
;; rarely, whale reverses course
if random 20000 < 1 [ rt (165 + random-float 30) ]
]
ask boats
[
; 1. calculate goal position and heading
; 2. Set heading as needed
; 3. Move boat.
; Step 1 uses some trigonometry trickery.
;; assumes "whale" is boats-owned, and already set to the whale agent to track
;; assumes "pwx" and "pwy" are boats-owned
;; assumes safe-distance is boats-owned and already set to some number of units
set wx [ xcor ] of whale
set wy [ ycor ] of whale
set wh [ heading ] of whale
set wdx [ dx ] of whale
set wdy [ dy ] of whale
set ws [ speed ] of whale
;; goal point is a point that is a safe-distance away and
;; 90 degrees clockwise from whale heading
;; goal heading is the same as the whale heading
;; trig trick: the point ( xcor + dx ) ( ycor + dy) is 1 unit directly ahead of the agent
;; and (xcor + dy) (ycor - dx) ) is a point 1 unit away and 90 degrees clockwise!
;; if we multiply dx and dy by the safe-distance, we get just the point we need,
;; the goal point.
set gx wx + wdy * safe-distance
set gy wy - wdx * safe-distance
ask patch gx gy [ set pcolor gray ]
;; and the goal heading is the whale heading
set gh wh
;; Now, step 2 is the tricky one:
;; 2a. if boat is more than desired maximum distance away from whale, turn boat (at safe turning speed), if needed, toward goal point*, but also tend to keep boat aligned with whale
;; 2b if boat is less than safe distance away, turn boat away from whale, away from whale direction of travel, but toward goal point, if possible (generally, desired avoidence heading will be perpendicular to heading toward whale, direction depends on whale direction and goal direction.
;; 2c. if boat is near goal point, maintain heading to heading of whale
;; This is all done with subtract-headings and some other trickery
;; turn boat towards a goal point,
;; adopt a goal heading when you get there.
;; gx is goal xcor
;; gy is goal ycor
;; gh is goal heading
;; max-change is the maximum degrees of change in heading allowed per turn
;; heading-diff is the difference bewteen our heading and some desired heading
;; initialize to 0
let heading-diff 0
;; if we are near the goal point...
let goal-dist sqrt (gx - xcor) (gy - ycor)
ifelse goal-dist < safe-range
[ ;; desired heading is the goal heading
set heading-diff subtract-headings gh heading
]
[ ;; otherwise, desired heading is towards the goal point
set heading-diff subtract-headings (towardsxy gx gy) heading
]
;; if any change is needed...
if abs heading-diff != 0
[ ;; turn in the direction of the difference
;; either the amount of the difference, or the max-change amount
;; in that direction, whichever is smaller
let turn-amount (min (list max (list heading-diff (- max-turn)) max-turn))
;; change heading by that amount
rt turn-amount
;; (remember, right-turn with negative angle is a left turn!)
]
; Step 3. Simplest of all.
;; though, here, there's some extra stuff added
;; to try to slow down the boat when near the station-keeping position
;; and to try to match the whale speed, without just
;; assigning ws to speed.
;; move the boat
ifelse goal-dist < safe-range
[ ;;
if abs (speed - ws) > 5 * accel
[ ifelse speed < ws [ set speed speed + accel ]
[ set speed speed - accel if speed < 0 [ set speed 0 ] ]
]
]
[ if speed < max-speed
[ set speed speed + accel
]
]
jump speed
]
]
end
to-report [ #a #b ]
report #a * #a + #b * #b
end
@#$#@#$#@
GRAPHICS-WINDOW
10
50
623
534
100
75
3.0
1
10
1
1
1
0
1
1
1
-100
100
-75
75
0
0
1
ticks
CC-WINDOW
5
548
632
643
Command Center
0
BUTTON
10
10
65
43
NIL
setup
NIL
1
T
OBSERVER
NIL
NIL
NIL
NIL
BUTTON
75
10
130
43
NIL
go
T
1
T
OBSERVER
NIL
NIL
NIL
NIL
TEXTBOX
140
10
295
40
Gray trace is the goal position\nYellow trace is the boat's path.\n
11
0.0
1
BUTTON
550
10
620
43
clear-traces
cp cd
NIL
1
T
OBSERVER
NIL
NIL
NIL
NIL
@#$#@#$#@
WHAT IS IT?
-----------
An example of another kind of following or flocking model.
In this case, we have a whale, and a whale-watch boat.
The whale generally ambles along, unless it feels spooked by a whale-watch boat, in which case it turns suddenly to head away from the vessel.
The boat always wants to get in the best whale watching position-- some safe distance of the right side of the whale.
Some simple (and rather dumb) rules make the boat attempt to maintain that position.
The boat isn't very good at matching speed, and doesn't know how to simply slow down, so when it gets too far ahead, it tends to loop around to try to regain the correct position, often spooking the whale in the process.
ACKNOWLEDGEMENTS
----------------
Inspired by questions posed to the netlogo-users yahoo group.
COPYRIGHT
---------
Copyright © 2007 James P. Steiner
@#$#@#$#@
default
true
0
Polygon -7500403 true true 150 5 40 250 150 205 260 250
boat
true
0
Polygon -7500403 true true 105 225 105 105 120 60 135 30 150 0 165 30 180 60 195 105 195 225 180 300 150 300 120 300
whale
true
0
Polygon -7500403 true true 135 315 150 300 165 315 225 315 195 285 165 285 150 255 135 285 105 285 75 315
Polygon -7500403 true true 150 180 120 135 120 45 135 0 165 0 180 45 180 135
@#$#@#$#@
NetLogo 4.0
@#$#@#$#@
@#$#@#$#@
@#$#@#$#@
@#$#@#$#@
@#$#@#$#@
default
0.0
-0.2 0 0.0 1.0
0.0 1 1.0 0.0
0.2 0 0.0 1.0
link direction
true
0
Line -7500403 true 150 150 90 180
Line -7500403 true 150 150 210 180
@#$#@#$#@