In this notebook we demonstrate how to define a crosswalk with pedestrians using AutomotiveDrivingModels. The last part also hows how to save a video from a simulation.
In [1]:
using AutomotiveDrivingModels
# All the functions related to visualization
using AutoViz
In this second example we demonstrate how to define a crosswalk area as well as a pedestrian agent type.
We define a new concrete type that will contain the roadway (where cars drive) and the crosswalk definition which is just a regular lane.
In [2]:
struct CrosswalkEnv
roadway::Roadway
crosswalk::Lane
end
The crosswalk lane consists of a straight road segment perpendicular to the road. We will define the roadway just as a straight road.
In [3]:
# geometry parameters
roadway_length = 50.
crosswalk_length = 20.
crosswalk_width = 6.0
crosswalk_pos = roadway_length/2
# Generate straight roadway of length roadway_length with 2 lanes
roadway = gen_straight_roadway(2, roadway_length)
# generate the crosswalk
n_samples = 2 # for curve generation
crosswalk = Lane(LaneTag(2,1), gen_straight_curve(VecE2(crosswalk_pos, -crosswalk_length/2),
VecE2(crosswalk_pos, crosswalk_length/2),
n_samples), width = crosswalk_width)
cw_segment = RoadSegment(2, [crosswalk])
push!(roadway.segments, cw_segment) # append it to the roadway
# initialize crosswalk environment
env = CrosswalkEnv(roadway, crosswalk);
Render the crosswalk
We will define a new method to render this new environment. The roadway part is just rendered regularly, we add specific instuction for the crossswalk part that will display the white stripes.
In [4]:
function AutoViz.render!(rendermodel::RenderModel, env::CrosswalkEnv)
roadway = gen_straight_roadway(2, roadway_length) # only render the road and not the crosswalk
render!(rendermodel, roadway)
# render crosswalk
curve = env.crosswalk.curve
n = length(curve)
pts = Array{Float64}(undef, 2, n)
for (i,pt) in enumerate(curve)
pts[1,i] = pt.pos.x
pts[2,i] = pt.pos.y
end
add_instruction!(rendermodel, render_dashed_line, (pts, colorant"white", env.crosswalk.width, 1.0, 1.0, 0.0, Cairo.CAIRO_LINE_CAP_BUTT))
return rendermodel
end
In [5]:
cam = FitToContentCamera(0.0)
render(Scene(), env, cam = cam)
Out[5]:
Cars will be navigating in the roadway just as before. For the pedestrian we can define a new vehicle definition where we specify the size of the bounding box represented by the pedestrian.
In [6]:
# field of the VehicleDef type
fieldnames(VehicleDef)
Out[6]:
In [7]:
# Agent.Class is from AutomotiveDrivingModels
const PEDESTRIAN_DEF = VehicleDef(AgentClass.PEDESTRIAN, 1.0, 1.0)
Out[7]:
In [8]:
# Car definition
car_initial_state = VehicleState(VecSE2(5.0, 0., 0.), roadway.segments[1].lanes[1],roadway, 8.0)
car = Vehicle(car_initial_state, VehicleDef(), 1)
# Pedestrian definition using our new Vehicle definition
ped_initial_state = VehicleState(VecSE2(+24.5,-7.0,π/2), env.crosswalk, roadway, 0.5)
ped = Vehicle(ped_initial_state, PEDESTRIAN_DEF, 2)
scene = Scene()
push!(scene, car)
push!(scene, ped)
# visualize the initial state
render(scene, env, cam=cam)
Out[8]:
In [9]:
mutable struct LinearDriver <: DriverModel{LaneFollowingAccel}
a::LaneFollowingAccel
p::Float64 # confidence on the pedestrian intention
k::Float64 # gain
end
In [10]:
function AutomotiveDrivingModels.get_name(model::LinearDriver)
return "linear driver"
end
Base.rand(model::LinearDriver) = model.a
function AutomotiveDrivingModels.observe!(model::LinearDriver, scene::EntityFrame{VehicleState, VehicleDef, Int64}, roadway::Roadway, egoid::Int)
model.a = LaneFollowingAccel(model.k*model.p)
# change the confidence based on some policy
# you can get the position of the pedestrian from the scene
model.p = 100.0
end
In [11]:
timestep = 0.1
# reset the initial scene
# Car definition
car_initial_state = VehicleState(VecSE2(5.0, 0., 0.), roadway.segments[1].lanes[1],roadway, 8.0)
car = Vehicle(car_initial_state, VehicleDef(), 1)
# Pedestrian definition using our new Vehicle definition
ped_initial_state = VehicleState(VecSE2(+24.5,-7.0,π/2), env.crosswalk, roadway, 0.5)
ped = Vehicle(ped_initial_state, PEDESTRIAN_DEF, 2)
scene = Scene()
push!(scene, car)
push!(scene, ped)
# define a model for each entities present in the scene
models = Dict{Int, DriverModel}()
ego_id = 1
ped_id = 2
# Constant speed model
models[ego_id] = LinearDriver(LaneFollowingAccel(0.0), 20.0, -0.02)
models[ped_id] = IntelligentDriverModel(v_des=1.0) # dumb model
nticks = 50
rec = SceneRecord(nticks+1, timestep)
# execute the simulation
simulate!(rec, scene, roadway, models, nticks)
render(rec[0], env, cam=cam)
Out[11]:
In [12]:
using Reel
In [13]:
function animate_record(rec::SceneRecord,dt::Float64, env::CrosswalkEnv, cam=FitToContentCamera(0.0))
duration =rec.nframes*dt::Float64
fps = Int(1/dt)
function render_rec(t, dt)
frame_index = Int(floor(t/dt)) + 1
return render(rec[frame_index-nframes(rec)], env, cam=cam)
end
return duration, fps, render_rec
end
Out[13]:
In [14]:
duration, fps, render_hist = animate_record(rec, timestep, env)
film = roll(render_hist, fps = fps, duration = duration)
Out[14]:
In [ ]: