use super::{controller::VehiclePIDController, pid::PIDParams, types::RoadOption};
use crate::{
agents::tools::get_speed,
client::{ActorBase, Vehicle, Waypoint},
error::Result,
rpc::VehicleControl,
};
use std::collections::VecDeque;
#[derive(Debug, Clone)]
pub struct LocalPlannerConfig {
pub dt: f32,
pub target_speed: f32,
pub sampling_radius: f32,
pub lateral_control_dict: PIDParams,
pub longitudinal_control_dict: PIDParams,
pub max_throttle: f32,
pub max_brake: f32,
pub max_steering: f32,
pub offset: f32,
}
impl Default for LocalPlannerConfig {
fn default() -> Self {
Self {
dt: 1.0 / 20.0,
target_speed: 20.0,
sampling_radius: 2.0,
lateral_control_dict: PIDParams {
k_p: 1.95,
k_i: 1.4,
k_d: 0.01,
},
longitudinal_control_dict: PIDParams {
k_p: 1.0,
k_i: 1.0,
k_d: 0.0,
},
max_throttle: 0.75,
max_brake: 0.3,
max_steering: 0.8,
offset: 0.0,
}
}
}
pub struct LocalPlanner {
vehicle: Vehicle,
controller: VehiclePIDController,
waypoints_queue: VecDeque<(Waypoint, RoadOption)>,
target_speed: f32,
_sampling_radius: f32,
follow_speed_limits: bool,
base_min_distance: f32,
distance_ratio: f32,
}
impl LocalPlanner {
pub fn new(vehicle: Vehicle, config: LocalPlannerConfig) -> Self {
let controller = VehiclePIDController::new(
config.lateral_control_dict,
config.longitudinal_control_dict,
config.offset,
config.max_throttle,
config.max_brake,
config.max_steering,
config.dt,
);
Self {
vehicle,
controller,
waypoints_queue: VecDeque::new(),
target_speed: config.target_speed,
_sampling_radius: config.sampling_radius,
follow_speed_limits: false,
base_min_distance: 3.0,
distance_ratio: 0.5,
}
}
pub fn set_speed(&mut self, speed: f32) {
self.target_speed = speed;
}
pub fn follow_speed_limits(&mut self, value: bool) {
self.follow_speed_limits = value;
}
pub fn set_offset(&mut self, offset: f32) {
self.controller.set_offset(offset);
}
pub fn set_global_plan(
&mut self,
plan: Vec<(Waypoint, RoadOption)>,
stop_waypoint_creation: bool,
clean_queue: bool,
) {
if clean_queue {
self.waypoints_queue.clear();
}
for waypoint_pair in plan {
self.waypoints_queue.push_back(waypoint_pair);
}
let _ = stop_waypoint_creation; }
pub fn get_plan(&self) -> Vec<(Waypoint, RoadOption)> {
self.waypoints_queue.iter().cloned().collect()
}
pub fn get_incoming_waypoint_and_direction(
&self,
steps: usize,
) -> Option<(Waypoint, RoadOption)> {
if steps >= self.waypoints_queue.len() {
self.waypoints_queue.back().cloned()
} else {
self.waypoints_queue.get(steps).cloned()
}
}
pub fn done(&self) -> bool {
self.waypoints_queue.is_empty()
}
pub fn run_step(&mut self, debug: bool) -> Result<VehicleControl> {
let vehicle_location = self.vehicle.transform()?.location;
let vehicle_speed = get_speed(&self.vehicle) / 3.6; let min_distance = self.base_min_distance + self.distance_ratio * vehicle_speed;
let mut num_waypoint_removed = 0;
for (waypoint, _) in &self.waypoints_queue {
let min_dist_threshold = if self.waypoints_queue.len() - num_waypoint_removed == 1 {
1.0
} else {
min_distance
};
let waypoint_location = waypoint.transform().location;
let distance = ((vehicle_location.x - waypoint_location.x).powi(2)
+ (vehicle_location.y - waypoint_location.y).powi(2))
.sqrt();
if distance < min_dist_threshold {
num_waypoint_removed += 1;
} else {
break;
}
}
for _ in 0..num_waypoint_removed {
self.waypoints_queue.pop_front();
}
if self.waypoints_queue.is_empty() {
return Ok(VehicleControl {
throttle: 0.0,
steer: 0.0,
brake: 1.0,
hand_brake: false,
reverse: false,
manual_gear_shift: false,
gear: 0,
});
}
let (target_waypoint, _) = &self.waypoints_queue[0];
let target_location = target_waypoint.transform().location;
let target_speed = self.target_speed;
if debug {
println!(
"LocalPlanner: target_speed={:.1}, queue_len={}",
target_speed,
self.waypoints_queue.len()
);
}
let control = self
.controller
.run_step(&self.vehicle, target_speed, &target_location)?;
Ok(control)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_local_planner_config_default() {
let config = LocalPlannerConfig::default();
assert_eq!(config.dt, 1.0 / 20.0);
assert_eq!(config.target_speed, 20.0);
assert_eq!(config.sampling_radius, 2.0);
}
#[test]
fn test_set_speed() {
let config = LocalPlannerConfig {
target_speed: 50.0,
..Default::default()
};
assert_eq!(config.target_speed, 50.0);
}
}