Automation and
PID Control
Watch
multiple intelligent agent simulation platform
Download
Introducing NetLogo
"INTERFACE"
"CODE"
Introducing NetLogo
The "INTERFACE" consists of a UI (switches, buttons, etc.) and a "gridworld" where squares are called "patches" and a command center where we can interact directly with the underlying code.
Let's Implement the
Soccer Field Example
- Start NetLogo
- Resize the interface
- Write code by stepwise refinement
Stepwise Refinement
Simulation
Go - code that runs the thing
Setup - code that takes care of preliminaries
Draw the soccer field
Create the agent
Compute the ERROR
Compute the COMMAND
Set system parameters
to setup
draw_field
create_agent
set_system_parameters
end
to go
print "ERROR COMPUTED"
print "COMMAND GENERATED AND EXECUTED"
end
to draw_field
print "FIELD DRAWN"
end
to create_agent
print "AGENT CREATED"
end
to set_system_parameters
print "SYSTEM PARAMETERS SET"
end
Stepwise Refinement
Change
Settings
For
Soccer
Field
Example
Draw the Field
Draw the Field
Code
to draw_field
ca
ask patches [if pycor = max-pycor [set pcolor white]]
ask patches [if pycor = min-pycor [set pcolor white]]
ask patches [if pxcor = max-pxcor [set pcolor white]]
ask patches [if pxcor = min-pxcor [set pcolor white]]
ask patches [if pxcor = max-pxcor / 2 [set pcolor white]]
print "FIELD DRAWN"
end
Code
to create_agent
crt 1 [ ;create one agent with these properties
set shape "circle" ;make it a circle
set size 2 ;not so big
set heading 90 ;pointed to the right
]
print "AGENT CREATED"
end
So Far
Example 1
NetLogo Info
commands can be given to patches, turtles (agents), or the "world"
we say we are in "turtle context" or "observer context" or "patch context"
in observer context you can "reach" patches or turtles by saying
ask agentset [command(s)]
where agentset is either turtles or patches
In the interface, we can designate a procedure's context.
NetLogo Set Procedure/Button Context
Code
globals [target err]
First line of NetLogo code
declares "GLOBAL" (i.e., know everywhere) names
Code
to go
set err target - xcor
type "err = " type err type " "
print "ERROR COMPUTED"
print "COMMAND COMPUTED AND EXECUTED"
end
set varname expression
sets value of varname to expression (no "=")
type value
outputs value in command center w/o CRLF
print value
outputs value in command center w CRLF
Code
to go
set err target - xcor
type "err = " type err type " "
print "ERROR COMPUTED"
fd 0.1 * err
print "COMMAND COMPUTED AND EXECUTED"
end
fd expression
turtle moves forward number of spaces equal to value of expression
PLANT
TARGET
POSITION
E
Kp
So Far
Add a few bells and whistles
add monitor for err on interface
add slider so we can set target
have to remove target from globals and set system parameters
let's make draw_field use target rather than hard-coding 100/2.
globals [err]
to setup
draw_field
create_agent
set_system_parameters
end
to go
set err target - xcor
type "err = " type err type " "
print "ERROR COMPUTED"
fd 0.1 * err
print "COMMAND COMPUTED AND EXECUTED"
end
to draw_field
ca
ask patches [if pycor = max-pycor [set pcolor white]]
ask patches [if pycor = min-pycor [set pcolor white]]
ask patches [if pxcor = max-pxcor [set pcolor white]]
ask patches [if pxcor = min-pxcor [set pcolor white]]
ask patches [if pxcor = target [set pcolor white]]
print "FIELD DRAWN"
end
to create_agent
crt 1 [
set shape "circle"
set size 2
set heading 90
pd
]
print "AGENT CREATED"
end
to set_system_parameters
set target 50
print "SYSTEM PARAMETERS SET"
end
start the agent out with its "pen" down
So Far
DRONE
Drone 0
- Reconfigure interface with 0,0 at lower left (100x100, patch size 5, nowrap vertical)
- create empty setup and go procedures
- create empty create agent, draw world, set parameter procedures
- create slider for target
- create monitor for err
- fill in a few details
globals [err]
to setup
ca
create_agent
set_system_parameters
draw_world
end
to go
print "COMPUTING ERROR"
print "COMPUTING COMMAND"
end
to create_agent
crt 1 [
set shape "circle"
set size 2
]
print "AGENT CREATED"
end
to set_system_parameters
print "SYSTEM PARAMETERS SET"
end
to draw_world
ask patches [if pycor = target [set pcolor yellow]]
end
Drone 0
Drone
Assume 100 revolutions per minute (RPM) is hovering.
Faster ascending, slower descending.
speed_vert = (prop_speed - 100) / 10
prop_speed = k_p * err
Prop Speed
TARGET
POSITION
E
Kp
Drone 1.0
to go
print "COMPUTING ERROR"
set err target - ycor
print "COMPUTING COMMAND"
let prop_speed k_p * err
let speed_vert (prop_speed - 100) / 10
fd speed_vert
end
Drone Tweaks
globals [err]
to setup
ca
create_agent
set_system_parameters
draw_world
end
to go
print "COMPUTING ERROR"
set err target - ycor
print "COMPUTING COMMAND"
let prop_speed k_p * err
let speed_vert (prop_speed - 100) / 10
;fd speed_vert
setxy xcor + 1 ycor + speed_vert
end
to create_agent
crt 1 [
set shape "circle"
set size 2
set heading 0
pd
set pen-size 3
]
print "AGENT CREATED"
end
to set_system_parameters
print "SYSTEM PARAMETERS SET"
end
to draw_world
ask patches [if pycor = target [set pcolor yellow]]
end
Make "time" flow left to right (16,17)
Let's put pen down so we see the trace (25) and make it thicker (26)
Drone 2.0
Drone 3.0
Change k_p slider to -100 to +100 (interface)
Add a "governor" so drone does not fly higher than the sky or lower than the ground. (17-22)
Add an "explode and die" procedure for when the drone hits the ground. (50-56)
globals [err]
to setup
ca
create_agent
set_system_parameters
draw_world
end
to go
print "COMPUTING ERROR"
set err target - ycor
print "COMPUTING COMMAND"
let prop_speed k_p * err
let speed_vert (prop_speed - 100) / 10
if (ycor + speed_vert) > max-pycor [ ;blasting through sky
set speed_vert max-pycor - pycor
]
if (ycor + speed_vert) < min-pycor [ ;digging into earth
set speed_vert min-pycor - ycor
]
;fd speed_vert
setxy xcor + 1 ycor + speed_vert
;die if you hit the ground
if ycor = min-pycor [explode_and_die]
end
to create_agent
crt 1 [
set shape "circle"
set size 2
set heading 0
pd
set pen-size 3
]
print "AGENT CREATED"
end
to set_system_parameters
print "SYSTEM PARAMETERS SET"
end
to draw_world
ask patches [if pycor = target [set pcolor yellow]]
end
to explode_and_die
set color red
set size 20 wait 0.2
set color yellow
set size 40 wait 0.2
die
end
Automation: turn it on and it runs by itself
Pay Attention to Future
Derivative as Current Rate of Change
Prop Speed
TARGET
POSITION
E
Kp
Kd
Drone 4.0
Create k_d slider (interface)
Add global variable last_err and delta_err (1). Include them in error computations (12-14)
Add Kd term to command computation. (17)
globals [err last_err delta_err]
to setup
ca
create_agent
set_system_parameters
draw_world
end
to go
print "COMPUTING ERROR"
set last_err err ;remember the error from last round
set err target - ycor
set delta_err err - last_err
print "COMPUTING COMMAND"
let prop_speed k_p * err + k_d * delta_err
let speed_vert (prop_speed - 100) / 10
if (ycor + speed_vert) > max-pycor [ ;blasting through sky
set speed_vert max-pycor - pycor
]
if (ycor + speed_vert) < min-pycor [ ;digging into earth
set speed_vert min-pycor - ycor
]
;fd speed_vert
setxy xcor + 1 ycor + speed_vert
;die if you hit the ground
if ycor = min-pycor [explode_and_die]
end
to create_agent
crt 1 [
set shape "circle"
set size 2
set heading 0
pd
set pen-size 3
]
print "AGENT CREATED"
end
to set_system_parameters
print "SYSTEM PARAMETERS SET"
end
to draw_world
ask patches [if pycor = target [set pcolor yellow]]
end
to explode_and_die
set color red set size 20 wait 0.2 set color yellow set size 40 wait 0.2 die
end
Add DERIVATIVE Control
Pay Attention to Past
Integral as Cumulative Error
Prop Speed
TARGET
POSITION
E
Kp
Kd
Ki
Drone 5.0
Create k_i slider (interface)
Add global variable cum_err and time_elapsed (1). Include them in error computations (12-14)
Add I term to command computation. (17)
globals [err last_err delta_err cum_error elapsed_time]
to setup
ca
create_agent
set_system_parameters
draw_world
end
to go
print "COMPUTING ERROR"
set last_err err ;remember the error from last round
set err target - ycor
set delta_err err - last_err
set cum_error cum_error + err
set elapsed_time elapsed_time + 1
print "COMPUTING COMMAND"
let prop_speed k_p * err + k_d * delta_err + k_i * cum_error
let speed_vert (prop_speed - 100) / 10
if (ycor + speed_vert) > max-pycor [ ;blasting through sky
set speed_vert max-pycor - pycor
]
if (ycor + speed_vert) < min-pycor [ ;digging into earth
set speed_vert min-pycor - ycor
]
;fd speed_vert
setxy xcor + 1 ycor + speed_vert
;die if you hit the ground
if ycor = min-pycor [explode_and_die]
end
to create_agent
crt 1 [
set shape "circle"
set size 2
set heading 0
pd
set pen-size 3
]
print "AGENT CREATED"
end
to set_system_parameters
set cum_error 0
set elapsed_time 0
print "SYSTEM PARAMETERS SET"
end
to draw_world
ask patches [if pycor = target [set pcolor yellow]]
end
to explode_and_die
set color red set size 20 wait 0.2 set color yellow set size 40 wait 0.2 die
end
Add INTEGRAL Control
Drone 6.0
x (interface)
x(12-14)
x. (17)
globals [err last_err delta_err cum_error elapsed_time]
extensions [sound]
to setup
ca
create_agent
set_system_parameters
draw_world
end
to go
;print "COMPUTING ERROR"
set last_err err ;remember the error from last round
set err target - ycor
set delta_err err - last_err
set cum_error cum_error + err
set elapsed_time elapsed_time + 1
if sound_on [sound:play-note "TRUMPET" 60 - ceiling err 64 - ceiling err 0.25]
;if sound_on [sound:play-note "gunshot" 60 - ceiling err 64 - ceiling err 2]
;print "COMPUTING COMMAND"
let prop_speed k_p * err + k_d * delta_err + k_i * cum_error
let speed_vert (prop_speed - 100) / 10
if (ycor + speed_vert) > max-pycor [ ;blasting through sky
set speed_vert max-pycor - pycor
]
if (ycor + speed_vert) < min-pycor [ ;digging into earth
set speed_vert min-pycor - ycor
]
;fd speed_vert
setxy xcor + 1 ycor + speed_vert
;die if you hit the ground
if ycor = min-pycor [explode_and_die]
end
to create_agent
crt 1 [
set shape "circle"
set size 2
set heading 0
pd
set pen-size 1
]
;print "AGENT CREATED"
end
to set_system_parameters
set cum_error 0
set elapsed_time 0
;print "SYSTEM PARAMETERS SET"
end
to draw_world
ask patches [if pycor = target [set pcolor yellow]]
end
to explode_and_die
if sound_on [sound:play-note "gunshot" 60 127 2]
sound:play-drum "Acoustic Bass Drum" 127
set color red set size 20 wait 0.2 set color yellow set size 40 wait 0.2 die
end
More Tweaks
Craziness
ISCHOOL VISUAL IDENTITY
#002554
#fed141
#007396
#382F2D
#3eb1c8
#f9423a
#C8102E
NetLogo 0.0
globals [err delta_error cum_error abs_cum_error CE elapsed_time max_rpm max_vy]
turtles-own [vy vx ay ax]
extensions [sound]
to setup
; clear all and reset global values
ca
set err 0
set delta_error 0
set cum_error 0
; create an agent and set initial properties
crt 1 [
set shape "ufo side"
set size 5
set heading 0
setxy min-pxcor + 1 min-pycor + 1
set ay 0 set vy 0 set ax 0 set vx 0
pd ]
; draw target elevation line
ask patches [if pycor = targety [set pcolor white]]
end
to go
if not any? turtles [ stop ]
ask turtles [
; time passes and drone moves to the right
; set xcor xcor + 0.1
set elapsed_time elapsed_time + 1
; compute error values
let old_error err
set err targety - ycor
set delta_error old_error - err
set cum_error cum_error + err
set abs_cum_error abs_cum_error + abs err
ifelse Use_Abs_Cum
[ set CE abs_cum_error ]
[ set CE cum_error ]
sound:play-note "TRUMPET" 60 - ceiling err 64 - ceiling err 0.25
; run the PID control equation
set vy (((Kp * err + Kd * delta_error + Ki * CE ) - 100) / 100)
; compute change in y (vertical) position
let deltay 0
if vy < 0 [ ; drone is falling
set color red
set deltay max list vy (min-pycor - ycor) ]
if vy > 0 [ ; drone is rising
set color green
set deltay min list vy (max-pycor - ycor) ]
if vy = 0 [ ; drone is hovering
set color blue]
setxy xcor + 0.3 ycor + deltay + wind
if ycor <= min-pycor [set size 20 wait 0.2 die]
]
end
to ZeroKd
set Kd 0
end
to ZeroKi
set Ki 0
end
to ZeroKp
set Kp 0
end
to-report wind
if windy[
report (windspeed - random (2 * windspeed)) / 10]
report 0
end
PID in NetLogo
By Dan Ryan
PID in NetLogo
- 177