Jimshidi, Chapter14, Mine Detector

Jimshidi, Chapter14, Mine Detector preview image

1 collaborator

Default-person John DeHart (Author)

Tags

(This model has yet to be categorized with any tags)
Visible to everyone | Changeable by everyone
Model was written in NetLogo 6.2.0 • Viewed 21 times • Downloaded 0 times • Run 0 times
Download the 'Jimshidi, Chapter14, Mine Detector' modelDownload this modelEmbed this model

Do you have questions or comments about this model? Ask them here! (You'll first need to log in.)


V3x - Added msg queue hold (line 301)
V4x - Improved random swarm calls to closest members of breed

WHAT IS IT - Systems of System Demo Model - ASE6102 Team6

System of Systems model for ASE6102. Based on the System of Systems described in Jamshidi, 1st ed, Ch 14, System of autonomous rovers and their applications. The enviornemtn contains multiple mines, a single base robot (although multiple may be added) and multiple swarm robots. Mines can be disarmed by a team of swarm robots. When all the mines are disarrmed the model stops running.

HOW IT WORKS

There are three types of agents: mines, base robots, and swarm robots.

Swarm robots have sensors which can detect a mine mine within their range and field of view (FoV) but in order to disarm a mine a group of swarm robots of a predetermined size must physically contact the mine.

Base Robots can only recieve notification from any swarm robot that a mine has been detected and the mines X,Y location. The base robot will then randomly select the required number of swarm robots to disarm the mine from the curently foraging robots, assign the a leader bot (the bot that found the mine), and direct them to the detected mines location for disarming.

Mines are static objects that are targets for disamring for the swarm robots. The mines have a XY location, a trigger radius, and a blast radius.

Base Robots and Swarm Robots work together: Swarm robots find mines then send messages to the base robot describing where the mines are located. Swarm robots perforrm a random walk during foragin and periodically get messages from base robots containing information about the location of mines that have been found by other swarm robots. If the swarm robot is not currently detecting within its sensor or is in the process of disarming a mine the bot travels to target mines identified by the base robot in support of the bot teams disarming proceedure.

Note: this is roughly similar to an example in Ch14 with the exception of identifying dynamic theats and utilizing sensors both of which are deleted (dont think that I didnt want to add them :).

The idea here is to extract the overall behavoirs and performance attributes in support of development of our teams artifacts for the presentation. Without this little model a lot of necessary information would have been overlooked during the block diagram building.

SYSTEM STATES

BASE ROBOT: In this model the base robot is simply a communcations tool utilized by swarm robots in support of mine disarming.

The base robot has two basic states:

ON (green) - The base robot is monitoring message queue. TX (blink-black) - The base robot has recieved a message, selected the supporting swarm robots, and is tramsitting data to the support robots. WAITING - Msg in queue waiting on enough foraging swarm bots to deliver

Data Recieved: detecingrobotId, targetX, targetY Data Transmitted: leadSwarmBotId, targetId, target_Vector(X,Y)

SWARM ROBOTS: The swarm robot has several states (and state colors) described below:

Foraging (blue) - In this state the swarm robot performs a random walk about the model looking for mines. (Although there should be...) No communcation to the outside world is happening when in the foraging state prior to finding a mine. During this state the swarm robot is using its sensor to look for mines where the sensor has a range and a field of view attribute. When a mine is found the swarm robot broadcasts the location to the base robots.

HOMING/WAITING (yellow) - When a swarm robot happens upon a mine that is idetified within its field of view the robot enters the homing/waiting state. During this state the robot is identified as a leader for the other swarm robots need for disarming and starts a homing procedure to slowly move the robot direclty next the edge of the mine to be disarmed. A timeout is set to ensure that if the disarming support robots do not arrive the system can reorder a new set of robots needed to disarm the mine.

SCENT-FOLLOWING (orange): Once a robot has found a mine and has been desginated a leader the base robot assignes a number of current foraging swarm robots to the disarming team and sets their state scent-following (as in ant swarming). The lead robot, mine X cooridiante, mine Y corrodinate, and the XY vector to the mine is sent to each of the selected swarm robots. During the robots travel to the identified mines location the robots sensor continues to look for mines (if we roll over a mine we blow up). If a mine is detected simple evacive measures are taken to no travel over the mine while continueing to track the vector to the mine to be disamred.

Data Recieved: leaderid, targetid, targetx, targety, target_vector(x,y) Data Transmitted: detecingrobotid, targetX, targetY

MINES: The mines have several states noted below:

HIDDEN (black) - Each mine is intiaized in the hidden state. FOUND (red) - When a swarm robot finds a mine the mines state is changed to Found. DISARMED (deleted from world) - When the swarm is able to disarm the mine the mines state is Disabled and the mine is asked to die removing it from the game.

TIMEOUTS: During the simualtion there are conditions that occure resulting in swarm robots that may become stuck or zombies. In order to ensure that each game finished the following timeout states are provided:

DISARMING: If a swarm robot is in the diarming state and the supporting robots are not able to reach the mines location within a resonable time the robot will perform a manuver to safely move away from the mine and set its status to Foraging to resume looking for mines. The mine status will be set to hidden but now the mine is colored white to idicate that it has been found one but was not disarmed.

FOUND: If a mine is found but not disarmed within the timeout limit its status will be changed back to hidden and its color will change to wite to idicate that it has been found one but was not disarmed.

FOLLOWING_SCENT: If a robot has been following scent too long (Zombie Robot) a timeout will occure and its status will be set back to foraging.

WAITING: If a swarm robot that has found a mine has been in the Homing/Waiting state too long a timeout will occure and its state will be set back to foraging.

OBSTACLE AVOIDANCE (currently only a sub-state of 'Following-Scent')

During the running of the models it became apparent particularly when the swarm robots are in the 'follow-scent' state that some sort of obsticle avoidance and decision making is necessary.

For instance when in the 'follow-scent' state the helper swarmBot travels a path straight to the mine where the leader is waiting. If another mine is within the path of the straight line between the helper bot and the leader what to do???

In order to accomidate this scenario the helper swarmBot's sensor remains on and when a mine (other than its target mine) is detected an avoidance manuver is executed with the bot being reoriented toward its target mine after the manuver.

For more fun a trigger radius is provided to assess the capability of the obstacle avoidance algorithm. If a swarmBot is located within the trigger radius of any mine the mine will detonate and kill any swarmBot within its blast radius. Any mines within the blast radius are also killed but the do not detonate.

Currently there are two fairly simple avoidance algorithms with the second being slight more complex and which can be turned on by setting 'obs-detection' to 'ON'. This second algorithm will show the path history of each bot for review.

Base Robots Movments:

The user can move the base robot with the buttons in the upper right side of the screen. Motion is limited to a single base robot. This fuction is intended to be a part of a future behavior related to limited communcaitons range assesments.

HOW TO USE IT

The model allows users to specify the number of mines, number of swarm robots, and the number of swarm robots necessary to disarm a mine, a swarmBots sensor range, and sensor field of view angle. The base robot is in the middle of the environment (xcor=0, ycor=0) and all of the swarm robot agents start there. Mines are randomly scattered around the environment.

Mines are circular black & white blobs, the base robot a green square shape, swarm robots are blue (standard turtle shape) when foraging, orange when following scent, yellow when homing/waiting on support robots, and red when they are disarming.

When the model starts running, detectors (blue) leave the base robot area, each randomly searching for a mine. When a swarm robot sensor detects a mine it send the base robot the X,Y corrdinates and its name. The base robot selects support robots (at random) and sends them a message about the mine's location and the robot that found the mine. The support robots (orange) then travel to the mine to be disarmed while continuing to look for mines so that can avoid the trigger-range of other mines (boom!!!).

When the required number of support robots reach the mine to be disarmed the robots turn red and the mine symbol disappears from the visual environment, the leader and the support robots then return to foraging (turning blue) for other hidden mines.

Players can vary paramters to determine how quickly a number of swarm robots for a given disarm group size can clean the mine field.

THINGS TO NOTICE

Object Detection and Obsticle Avoidance: When working with the simulation model it becomes appartent that object detection and the associated algorithms for addressing these objects are very imoportant and become the most complex part of the SoS. A good strategy would be to utilize the base robot as the processing power for any complex object detection/avoidance algos as the swarmBots are to remain simple in nature due to the quantities. Well beyond the scope of this class a full study of the detection and avoidance algos would be super fun particuarly when using this super easy to code tool (netlogo). There is a 'R' plug-in for NetLogo which would allow easier introduction of maching learning tools... keep this in mine for future efforts.

FURTHER INFORMATION

jdehart@gatech.edu john@int64.tech

CREDITS AND REFERENCES

1- The origination of this model and the agent messaging script (messaging.nls) was developed as part of the tutorial for NL Boris - see www.agent-domain.org for additional tutorials and updates. 2 - Based on the model described in Chapter 14 of Jamshidi - System of autonomous rovers and their applications. 3 - The supporint script sxl-utils.nls was devloped by S.C.Lynch (http://s573859921.websitehome.co.uk/pub/netlogo/cogsnltools.htm#utils)

Comments and Questions

Please start the discussion about this model! (You'll first need to log in.)

Click to Run Model

;; ASE6102 System of Systems
;; Swarm Robotics - Demonstration Model
;; Based on system described in Jamshidi, Ch 14, 1st ed.
;; Team6


;;-----------------------------------
;; declarations
;;-----------------------------------

__includes ;; Moved to end of code since includes do not work with commons
[ ;;"messaging.nls"     ; handles agent messaging
  ;;"sxl-utils.nls"     ; small set of NetLogo utilities
]

globals
[ mine-active-color
  mine-deactive-color
  target_X                       ; xcoord of target mine
  target_Y                       ; ycoord of target mine
  swarmTeamSize                  ; number of robots in a swarm team
  disarm_Count                   ; count for number of disarming swarmRobots
  target_mine                    ; name of mine to help with
  leader                         ; lead swarmRobot (he who(m?) found the mine)
  closestSwarmMembers
]

frags-own [
  dim             ; used for fading particles
]

;directed-link-breed [red-links red-link]

;;-----------------------------------
;; breed data
;;-----------------------------------
breed [sensors sensor]
sensors-own
[ status          ;; off/monitoring/detecting
  name
]

breed [swarmRobots swarmRobot]
swarmRobots-own
[ status          ;; foraging/following_scent/waiting/homing/disarming
  target          ;; target mine
  leadSwarmBot    ;; lead swarmRobot
  start-time
  time-taken
  name
]

breed [baseRobots baseRobot]
baseRobots-own
[ status          ;; on/tx
  name
]

breed [mines mine]
mines-own
[ status          ;; hidden/found/disarmed[die]
  start-time
  time-taken
  name
]

breed [dynamicTargets dyanmicTarget]
dynamicTargets-own
[status
 start-time
 time-taken
 name
]

breed [obstacles obstacle]
obstacles-own
[ ob-dia
  ob-color
]

breed [ frags frag ]

turtles-own [
  col             ; sets color of an explosion particle
  x-vel           ; x-velocity
  y-vel           ; y-velocity
  #msgQ          ;; the message queue
  #msg-id        ;; the agent name/id for messaging
]

;;-----------------------------------
;; general
;;-----------------------------------

to setup-turtles
  ask turtles[
    set col 0
    set color 2
  ]
end 

to setup
  clear-all
  setup-globals
  setup-patches
  setup-obsticals
  setup-mines
  setup-swarmRobots
  setup-baseRobots
  setup-sensors
  setup-dynamicTargets
  reset-ticks
end 

to setup-globals
  ;; set globals
  set mine-active-color red
  set mine-deactive-color green
  set swarmTeamSize swarm-teamSize - 1
end 

to setup-patches
  ask patches [set pcolor gray]
end 

to setup-mines
  create-mines no-of-mines
  ask mines
  [ set name (word "mine_" who)
    setxy random-xcor random-ycor
    ;setxy 0 10
    set color black
    set shape "ufo top"
    set status "hidden"
    ask mines
    [
    ifelse (any? obstacles-on patch-here)
      [
        wiggle
      ][
        fd 2
      ]
    ]
  ]
end 

to setup-swarmRobots
  create-swarmRobots no-of-swarmRobots
  ask swarmRobots
  [ set name (word "swarmrobot " who)
    ; make-msgQ (word "swarm_" who)
    setxy 0 0
    set color blue
    set status "foraging"
  ]
end 

to setup-baseRobots
  create-baseRobots no-of-baseRobots
  ask baseRobots
  [ set name (word "base_" who)
    make-msgQ (word "base_" who)
    setxy 0 0
    set color green
    set size 1.5
    ;;set shape "square"
    set status "ON"
  ]
end 

to setup-sensors
  create-sensors 10
  [
    set shape "star"
    set size .5
    set color yellow
    let $n 0  ;; actual number of turtles on this patch
    let $s 0  ;; current number of turtles on a side of square pattern - 1
    set heading 0
    ask patch-here []
    repeat no-of-sensors   ;; number of needed turtles
    [ hatch 1 jump Grid   ;; make one turtle and move
      set $n $n + 1   ;; increment count of curent side
      ask patch-here []
      if $n > $s  ;; if side finished...
      [
        right 90 set $n 0   ;; turn and reset count
        ask patch-here []
        ;; if headed up or down, increment side count
        if heading mod 180 = 0 [ set $s $s + 1
          ]
      ]
    ]
   die
  ]
end 

to setup-dynamicTargets
  create-dynamicTargets no-of-dynamicTargets
  ask dynamicTargets
  [
    setxy random-xcor 20
    set shape "person"
    set size 1
    set color black
  ]
end 

to setup-obsticals
  create-obstacles no-of-obstacles
  ask obstacles
  [
    setxy random-xcor random-ycor
    set shape "square"
    set size random 5
    set col one-of base-colors
  ]
end 

to go
  if ticks > Game_Time_Out [ setup go ]   ;; stop when ticks run high
  if not any? mines [ setup go ]        ;; stop when no mines
  if count swarmRobots < swarm-teamSize [ setup go ] ;; cant disarm mines anymore
  forage-SwarmRobot
  homming
  comms-baseRobots
  following-scent
  ;obs-avoidance
  disarming
  timeOut
  blowup
  ask frags
  [
        fade
  ]
  every reset_Time
  [
    setup
    go
  ]
  tick
end 

to moveForage
  ask swarmRobots
  [
    if status = "foraging"
    [
      wiggle
      forward .1
      ; obs-avoidance
    ]
  ]
end 

to forage-SwarmRobot
  ask swarmRobots
  [
    if status = "foraging"
    [
      ;; look for any mines using the robots sensor
      ifelse any? mines in-cone sensor-range sensor-FoV  ;; [in-cone range fov_angle]
      [
        ;; check to see of the mine is already found and being disarmed
        ask nearest-of mines
        [
          ifelse status != "found"
          [
            set status "found"
            set start-time ticks
            set color red
            ;; update the status of the robot that found the mine
            ask nearest-of swarmRobots
            [
              ;; update status of swarmRobot that has found a mine
              set status "waiting"
              set color yellow
              set target nearest-of mines
              ;;fd 1 ; move forward one... this should be calculated
              face nearest-of mines

              ;; send message to baseRobot with x,y coordinates
              broadcast baseRobots (list ([xcor] of nearest-of mines) ([ycor] of nearest-of mines) nearest-of swarmRobots who)
              ;;ask nearest-of swarmRobots [
                ;create-red-link-to nearest-of baseRobots
                ;show link-with nearest-of baseRobots
              ;]
            ]
          ]
          [
            ;; tell any other robots to move along if they are not waiting
            ;; if they see the mine
            ask swarmRobots
            [
              if status != "waiting" [moveForage]
            ]

          ]
        ]
      ]
      ;; else keep foraging for other mines
      [
        moveForage
      ]
    ]
  ]
end 

to comms-baseRobots
  ;; base robots get told about mines to disarm by swarmRobot and sends helper swarmRobots
  ask baseRobots
    [ if msg-waiting? ;; check for a message [Message = swarmRobot#(mineX, mineY)
      [
        ;; added a queue hold for next bot if two mines are detected at the same time with
        ;; less than the required bots foraging to send to disarm
        ifelse count swarmRobots with [status = "foraging"] < swarm-teamSize - 1
        [
          set color yellow
          if swarmRobots with [status = "scent-following"] != nobody
          [
          set closestSwarmMembers up-to-n-of (swarm-teamSize - 1) swarmRobots with [status = "following_scent"]
          ;show closestSwarmMembers
          ask closestSwarmMembers ;up-to-n-of (swarm-teamSize - 1) swarmRobots with [status = "foraging"]
            [
              right 180
              fd 1
              set status "foraging"
              set color blue
            ]
          ]

        ;; do nothing set
        ]
        [
            set color black
            set status "tx"
            let m get-msg ;; fetch message - clears queue
            let from item 0 m ;; mineX
            let msg  item 1 m ;; mineY
            set target_X   item 0 msg ;; move value to var
            set target_Y   item 1 msg ;; move value to var
            set leader     item 2 msg ;; lead swarm robot name

            ;; set the target mine variable to the mine name
            set target_mine one-of mines with
                  [(xcor = [target_X] of myself) and (ycor = [target_Y] of myself)]

            ;; now ask some others of the swarm to go help with the disarming of the mine
            ;; right now this is random but a good upgrade would be to grab the closest avalible
          set closestSwarmMembers up-to-n-of (swarm-teamSize - 1) swarmRobots with [status = "foraging"]
          ;show closestSwarmMembers
          ask closestSwarmMembers ;up-to-n-of (swarm-teamSize - 1) swarmRobots with [status = "foraging"]
            [
              set status "following_scent"
              set start-time ticks
              set color orange
              set target target_mine
              set leadSwarmBot leader
              facexy target_X target_Y
            ]
          ]
        ]
      ]
end 

to following-scent
  ask swarmRobots with [status = "following_scent"]
  [
    ifelse target != nobody
    [
      ;; either move to target or start disarming the mine
      ifelse distance target > 1
      [
        ifelse any? mines in-cone sensor-range sensor-FoV ;; [in-cone range fov_angle]
        [
          if mines != target
          [
            ifelse obs-detection = true
            [
              obs-avoidance
            ]
            [ ;; Simple obsticle avoidance
              right random 60
              left random 60
              fd .1
            ]

          ]
        ]
        [
          face target ;; important prevents zombie swarmbots
          fd .1
        ]
      ]
      [
        set status "disarming"
        set start-time ticks
        set color red
      ]
    ]
    [
      set status "foraging"
      set color blue
    ]
  ]
end 

to homming
  ;; when a bot finds a mine its at the distance near its sensor range
  ;; need to walk the bot up to the mine and then set bot status to disarming
  ;; need timeout
  ask swarmRobots with [status = "waiting"]
  [
    if target != nobody
    [
      ;; either move to target or start disarming the mine
      ifelse distance target > 1
      [
        face target ;; important prevents zombie swarmbots
        fd .1
        ask baseRobots
        [
          set color green
          set status "ON"
        ]
      ]
      [
        ; start disarming the mine
        set status "disarming"
        set start-time ticks
        set color red
      ]
    ]

  ]
end 

to disarming
  ;; check around the mine and make sure that there are the number of
  ;; required bots then set mine status to disarm and reset bots
  ;; and set bot status to foraging
  ask mines with [status = "found"]
  [
    ;; if the number of bots around the mine is corrent then return the bots to
    ;; foraging and destry the mine
    if (count swarmRobots in-radius 1) >= swarm-teamSize [
      ask swarmRobots in-radius 1 ;; check for bots in a radius around the mine
      [set status "foraging"
       set color blue
      ]
      set status "disarmed"
      ask mines with [status = "disarmed"] [die]
    ]
  ]
end 

to timeOut ;; this is a super important part of the system of systems... no timeout = zombies
  ;; resets a swarmBot that does not get help to a foraging bot
  ;; and idetntifies the mine
  ;; ***need to send this data to the baseRobot as a list of mines
  if mines != nobody[

    ask swarmRobots with [status = "disarming"]
    [
      if target != nobody
      [
        if (ticks - start-time) > Disarm_TimeOut
        [
          right 180
          fd random 10
          set status "foraging"
          set start-time ticks
          set color blue
          ask target [
            set status "hidden"
            set start-time ticks
            set color yellow
          ]

        ]
      ]
    ]

    ask mines with [status = "found"]
    [
      if mines != nobody
      [
        if (ticks - start-time) > Found_TimeOut [
          set status "hidden"
          set start-time ticks
          set size 1
          set color white
        ]
      ]
    ]

    ask swarmRobots with [status = "following_scent"]
    [
      if target != nobody
      [
        if (ticks - start-time) > Follow_Scent_TimeOut [
          set status "foraging"
          set start-time ticks
          set color blue
        ]

      ]
    ]

    ask swarmRobots with [status = "waiting"]
    [
      if target != nobody
      [
        if (ticks - start-time) > Follow_Scent_TimeOut [
          set status "foraging"
          set start-time ticks
          set color blue
        ]

      ]
    ]

  ]
end 

to blowup
  ;; this is fun - if my obsticle avoidance algo does not work well then the system will blow up.
  ask swarmRobots [
    if min-one-of other mines in-radius trigger-radius [distance myself]!= nobody
     [
      if min-one-of mines in-radius trigger-radius [distance myself] != target
        [
          if mines != nobody or swarmRobots != nobody [
            explode
            ask mines in-radius blast-radius [die]
            ask swarmRobots in-radius blast-radius [die]
          ]
        ]
     ]
  ]

  ask baseRobots [
    if min-one-of other mines in-radius trigger-radius [distance myself] != nobody
    [
      if mines != nobody or swarmRobots != nobody [
        explode
        ask baseRobots in-radius blast-radius [die]
        ask mines in-radius blast-radius [die]
        ask swarmRobots in-radius blast-radius [die]
        ]
    ]
  ]
end 


; This is where the explosion is created.
; EXPLODE calls hatch a number of times indicated by the slider FRAGMENTS.

to explode ; turtle procedure
  hatch-frags 10 [
    set dim 0
    rt random 360
    set size blast-radius
    set x-vel (x-vel * .5 + dx + (random-float 2.0) - 1)
    set y-vel (y-vel * .3 + dy + (random-float 2.0) - 1)
    pen-down
  ]
end 

; This function changes the color of a frag.
; Each frag fades its color by an amount proportional to FADE-AMOUNT.

to fade ; frag procedure
  ;set col one-of base-colors
  ;set color (col + 2)
  set dim dim - (10 / 10)
  set color scale-color color dim 5 .5
  ;show col
  if (color < (col - 3.0)) [ die ]
end 

to obs-avoidance
  ;; more complex obstical avoidance but I need to look at this
  ifelse min-one-of mines in-radius 1 [distance myself]!= nobody or min-one-of obstacles in-radius 1 [distance myself]!= nobody
   [face patch-right-and-ahead 90 1 fd 1 repeat 2 [face patch-left-and-ahead 90 1   fd 1] face patch-right-and-ahead 90 1 fd 1]
   [pd fd 1]
end 

to move_up
  ask baseRobots [set heading 0 fd 1]
end 

to move_rt
  ask baseRobots [set heading 90 fd 1]
end 

to move_lt
  ask baseRobots [set heading 270 fd 1]
end 

to move_dn
  ask baseRobots [set heading 180 fd 1]
end 


;; Includes from above

to make-msgQ [#id]
  set #msg-id #id
  set #msgQ []
end 

to-report msg-waiting?
  report (not empty? #msgQ)
end 

to-report get-msg
  let #tmp (first #msgQ)
  set #msgQ (but-first #msgQ)
  report #tmp
end 

to send-msg [#who-to #msg]
  let #who-from self
  ask turtles with [#msg-id = #who-to]
  [ set #msgQ (lput (list #who-from #msg) #msgQ)
  ]
end 

to broadcast [#breed-to #msg]
  let #who-from self
  set #msg (list #who-from #msg)
  ask turtles with [breed = #breed-to]
  [ set #msgQ (lput #msg #msgQ)
  ]
end 

to flush-msgQ [#id]
  set #msgQ []
end 

to flush-all-msgQs
  ask turtles
  [ set #msgQ []
  ]
end 

;; sxl-utils

to wiggle
  right 45 - (random 90)
end 

to-report nearest-of [#breed]
  report min-one-of #breed [distance myself]
end 

to-report nearest-of-xy [#breed #corx #cory]
  report min-one-of #breed [distancexy #corx #cory]
end 

to-report trigger [#prob]
  report (random 1000) < (#prob * 10)
end 

to-report mutate [#val #delta]
  let #mutator (random (#delta * 2 + 1)) - #delta
  report (#val + #mutator)
end 

to-report smooth-value [#last #inc #alpha]
  ;
  ; used in plotting to smooth graph data
  ; #alpha is the smoothing value 0-1
  ; larger #alphas are smoother, 0: no smoothing, 1: no recent value
  ;
  set #alpha (bounds 0 #alpha 1)
  let #new (#alpha * #last + (1 - #alpha) * #inc)
  report #new
end 

to-report bounds [#lo #x #hi]
  ;
  ; return #x bounded by #lo & #hi
  ;
  report (min (list #hi (max (list #lo #x))))
end 

There is only one version of this model, created about 1 month ago by John DeHart.

Attached files

File Type Description Last updated
Jimshidi, Chapter14, Mine Detector.png preview Preview for 'Jimshidi, Chapter14, Mine Detector' about 1 month ago, by John DeHart Download

This model does not have any ancestors.

This model does not have any descendants.