From d5392c7408346cb87288a221365b3c4dcff1e42d Mon Sep 17 00:00:00 2001 From: nsubiron Date: Sun, 21 Oct 2018 23:35:03 +0200 Subject: [PATCH] Add traffic lights and signs as actors --- LibCarla/source/carla/client/TrafficLight.cpp | 25 ++++++++++++++++ LibCarla/source/carla/client/TrafficLight.h | 30 +++++++++++++++++++ .../carla/client/detail/ActorFactory.cpp | 3 ++ .../carla/client/detail/EpisodeState.cpp | 2 +- .../source/carla/client/detail/EpisodeState.h | 1 + .../carla/sensor/data/ActorDynamicState.h | 4 ++- PythonAPI/source/libcarla/Actor.cpp | 13 ++++++++ .../Source/Carla/Actor/ActorRegistry.cpp | 12 ++++++++ .../Carla/Source/Carla/Actor/ActorView.h | 8 +++++ .../Carla/Source/Carla/Game/CarlaEpisode.cpp | 29 ++++++++++++++++++ .../Source/Carla/Sensor/WorldObserver.cpp | 20 +++++++++++-- 11 files changed, 143 insertions(+), 4 deletions(-) create mode 100644 LibCarla/source/carla/client/TrafficLight.cpp create mode 100644 LibCarla/source/carla/client/TrafficLight.h diff --git a/LibCarla/source/carla/client/TrafficLight.cpp b/LibCarla/source/carla/client/TrafficLight.cpp new file mode 100644 index 000000000..16d8f62e9 --- /dev/null +++ b/LibCarla/source/carla/client/TrafficLight.cpp @@ -0,0 +1,25 @@ +// Copyright (c) 2017 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/TrafficLight.h" + +#include "carla/client/detail/Simulator.h" + +namespace carla { +namespace client { + + TrafficLightState TrafficLight::GetState() { + auto state = GetEpisode().Lock()->GetActorDynamicState(*this).state; + switch (state) { + case 1u: return TrafficLightState::Red; + case 2u: return TrafficLightState::Yellow; + case 3u: return TrafficLightState::Green; + default: return TrafficLightState::Unknown; + } + } + +} // namespace client +} // namespace carla diff --git a/LibCarla/source/carla/client/TrafficLight.h b/LibCarla/source/carla/client/TrafficLight.h new file mode 100644 index 000000000..1fe016742 --- /dev/null +++ b/LibCarla/source/carla/client/TrafficLight.h @@ -0,0 +1,30 @@ +// Copyright (c) 2017 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 . + +#pragma once + +#include "carla/client/Actor.h" + +namespace carla { +namespace client { + + enum class TrafficLightState { + Unknown, + Red, + Yellow, + Green + }; + + class TrafficLight : public Actor { + public: + + explicit TrafficLight(ActorInitializer init) : Actor(std::move(init)) {} + + TrafficLightState GetState(); + }; + +} // namespace client +} // namespace carla diff --git a/LibCarla/source/carla/client/detail/ActorFactory.cpp b/LibCarla/source/carla/client/detail/ActorFactory.cpp index 99897e7ec..9d6f338be 100644 --- a/LibCarla/source/carla/client/detail/ActorFactory.cpp +++ b/LibCarla/source/carla/client/detail/ActorFactory.cpp @@ -10,6 +10,7 @@ #include "carla/StringUtil.h" #include "carla/client/Actor.h" #include "carla/client/Sensor.h" +#include "carla/client/TrafficLight.h" #include "carla/client/Vehicle.h" #include "carla/client/World.h" #include "carla/client/detail/Client.h" @@ -70,6 +71,8 @@ namespace detail { return MakeActorImpl(ActorInitializer{description, episode}, gc); } else if (StringUtil::StartsWith(description.description.id, "vehicle.")) { return MakeActorImpl(ActorInitializer{description, episode}, gc); + } else if (StringUtil::StartsWith(description.description.id, "traffic.traffic_light")) { + return MakeActorImpl(ActorInitializer{description, episode}, gc); } return MakeActorImpl(ActorInitializer{description, episode}, gc); } diff --git a/LibCarla/source/carla/client/detail/EpisodeState.cpp b/LibCarla/source/carla/client/detail/EpisodeState.cpp index 7f6e54bb7..914cf6b16 100644 --- a/LibCarla/source/carla/client/detail/EpisodeState.cpp +++ b/LibCarla/source/carla/client/detail/EpisodeState.cpp @@ -38,7 +38,7 @@ namespace detail { DEBUG_ONLY(auto result = ) next->_actors.emplace( actor.id, - ActorState{actor.transform, actor.velocity, acceleration}); + ActorState{actor.transform, actor.velocity, acceleration, actor.state}); DEBUG_ASSERT(result.second); } return next; diff --git a/LibCarla/source/carla/client/detail/EpisodeState.h b/LibCarla/source/carla/client/detail/EpisodeState.h index aaf2c4a49..213e5da2e 100644 --- a/LibCarla/source/carla/client/detail/EpisodeState.h +++ b/LibCarla/source/carla/client/detail/EpisodeState.h @@ -30,6 +30,7 @@ namespace detail { geom::Transform transform; geom::Vector3D velocity; geom::Vector3D acceleration; + uint8_t state = 0u; }; const auto &GetTimestamp() const { diff --git a/LibCarla/source/carla/sensor/data/ActorDynamicState.h b/LibCarla/source/carla/sensor/data/ActorDynamicState.h index 9aa4a58cf..77c85ed54 100644 --- a/LibCarla/source/carla/sensor/data/ActorDynamicState.h +++ b/LibCarla/source/carla/sensor/data/ActorDynamicState.h @@ -26,11 +26,13 @@ namespace data { geom::Transform transform; geom::Vector3D velocity; + + uint8_t state; }; #pragma pack(pop) - static_assert(sizeof(ActorDynamicState) == 10u * sizeof(uint32_t), "Invalid ActorDynamicState size!"); + static_assert(sizeof(ActorDynamicState) == 1u + 10u * sizeof(uint32_t), "Invalid ActorDynamicState size!"); } // namespace data } // namespace sensor diff --git a/PythonAPI/source/libcarla/Actor.cpp b/PythonAPI/source/libcarla/Actor.cpp index 79003408c..10ee0dd17 100644 --- a/PythonAPI/source/libcarla/Actor.cpp +++ b/PythonAPI/source/libcarla/Actor.cpp @@ -5,6 +5,7 @@ // For a copy, see . #include +#include #include #include @@ -62,4 +63,16 @@ void export_actor() { .def("set_autopilot", &cc::Vehicle::SetAutopilot, (arg("enabled")=true)) .def(self_ns::str(self_ns::self)) ; + + enum_("TrafficLightState") + .value("Unknown", cc::TrafficLightState::Unknown) + .value("Red", cc::TrafficLightState::Red) + .value("Yellow", cc::TrafficLightState::Yellow) + .value("Green", cc::TrafficLightState::Green) + ; + + class_, boost::noncopyable, boost::shared_ptr>("TrafficLight", no_init) + .add_property("state", &cc::TrafficLight::GetState) + .def(self_ns::str(self_ns::self)) + ; } diff --git a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Actor/ActorRegistry.cpp b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Actor/ActorRegistry.cpp index 6c5433cb7..bc407403d 100644 --- a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Actor/ActorRegistry.cpp +++ b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Actor/ActorRegistry.cpp @@ -8,7 +8,17 @@ #include "Carla.h" #include "Carla/Actor/ActorRegistry.h" + #include "Carla/Game/Tagger.h" +#include "Carla/Traffic/TrafficLightBase.h" + +static bool FActorRegistry_IsTrafficLight(const FActorView &View) +{ + return + View.IsValid() && + View.GetSemanticTags().Contains(ECityObjectLabel::TrafficSigns) && + (nullptr != Cast(View.GetActor())); +} static FString GetRelevantTagAsString(const FActorView &View) { @@ -41,6 +51,8 @@ FActorView FActorRegistry::Register(AActor &Actor, FActorDescription Description auto View = FActorView(Id, Actor, std::move(Description)); ATagger::GetTagsOfTaggedActor(Actor, View.SemanticTags); + View.bIsTrafficLight = FActorRegistry_IsTrafficLight(View); + auto Result = ActorDatabase.emplace(Id, View); check(Result.second); check(static_cast(Actors.Num()) == ActorDatabase.size()); diff --git a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Actor/ActorView.h b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Actor/ActorView.h index 80b7a97de..f548249eb 100644 --- a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Actor/ActorView.h +++ b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Actor/ActorView.h @@ -51,6 +51,11 @@ public: return SemanticTags; } + bool IsTrafficLight() const + { + return bIsTrafficLight; + } + private: friend class FActorRegistry; @@ -67,4 +72,7 @@ private: TSharedPtr Description = nullptr; TSet SemanticTags; + + /// @todo + bool bIsTrafficLight = false; }; diff --git a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Game/CarlaEpisode.cpp b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Game/CarlaEpisode.cpp index fc5ae2897..9f884f4a3 100644 --- a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Game/CarlaEpisode.cpp +++ b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Game/CarlaEpisode.cpp @@ -10,6 +10,25 @@ #include "EngineUtils.h" #include "GameFramework/SpectatorPawn.h" +static FString UCarlaEpisode_GetTrafficSignId(ETrafficSignState State) +{ + using TSS = ETrafficSignState; + switch (State) { + case TSS::TrafficLightRed: + case TSS::TrafficLightYellow: + case TSS::TrafficLightGreen: return TEXT("traffic.traffic_light"); + case TSS::SpeedLimit_30: return TEXT("traffic.speed_limit.30"); + case TSS::SpeedLimit_40: return TEXT("traffic.speed_limit.40"); + case TSS::SpeedLimit_50: return TEXT("traffic.speed_limit.50"); + case TSS::SpeedLimit_60: return TEXT("traffic.speed_limit.60"); + case TSS::SpeedLimit_90: return TEXT("traffic.speed_limit.90"); + case TSS::SpeedLimit_100: return TEXT("traffic.speed_limit.100"); + case TSS::SpeedLimit_120: return TEXT("traffic.speed_limit.120"); + case TSS::SpeedLimit_130: return TEXT("traffic.speed_limit.130"); + default: return TEXT("traffic.unknown"); + } +} + UCarlaEpisode::UCarlaEpisode(const FObjectInitializer &ObjectInitializer) : Super(ObjectInitializer), Id([]() { @@ -57,4 +76,14 @@ void UCarlaEpisode::InitializeAtBeginPlay() { UE_LOG(LogCarla, Error, TEXT("Can't find spectator!")); } + + for (TActorIterator It(World); It; ++It) + { + ATrafficSignBase *Actor = *It; + check(Actor != nullptr); + FActorDescription Description; + Description.Id = UCarlaEpisode_GetTrafficSignId(Actor->GetTrafficSignState()); + Description.Class = Actor->GetClass(); + ActorDispatcher.GetActorRegistry().Register(*Actor, Description); + } } diff --git a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Sensor/WorldObserver.cpp b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Sensor/WorldObserver.cpp index 1b9190d83..0ed8450a4 100644 --- a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Sensor/WorldObserver.cpp +++ b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Sensor/WorldObserver.cpp @@ -7,18 +7,33 @@ #include "Carla.h" #include "Carla/Sensor/WorldObserver.h" +#include "Carla/Traffic/TrafficLightBase.h" + #include "CoreGlobals.h" #include #include #include +static uint8 AWorldObserver_GetActorState(const FActorView &View) +{ + if (View.IsTrafficLight()) + { + auto TrafficLight = Cast(View.GetActor()); + if (TrafficLight != nullptr) + { + return static_cast(TrafficLight->GetTrafficSignState()); + } + } + return 0u; +} static carla::Buffer AWorldObserver_Serialize( carla::Buffer buffer, double game_timestamp, double platform_timestamp, - const FActorRegistry &Registry) { + const FActorRegistry &Registry) +{ using Serializer = carla::sensor::s11n::EpisodeStateSerializer; using ActorDynamicState = carla::sensor::data::ActorDynamicState; @@ -43,7 +58,8 @@ static carla::Buffer AWorldObserver_Serialize( ActorDynamicState info = { actor_view.GetActorId(), actor_view.GetActor()->GetActorTransform(), - carla::geom::Vector3D{velocity.X, velocity.Y, velocity.Z} + carla::geom::Vector3D{velocity.X, velocity.Y, velocity.Z}, + AWorldObserver_GetActorState(actor_view) }; write_data(info); }