libcarla/include/carla/client/LightManager.cpp
2024-10-18 13:19:59 +08:00

336 lines
9.5 KiB
C++

// 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 "carla/client/LightManager.h"
#include "carla/client/detail/Simulator.h"
namespace carla {
namespace client {
using LightGroup = rpc::LightState::LightGroup;
LightManager::~LightManager(){
if(_episode.IsValid()) {
_episode.Lock()->RemoveOnTickEvent(_on_light_update_register_id);
_episode.Lock()->RemoveLightUpdateChangeEvent(_on_light_update_register_id);
}
UpdateServerLightsState(true);
}
void LightManager::SetEpisode(detail::WeakEpisodeProxy episode) {
_episode = episode;
_on_tick_register_id = _episode.Lock()->RegisterOnTickEvent(
[&](const WorldSnapshot&) {
UpdateServerLightsState();
});
_on_light_update_register_id = _episode.Lock()->RegisterLightUpdateChangeEvent(
[&](const WorldSnapshot& ) {
QueryLightsStateToServer();
ApplyChanges();
});
QueryLightsStateToServer();
}
std::vector<Light> LightManager::GetAllLights(LightGroup type) const {
std::vector<Light> result;
for(auto lights_state : _lights_state) {
LightGroup group = lights_state.second._group;
if((type == LightGroup::None) || (group == type)) {
auto it_light = _lights.find(lights_state.first);
result.push_back(it_light->second);
}
}
return result;
}
void LightManager::TurnOn(std::vector<Light>& lights) {
for(Light& light : lights) {
SetActive(light._id, true);
}
}
void LightManager::TurnOff(std::vector<Light>& lights) {
for(Light& light : lights) {
SetActive(light._id, false);
}
}
void LightManager::SetActive(std::vector<Light>& lights, std::vector<bool>& active) {
size_t lights_to_update = (lights.size() < active.size()) ? lights.size() : active.size();
for(size_t i = 0; i < lights_to_update; i++) {
SetActive(lights[i]._id, active[i]);
}
}
std::vector<bool> LightManager::IsActive(std::vector<Light>& lights) const {
std::vector<bool> result;
for(Light& light : lights) {
result.push_back( IsActive(light._id) );
}
return result;
}
std::vector<Light> LightManager::GetTurnedOnLights(LightGroup type) const {
std::vector<Light> result;
for(auto lights_state : _lights_state) {
LightState& state = lights_state.second;
LightGroup group = state._group;
if( (type == LightGroup::None || group == type) && state._active ) {
auto it_light = _lights.find(lights_state.first);
result.push_back(it_light->second);
}
}
return result;
}
std::vector<Light> LightManager::GetTurnedOffLights(LightGroup type) const {
std::vector<Light> result;
for(auto lights_state : _lights_state) {
LightState& state = lights_state.second;
LightGroup group = state._group;
if( (type == LightGroup::None || group == type) && !state._active ) {
auto it_light = _lights.find(lights_state.first);
result.push_back(it_light->second);
}
}
return result;
}
void LightManager::SetColor(std::vector<Light>& lights, Color color) {
for(Light& light : lights) {
SetColor(light._id, color);
}
}
void LightManager::SetColor(std::vector<Light>& lights, std::vector<Color>& colors) {
size_t lights_to_update = (lights.size() < colors.size()) ? lights.size() : colors.size();
for(size_t i = 0; i < lights_to_update; i++) {
SetColor(lights[i]._id, colors[i]);
}
}
std::vector<Color> LightManager::GetColor(std::vector<Light>& lights) const {
std::vector<Color> result;
for(Light& light : lights) {
result.push_back( GetColor(light._id) );
}
return result;
}
void LightManager::SetIntensity(std::vector<Light>& lights, float intensity) {
for(Light& light : lights) {
SetIntensity(light._id, intensity);
}
}
void LightManager::SetIntensity(std::vector<Light>& lights, std::vector<float>& intensities) {
size_t lights_to_update = (lights.size() < intensities.size()) ? lights.size() : intensities.size();
for(size_t i = 0; i < lights_to_update; i++) {
SetIntensity(lights[i]._id, intensities[i]);
}
}
std::vector<float> LightManager::GetIntensity(std::vector<Light>& lights) const {
std::vector<float> result;
for(Light& light : lights) {
result.push_back( GetIntensity(light._id) );
}
return result;
}
void LightManager::SetLightGroup(std::vector<Light>& lights, LightGroup group) {
for(Light& light : lights) {
SetLightGroup(light._id, group);
}
}
void LightManager::SetLightGroup(std::vector<Light>& lights, std::vector<LightGroup>& groups) {
size_t lights_to_update = (lights.size() < groups.size()) ? lights.size() : groups.size();
for(size_t i = 0; i < lights_to_update; i++) {
SetLightGroup(lights[i]._id, groups[i]);
}
}
std::vector<LightGroup> LightManager::GetLightGroup(std::vector<Light>& lights) const {
std::vector<LightGroup> result;
for(Light& light : lights) {
result.push_back( GetLightGroup(light._id) );
}
return result;
}
void LightManager::SetLightState(std::vector<Light>& lights, LightState state) {
for(Light& light : lights) {
SetLightState(light._id, state);
}
}
void LightManager::SetLightState(std::vector<Light>& lights, std::vector<LightState>& states) {
size_t lights_to_update = (lights.size() < states.size()) ? lights.size() : states.size();
for(size_t i = 0; i < lights_to_update; i++) {
SetLightState(lights[i]._id, states[i]);
}
}
std::vector<LightState> LightManager::GetLightState(std::vector<Light>& lights) const {
std::vector<LightState> result;
for(Light& light : lights) {
result.push_back( RetrieveLightState(light._id) );
}
return result;
}
Color LightManager::GetColor(LightId id) const {
return RetrieveLightState(id)._color;
}
float LightManager::GetIntensity(LightId id) const {
return RetrieveLightState(id)._intensity;
}
LightState LightManager::GetLightState(LightId id) const {
return RetrieveLightState(id);
}
LightGroup LightManager::GetLightGroup(LightId id) const {
return RetrieveLightState(id)._group;
}
bool LightManager::IsActive(LightId id) const {
return RetrieveLightState(id)._active;
}
void LightManager::SetActive(LightId id, bool active) {
std::lock_guard<std::mutex> lock(_mutex);
LightState& state = const_cast<LightState&>(RetrieveLightState(id));
state._active = active;
_lights_changes[id] = state;
_dirty = true;
}
void LightManager::SetColor(LightId id, Color color) {
std::lock_guard<std::mutex> lock(_mutex);
LightState& state = const_cast<LightState&>(RetrieveLightState(id));
state._color = color;
_lights_changes[id] = state;
_dirty = true;
}
void LightManager::SetIntensity(LightId id, float intensity) {
std::lock_guard<std::mutex> lock(_mutex);
LightState& state = const_cast<LightState&>(RetrieveLightState(id));
state._intensity = intensity;
_lights_changes[id] = state;
_dirty = true;
}
void LightManager::SetLightState(LightId id, const LightState& new_state) {
std::lock_guard<std::mutex> lock(_mutex);
LightState& state = const_cast<LightState&>(RetrieveLightState(id));
state = new_state;
_lights_changes[id] = state;
_dirty = true;
}
void LightManager::SetLightStateNoLock(LightId id, const LightState& new_state) {
LightState& state = const_cast<LightState&>(RetrieveLightState(id));
state = new_state;
_lights_changes[id] = state;
}
void LightManager::SetLightGroup(LightId id, LightGroup group) {
std::lock_guard<std::mutex> lock(_mutex);
LightState& state = const_cast<LightState&>(RetrieveLightState(id));
state._group = group;
_lights_changes[id] = state;
_dirty = true;
}
const LightState& LightManager::RetrieveLightState(LightId id) const {
auto it = _lights_state.find(id);
if(it == _lights_state.end()) {
carla::log_warning("Invalid light", id);
return _state;
}
return it->second;
}
void LightManager::QueryLightsStateToServer() {
std::lock_guard<std::mutex> lock(_mutex);
// Send blocking query
std::vector<rpc::LightState> lights_snapshot = _episode.Lock()->QueryLightsStateToServer();
// Update lights
SharedPtr<LightManager> lm = _episode.Lock()->GetLightManager();
for(const auto& it : lights_snapshot) {
_lights_state[it._id] = LightState(
it._intensity,
Color(it._color.r, it._color.g, it._color.b),
static_cast<LightState::LightGroup>(it._group),
it._active
);
if(_lights.find(it._id) == _lights.end())
{
_lights[it._id] = Light(lm, it._location, it._id);
}
}
}
void LightManager::UpdateServerLightsState(bool discard_client) {
std::lock_guard<std::mutex> lock(_mutex);
if(_dirty) {
std::vector<rpc::LightState> message;
for(auto it : _lights_changes) {
auto it_light = _lights.find(it.first);
if(it_light != _lights.end()) {
rpc::LightState state(
it_light->second.GetLocation(),
it.second._intensity,
it.second._group,
rpc::Color(it.second._color.r, it.second._color.g, it.second._color.b),
it.second._active
);
state._id = it.first;
// Add to command
message.push_back(state);
}
}
_episode.Lock()->UpdateServerLightsState(message, discard_client);
_lights_changes.clear();
_dirty = false;
}
}
void LightManager::ApplyChanges() {
std::lock_guard<std::mutex> lock(_mutex);
for(const auto& it : _lights_changes) {
SetLightStateNoLock(it.first, it.second);
}
}
void LightManager::SetDayNightCycle(const bool active) {
_episode.Lock()->UpdateDayNightCycle(active);
}
} // namespace client
} // namespace carla