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 @#$#@#$#@