Crosswalk

In this notebook we demonstrate how to define a crosswalk with pedestrians using AutomotiveSimulator. To do this, we define a crosswalk area as well as a pedestrian agent type.

Generate a crosswalk environment

We define a new concrete type that will contain the roadway (where cars drive) and the crosswalk definition which is just a regular lane.

using AutomotiveSimulator
using AutomotiveVisualization
using Random

struct CrosswalkEnv
    roadway::Roadway{Float64}
    crosswalk::Lane{Float64}
end

The crosswalk lane consists of a straight road segment perpendicular to the road. We will define the roadway just as a straight road.

geometry parameters

roadway_length = 50.
crosswalk_length = 20.
crosswalk_width = 6.0
crosswalk_pos = roadway_length/2
25.0

Generate a straight 2-lane roadway and a crosswalk lane

roadway = gen_straight_roadway(2, roadway_length)
crosswalk_start = VecE2(crosswalk_pos, -crosswalk_length/2)
crosswalk_end = VecE2(crosswalk_pos, crosswalk_length/2)
crosswalk_lane = gen_straight_curve(crosswalk_start, crosswalk_end, 2)
crosswalk = Lane(LaneTag(2,1), crosswalk_lane, width = crosswalk_width)
cw_segment = RoadSegment(2, [crosswalk])
push!(roadway.segments, cw_segment) # append it to the roadway
2-element Vector{RoadSegment{Float64}}:
 RoadSegment{Float64}(1, Lane{Float64}[Lane{Float64}(LaneTag(1, 1), CurvePt{Float64}[CurvePt({0.000, 0.000, 0.000}, 0.000, NaN, NaN), CurvePt({50.000, 0.000, 0.000}, 50.000, NaN, NaN)], 3.0, SpeedLimit(-Inf, Inf), LaneBoundary(:broken, :white), LaneBoundary(:solid, :white), LaneConnection{Int64, Float64}[], LaneConnection{Int64, Float64}[]), Lane{Float64}(LaneTag(1, 2), CurvePt{Float64}[CurvePt({0.000, 3.000, 0.000}, 0.000, NaN, NaN), CurvePt({50.000, 3.000, 0.000}, 50.000, NaN, NaN)], 3.0, SpeedLimit(-Inf, Inf), LaneBoundary(:solid, :white), LaneBoundary(:broken, :white), LaneConnection{Int64, Float64}[], LaneConnection{Int64, Float64}[])])
 RoadSegment{Float64}(2, Lane{Float64}[Lane{Float64}(LaneTag(2, 1), CurvePt{Float64}[CurvePt({25.000, -10.000, 1.571}, 0.000, 0.000, NaN), CurvePt({25.000, 10.000, 1.571}, 20.000, 0.000, NaN)], 6.0, SpeedLimit(-Inf, Inf), LaneBoundary(:unknown, :unknown), LaneBoundary(:unknown, :unknown), LaneConnection{Int64, Float64}[], LaneConnection{Int64, Float64}[])])

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 crosswalk part that will display the white stripes.

using Cairo

function AutomotiveVisualization.add_renderable!(rendermodel::RenderModel, env::CrosswalkEnv)

    # render the road without the crosswalk
    roadway = gen_straight_roadway(2, roadway_length)
    add_renderable!(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

snapshot = render([env])

crosswalk

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.

field of the VehicleDef type

fieldnames(VehicleDef)
# Agent.Class is from AutomotiveSimulator
const PEDESTRIAN_DEF = VehicleDef(AgentClass.PEDESTRIAN, 1.0, 1.0)

Car definition

car_initial_state = VehicleState(VecSE2(5.0, 0., 0.), roadway.segments[1].lanes[1],roadway, 8.0)
car = Entity(car_initial_state, VehicleDef(), :car)
Entity{VehicleState, VehicleDef, Symbol}(VehicleState(VecSE2({5.000, 0.000}, 0.000), Frenet(RoadIndex({1,   0}, {1, 1}), 5.000, 0.000, 0.000), 8.000), VehicleDef(CAR, 4.000, 1.800), :car)

Pedestrian definition using our new Vehicle definition

ped_initial_state = VehicleState(VecSE2(+24.5,-7.0,π/2), env.crosswalk, roadway, 0.5)
ped = Entity(ped_initial_state, PEDESTRIAN_DEF, :pedestrian)

scene = Scene([car, ped])
Scene{Entity{VehicleState, VehicleDef, Symbol}}(2 entities)

visualize the initial state

snapshot = render([env, scene])

initial state of crosswalk

Simulate the scenario

As before, associate a driver model to each vehicle in the scene. We will use the model defined in the intersection example for both agents.

mutable struct LinearDriver <: DriverModel{LaneFollowingAccel}
    a::LaneFollowingAccel
    p::Float64 # confidence on the pedestrian intention
    k::Float64 # gain
end

function AutomotiveSimulator.observe!(model::LinearDriver, scene::Scene, roadway::Roadway, egoid)
    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
Base.rand(rng::AbstractRNG, model::LinearDriver) = model.a

timestep = 0.1
nticks = 50

# define a model for each entities present in the scene
models = Dict{Symbol, DriverModel}()

# Constant speed model
models[:car] = LinearDriver(LaneFollowingAccel(0.0), 20.0, -0.02)
models[:pedestrian] = IntelligentDriverModel(v_des=1.0)

# execute the simulation
scenes = simulate(scene, roadway, models, nticks, timestep)

Generate a video with Reel.jl

using Reel

function animate_record(scenes::Vector{Scene{E}},dt::Float64, env::CrosswalkEnv) where {E<:Entity}
    duration = length(scenes)*dt::Float64
    fps = Int(1/dt)
    function render_rec(t, dt)
        frame_index = Int(floor(t/dt)) + 1
        return render([env, scenes[frame_index]])
    end
    return duration, fps, render_rec
end

duration, fps, render_hist = animate_record(scenes, timestep, env)
film = roll(render_hist, fps=fps, duration=duration)

animated crosswalk


This page was generated using Literate.jl.