// 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 . #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 LightManager::GetAllLights(LightGroup type) const { std::vector 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& lights) { for(Light& light : lights) { SetActive(light._id, true); } } void LightManager::TurnOff(std::vector& lights) { for(Light& light : lights) { SetActive(light._id, false); } } void LightManager::SetActive(std::vector& lights, std::vector& 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 LightManager::IsActive(std::vector& lights) const { std::vector result; for(Light& light : lights) { result.push_back( IsActive(light._id) ); } return result; } std::vector LightManager::GetTurnedOnLights(LightGroup type) const { std::vector 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 LightManager::GetTurnedOffLights(LightGroup type) const { std::vector 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& lights, Color color) { for(Light& light : lights) { SetColor(light._id, color); } } void LightManager::SetColor(std::vector& lights, std::vector& 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 LightManager::GetColor(std::vector& lights) const { std::vector result; for(Light& light : lights) { result.push_back( GetColor(light._id) ); } return result; } void LightManager::SetIntensity(std::vector& lights, float intensity) { for(Light& light : lights) { SetIntensity(light._id, intensity); } } void LightManager::SetIntensity(std::vector& lights, std::vector& 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 LightManager::GetIntensity(std::vector& lights) const { std::vector result; for(Light& light : lights) { result.push_back( GetIntensity(light._id) ); } return result; } void LightManager::SetLightGroup(std::vector& lights, LightGroup group) { for(Light& light : lights) { SetLightGroup(light._id, group); } } void LightManager::SetLightGroup(std::vector& lights, std::vector& 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 LightManager::GetLightGroup(std::vector& lights) const { std::vector result; for(Light& light : lights) { result.push_back( GetLightGroup(light._id) ); } return result; } void LightManager::SetLightState(std::vector& lights, LightState state) { for(Light& light : lights) { SetLightState(light._id, state); } } void LightManager::SetLightState(std::vector& lights, std::vector& 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 LightManager::GetLightState(std::vector& lights) const { std::vector 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 lock(_mutex); LightState& state = const_cast(RetrieveLightState(id)); state._active = active; _lights_changes[id] = state; _dirty = true; } void LightManager::SetColor(LightId id, Color color) { std::lock_guard lock(_mutex); LightState& state = const_cast(RetrieveLightState(id)); state._color = color; _lights_changes[id] = state; _dirty = true; } void LightManager::SetIntensity(LightId id, float intensity) { std::lock_guard lock(_mutex); LightState& state = const_cast(RetrieveLightState(id)); state._intensity = intensity; _lights_changes[id] = state; _dirty = true; } void LightManager::SetLightState(LightId id, const LightState& new_state) { std::lock_guard lock(_mutex); LightState& state = const_cast(RetrieveLightState(id)); state = new_state; _lights_changes[id] = state; _dirty = true; } void LightManager::SetLightStateNoLock(LightId id, const LightState& new_state) { LightState& state = const_cast(RetrieveLightState(id)); state = new_state; _lights_changes[id] = state; } void LightManager::SetLightGroup(LightId id, LightGroup group) { std::lock_guard lock(_mutex); LightState& state = const_cast(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 lock(_mutex); // Send blocking query std::vector lights_snapshot = _episode.Lock()->QueryLightsStateToServer(); // Update lights SharedPtr 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(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 lock(_mutex); if(_dirty) { std::vector 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 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