whale-watch


Information

Created with NetLogo version NetLogo 4.0
Running with NetLogoLite.jar version 404.



Procedures

NetLogo Version: NetLogo 4.0

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
          
     

                    


Download Link

View or download the complete model file (to download: right-click, save-link-as):
-- Download whale-watch --