libcarla/include/carla/trafficmanager/TrafficManagerLocal.cpp

496 lines
17 KiB
C++
Raw Permalink Normal View History

2024-10-18 13:19:59 +08:00
// Copyright (c) 2020 Computer Vision Center (CVC) at the Universitat Autonoma
// de Barcelona (UAB).
//
// This work is licensed under the terms of the MIT license.
// For a copy, see <https://opensource.org/licenses/MIT>.
#include <algorithm>
#include "carla/Logging.h"
#include "carla/client/detail/Simulator.h"
#include "carla/trafficmanager/TrafficManagerLocal.h"
namespace carla {
namespace traffic_manager {
using namespace constants::FrameMemory;
TrafficManagerLocal::TrafficManagerLocal(
std::vector<float> longitudinal_PID_parameters,
std::vector<float> longitudinal_highway_PID_parameters,
std::vector<float> lateral_PID_parameters,
std::vector<float> lateral_highway_PID_parameters,
float perc_difference_from_limit,
cc::detail::EpisodeProxy &episode_proxy,
uint16_t &RPCportTM)
: longitudinal_PID_parameters(longitudinal_PID_parameters),
longitudinal_highway_PID_parameters(longitudinal_highway_PID_parameters),
lateral_PID_parameters(lateral_PID_parameters),
lateral_highway_PID_parameters(lateral_highway_PID_parameters),
episode_proxy(episode_proxy),
world(cc::World(episode_proxy)),
localization_stage(LocalizationStage(vehicle_id_list,
buffer_map,
simulation_state,
track_traffic,
local_map,
parameters,
marked_for_removal,
localization_frame,
random_device)),
collision_stage(CollisionStage(vehicle_id_list,
simulation_state,
buffer_map,
track_traffic,
parameters,
collision_frame,
random_device)),
traffic_light_stage(TrafficLightStage(vehicle_id_list,
simulation_state,
buffer_map,
parameters,
world,
tl_frame,
random_device)),
motion_plan_stage(MotionPlanStage(vehicle_id_list,
simulation_state,
parameters,
buffer_map,
track_traffic,
longitudinal_PID_parameters,
longitudinal_highway_PID_parameters,
lateral_PID_parameters,
lateral_highway_PID_parameters,
localization_frame,
collision_frame,
tl_frame,
world,
control_frame,
random_device,
local_map)),
vehicle_light_stage(VehicleLightStage(vehicle_id_list,
buffer_map,
parameters,
world,
control_frame)),
alsm(ALSM(registered_vehicles,
buffer_map,
track_traffic,
marked_for_removal,
parameters,
world,
local_map,
simulation_state,
localization_stage,
collision_stage,
traffic_light_stage,
motion_plan_stage,
vehicle_light_stage)),
server(TrafficManagerServer(RPCportTM, static_cast<carla::traffic_manager::TrafficManagerBase *>(this))) {
parameters.SetGlobalPercentageSpeedDifference(perc_difference_from_limit);
registered_vehicles_state = -1;
SetupLocalMap();
Start();
}
TrafficManagerLocal::~TrafficManagerLocal() {
episode_proxy.Lock()->DestroyTrafficManager(server.port());
Release();
}
void TrafficManagerLocal::SetupLocalMap() {
const carla::SharedPtr<const cc::Map> world_map = world.GetMap();
local_map = std::make_shared<InMemoryMap>(world_map);
auto files = episode_proxy.Lock()->GetRequiredFiles("TM");
if (!files.empty()) {
auto content = episode_proxy.Lock()->GetCacheFile(files[0], true);
if (content.size() != 0) {
local_map->Load(content);
} else {
log_warning("No InMemoryMap cache found. Setting up local map. This may take a while...");
local_map->SetUp();
}
} else {
log_warning("No InMemoryMap cache found. Setting up local map. This may take a while...");
local_map->SetUp();
}
}
void TrafficManagerLocal::Start() {
run_traffic_manger.store(true);
worker_thread = std::make_unique<std::thread>(&TrafficManagerLocal::Run, this);
}
void TrafficManagerLocal::Run() {
localization_frame.reserve(INITIAL_SIZE);
collision_frame.reserve(INITIAL_SIZE);
tl_frame.reserve(INITIAL_SIZE);
control_frame.reserve(INITIAL_SIZE);
current_reserved_capacity = INITIAL_SIZE;
size_t last_frame = 0;
while (run_traffic_manger.load()) {
bool synchronous_mode = parameters.GetSynchronousMode();
bool hybrid_physics_mode = parameters.GetHybridPhysicsMode();
parameters.SetMaxBoundaries(20.0f, episode_proxy.Lock()->GetEpisodeSettings().actor_active_distance);
// Wait for external trigger to initiate cycle in synchronous mode.
if (synchronous_mode) {
std::unique_lock<std::mutex> lock(step_execution_mutex);
step_begin_trigger.wait(lock, [this]() {return step_begin.load() || !run_traffic_manger.load();});
step_begin.store(false);
}
// Skipping velocity update if elapsed time is less than 0.05s in asynchronous, hybrid mode.
if (!synchronous_mode && hybrid_physics_mode) {
TimePoint current_instance = chr::system_clock::now();
chr::duration<float> elapsed_time = current_instance - previous_update_instance;
chr::duration<float> time_to_wait = chr::duration<float>(HYBRID_MODE_DT) - elapsed_time;
if (time_to_wait > chr::duration<float>(0.0f)) {
std::this_thread::sleep_for(time_to_wait);
}
previous_update_instance = current_instance;
}
// Stop TM from processing the same frame more than once
if (!synchronous_mode) {
carla::client::Timestamp timestamp = world.GetSnapshot().GetTimestamp();
if (timestamp.frame == last_frame) {
continue;
}
last_frame = timestamp.frame;
}
std::unique_lock<std::mutex> registration_lock(registration_mutex);
// Updating simulation state, actor life cycle and performing necessary cleanup.
alsm.Update();
// Re-allocating inter-stage communication frames based on changed number of registered vehicles.
int current_registered_vehicles_state = registered_vehicles.GetState();
unsigned long number_of_vehicles = vehicle_id_list.size();
if (registered_vehicles_state != current_registered_vehicles_state || number_of_vehicles != registered_vehicles.Size()) {
vehicle_id_list = registered_vehicles.GetIDList();
number_of_vehicles = vehicle_id_list.size();
// Reserve more space if needed.
uint64_t growth_factor = static_cast<uint64_t>(static_cast<float>(number_of_vehicles) * INV_GROWTH_STEP_SIZE);
uint64_t new_frame_capacity = INITIAL_SIZE + GROWTH_STEP_SIZE * growth_factor;
if (new_frame_capacity > current_reserved_capacity) {
localization_frame.reserve(new_frame_capacity);
collision_frame.reserve(new_frame_capacity);
tl_frame.reserve(new_frame_capacity);
control_frame.reserve(new_frame_capacity);
}
registered_vehicles_state = registered_vehicles.GetState();
}
// Reset frames for current cycle.
localization_frame.clear();
localization_frame.resize(number_of_vehicles);
collision_frame.clear();
collision_frame.resize(number_of_vehicles);
tl_frame.clear();
tl_frame.resize(number_of_vehicles);
control_frame.clear();
// Reserve two frames for each vehicle: one for the ApplyVehicleControl command,
// and one for the optional SetVehicleLightState command
control_frame.reserve(2 * number_of_vehicles);
// Resize to accomodate at least all ApplyVehicleControl commands,
// that will be inserted by the motion_plan_stage stage.
control_frame.resize(number_of_vehicles);
// Run core operation stages.
for (unsigned long index = 0u; index < vehicle_id_list.size(); ++index) {
localization_stage.Update(index);
}
for (unsigned long index = 0u; index < vehicle_id_list.size(); ++index) {
collision_stage.Update(index);
}
collision_stage.ClearCycleCache();
vehicle_light_stage.UpdateWorldInfo();
for (unsigned long index = 0u; index < vehicle_id_list.size(); ++index) {
traffic_light_stage.Update(index);
motion_plan_stage.Update(index);
vehicle_light_stage.Update(index);
}
registration_lock.unlock();
// Sending the current cycle's batch command to the simulator.
if (synchronous_mode) {
episode_proxy.Lock()->ApplyBatchSync(control_frame, false);
step_end.store(true);
step_end_trigger.notify_one();
} else {
if (control_frame.size() > 0){
episode_proxy.Lock()->ApplyBatchSync(control_frame, false);
}
}
}
}
bool TrafficManagerLocal::SynchronousTick() {
if (parameters.GetSynchronousMode()) {
step_begin.store(true);
step_begin_trigger.notify_one();
std::unique_lock<std::mutex> lock(step_execution_mutex);
step_end_trigger.wait(lock, [this]() { return step_end.load(); });
step_end.store(false);
}
return true;
}
void TrafficManagerLocal::Stop() {
run_traffic_manger.store(false);
if (parameters.GetSynchronousMode()) {
step_begin_trigger.notify_one();
}
if (worker_thread) {
if (worker_thread->joinable()) {
worker_thread->join();
}
worker_thread.release();
}
vehicle_id_list.clear();
registered_vehicles.Clear();
registered_vehicles_state = -1;
track_traffic.Clear();
previous_update_instance = chr::system_clock::now();
current_reserved_capacity = 0u;
simulation_state.Reset();
localization_stage.Reset();
collision_stage.Reset();
traffic_light_stage.Reset();
motion_plan_stage.Reset();
buffer_map.clear();
localization_frame.clear();
collision_frame.clear();
tl_frame.clear();
control_frame.clear();
run_traffic_manger.store(true);
step_begin.store(false);
step_end.store(false);
}
void TrafficManagerLocal::Release() {
Stop();
local_map.reset();
}
void TrafficManagerLocal::Reset() {
Release();
episode_proxy = episode_proxy.Lock()->GetCurrentEpisode();
world = cc::World(episode_proxy);
SetupLocalMap();
Start();
}
void TrafficManagerLocal::RegisterVehicles(const std::vector<ActorPtr> &vehicle_list) {
std::lock_guard<std::mutex> registration_lock(registration_mutex);
registered_vehicles.Insert(vehicle_list);
}
void TrafficManagerLocal::UnregisterVehicles(const std::vector<ActorPtr> &actor_list) {
std::lock_guard<std::mutex> registration_lock(registration_mutex);
std::vector<ActorId> actor_id_list;
for (auto &actor : actor_list) {
alsm.RemoveActor(actor->GetId(), true);
}
}
void TrafficManagerLocal::SetPercentageSpeedDifference(const ActorPtr &actor, const float percentage) {
parameters.SetPercentageSpeedDifference(actor, percentage);
}
void TrafficManagerLocal::SetGlobalPercentageSpeedDifference(const float percentage) {
parameters.SetGlobalPercentageSpeedDifference(percentage);
}
void TrafficManagerLocal::SetLaneOffset(const ActorPtr &actor, const float offset) {
parameters.SetLaneOffset(actor, offset);
}
void TrafficManagerLocal::SetGlobalLaneOffset(const float offset) {
parameters.SetGlobalLaneOffset(offset);
}
void TrafficManagerLocal::SetDesiredSpeed(const ActorPtr &actor, const float value) {
parameters.SetDesiredSpeed(actor, value);
}
/// Method to set the automatic management of the vehicle lights
void TrafficManagerLocal::SetUpdateVehicleLights(const ActorPtr &actor, const bool do_update) {
parameters.SetUpdateVehicleLights(actor, do_update);
}
void TrafficManagerLocal::SetCollisionDetection(const ActorPtr &reference_actor, const ActorPtr &other_actor, const bool detect_collision) {
parameters.SetCollisionDetection(reference_actor, other_actor, detect_collision);
}
void TrafficManagerLocal::SetForceLaneChange(const ActorPtr &actor, const bool direction) {
parameters.SetForceLaneChange(actor, direction);
}
void TrafficManagerLocal::SetAutoLaneChange(const ActorPtr &actor, const bool enable) {
parameters.SetAutoLaneChange(actor, enable);
}
void TrafficManagerLocal::SetDistanceToLeadingVehicle(const ActorPtr &actor, const float distance) {
parameters.SetDistanceToLeadingVehicle(actor, distance);
}
void TrafficManagerLocal::SetGlobalDistanceToLeadingVehicle(const float distance) {
parameters.SetGlobalDistanceToLeadingVehicle(distance);
}
void TrafficManagerLocal::SetPercentageIgnoreWalkers(const ActorPtr &actor, const float perc) {
parameters.SetPercentageIgnoreWalkers(actor, perc);
}
void TrafficManagerLocal::SetPercentageIgnoreVehicles(const ActorPtr &actor, const float perc) {
parameters.SetPercentageIgnoreVehicles(actor, perc);
}
void TrafficManagerLocal::SetPercentageRunningLight(const ActorPtr &actor, const float perc) {
parameters.SetPercentageRunningLight(actor, perc);
}
void TrafficManagerLocal::SetPercentageRunningSign(const ActorPtr &actor, const float perc) {
parameters.SetPercentageRunningSign(actor, perc);
}
void TrafficManagerLocal::SetKeepRightPercentage(const ActorPtr &actor, const float percentage) {
parameters.SetKeepRightPercentage(actor, percentage);
}
void TrafficManagerLocal::SetRandomLeftLaneChangePercentage(const ActorPtr &actor, const float percentage) {
parameters.SetRandomLeftLaneChangePercentage(actor, percentage);
}
void TrafficManagerLocal::SetRandomRightLaneChangePercentage(const ActorPtr &actor, const float percentage) {
parameters.SetRandomRightLaneChangePercentage(actor, percentage);
}
void TrafficManagerLocal::SetHybridPhysicsMode(const bool mode_switch) {
parameters.SetHybridPhysicsMode(mode_switch);
}
void TrafficManagerLocal::SetHybridPhysicsRadius(const float radius) {
parameters.SetHybridPhysicsRadius(radius);
}
void TrafficManagerLocal::SetOSMMode(const bool mode_switch) {
parameters.SetOSMMode(mode_switch);
}
void TrafficManagerLocal::SetCustomPath(const ActorPtr &actor, const Path path, const bool empty_buffer) {
parameters.SetCustomPath(actor, path, empty_buffer);
}
void TrafficManagerLocal::RemoveUploadPath(const ActorId &actor_id, const bool remove_path) {
parameters.RemoveUploadPath(actor_id, remove_path);
}
void TrafficManagerLocal::UpdateUploadPath(const ActorId &actor_id, const Path path) {
parameters.UpdateUploadPath(actor_id, path);
}
void TrafficManagerLocal::SetImportedRoute(const ActorPtr &actor, const Route route, const bool empty_buffer) {
parameters.SetImportedRoute(actor, route, empty_buffer);
}
void TrafficManagerLocal::RemoveImportedRoute(const ActorId &actor_id, const bool remove_path) {
parameters.RemoveImportedRoute(actor_id, remove_path);
}
void TrafficManagerLocal::UpdateImportedRoute(const ActorId &actor_id, const Route route) {
parameters.UpdateImportedRoute(actor_id, route);
}
void TrafficManagerLocal::SetRespawnDormantVehicles(const bool mode_switch) {
parameters.SetRespawnDormantVehicles(mode_switch);
}
void TrafficManagerLocal::SetBoundariesRespawnDormantVehicles(const float lower_bound, const float upper_bound) {
parameters.SetBoundariesRespawnDormantVehicles(lower_bound, upper_bound);
}
void TrafficManagerLocal::SetMaxBoundaries(const float lower, const float upper) {
parameters.SetMaxBoundaries(lower, upper);
}
Action TrafficManagerLocal::GetNextAction(const ActorId &actor_id) {
return localization_stage.ComputeNextAction(actor_id);
}
ActionBuffer TrafficManagerLocal::GetActionBuffer(const ActorId &actor_id) {
return localization_stage.ComputeActionBuffer(actor_id);
}
bool TrafficManagerLocal::CheckAllFrozen(TLGroup tl_to_freeze) {
for (auto &elem : tl_to_freeze) {
if (!elem->IsFrozen() || elem->GetState() != TLS::Red) {
return false;
}
}
return true;
}
void TrafficManagerLocal::SetSynchronousMode(bool mode) {
const bool previous_mode = parameters.GetSynchronousMode();
parameters.SetSynchronousMode(mode);
if (previous_mode && !mode) {
step_begin.store(true);
step_begin_trigger.notify_one();
}
}
void TrafficManagerLocal::SetSynchronousModeTimeOutInMiliSecond(double time) {
parameters.SetSynchronousModeTimeOutInMiliSecond(time);
}
carla::client::detail::EpisodeProxy &TrafficManagerLocal::GetEpisodeProxy() {
return episode_proxy;
}
std::vector<ActorId> TrafficManagerLocal::GetRegisteredVehiclesIDs() {
return registered_vehicles.GetIDList();
}
void TrafficManagerLocal::SetRandomDeviceSeed(const uint64_t _seed) {
seed = _seed;
random_device = RandomGenerator(seed);
world.ResetAllTrafficLights();
}
} // namespace traffic_manager
} // namespace carla