From 3e93782c98a273e39f827c0abb65b8ee08dbe32a Mon Sep 17 00:00:00 2001 From: nsubiron Date: Fri, 8 Feb 2019 14:37:31 +0100 Subject: [PATCH] Expose traffic sign's trigger volumes on Python API --- CHANGELOG.md | 2 +- LibCarla/source/carla/client/TrafficLight.h | 25 ++-- LibCarla/source/carla/client/TrafficSign.h | 25 ++++ LibCarla/source/carla/client/Vehicle.h | 24 +++- LibCarla/source/carla/client/Walker.h | 2 + .../carla/client/detail/ActorFactory.cpp | 5 +- .../source/carla/client/detail/ActorState.h | 8 +- PythonAPI/source/libcarla/Actor.cpp | 131 +++++++++--------- .../Source/Carla/Traffic/TrafficSignBase.h | 5 + .../Carla/Util/BoundingBoxCalculator.cpp | 18 +++ .../Source/Carla/Util/BoundingBoxCalculator.h | 2 + 11 files changed, 167 insertions(+), 80 deletions(-) create mode 100644 LibCarla/source/carla/client/TrafficSign.h diff --git a/CHANGELOG.md b/CHANGELOG.md index 4a2b0d4d3..d60ee0e3f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,7 +20,7 @@ * Fixed static objects present in the map were marked as "movable" * Fixed BP_MultipleFloor, tweaked offset in BaseFloor to adjust meshes between them * New traffic signs assets: one-way, no-turn, more speed limits, do not enter, arrow floors, Michigan left, and lane end - + * Expose traffic sign's trigger volumes on Python API ## CARLA 0.9.3 diff --git a/LibCarla/source/carla/client/TrafficLight.h b/LibCarla/source/carla/client/TrafficLight.h index b9e3b556e..b5beab046 100644 --- a/LibCarla/source/carla/client/TrafficLight.h +++ b/LibCarla/source/carla/client/TrafficLight.h @@ -6,43 +6,52 @@ #pragma once -#include "carla/client/Actor.h" +#include "carla/client/TrafficSign.h" #include "carla/rpc/TrafficLightState.h" namespace carla { namespace client { - class TrafficLight : public Actor { + class TrafficLight : public TrafficSign { public: - explicit TrafficLight(ActorInitializer init) : Actor(std::move(init)) {} + explicit TrafficLight(ActorInitializer init) : TrafficSign(std::move(init)) {} + + void SetState(rpc::TrafficLightState state); /// Return the current state of the traffic light. /// - /// @note These functions do not call the simulator, they return the - /// data received in the last tick. - void SetState(rpc::TrafficLightState state); - + /// @note This function does not call the simulator, it returns the data + /// received in the last tick. rpc::TrafficLightState GetState() const; void SetGreenTime(float green_time); + /// @note This function does not call the simulator, it returns the data + /// received in the last tick. float GetGreenTime() const; void SetYellowTime(float yellow_time); + /// @note This function does not call the simulator, it returns the data + /// received in the last tick. float GetYellowTime() const; void SetRedTime(float red_time); + /// @note This function does not call the simulator, it returns the data + /// received in the last tick. float GetRedTime() const; + /// @note This function does not call the simulator, it returns the data + /// received in the last tick. float GetElapsedTime() const; void Freeze(bool freeze); + /// @note This function does not call the simulator, it returns the data + /// received in the last tick. bool IsFrozen() const; - }; } // namespace client diff --git a/LibCarla/source/carla/client/TrafficSign.h b/LibCarla/source/carla/client/TrafficSign.h new file mode 100644 index 000000000..f14b99370 --- /dev/null +++ b/LibCarla/source/carla/client/TrafficSign.h @@ -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 . + +#pragma once + +#include "carla/client/Actor.h" + +namespace carla { +namespace client { + + class TrafficSign : public Actor { + public: + + explicit TrafficSign(ActorInitializer init) : Actor(std::move(init)) {} + + const geom::BoundingBox &GetTriggerVolume() const { + return ActorState::GetBoundingBox(); + } + }; + +} // namespace client +} // namespace carla diff --git a/LibCarla/source/carla/client/Vehicle.h b/LibCarla/source/carla/client/Vehicle.h index 492efb840..c8ded8d5a 100644 --- a/LibCarla/source/carla/client/Vehicle.h +++ b/LibCarla/source/carla/client/Vehicle.h @@ -23,6 +23,8 @@ namespace client { explicit Vehicle(ActorInitializer init) : Actor(std::move(init)) {} + using ActorState::GetBoundingBox; + /// Switch on/off this vehicle's autopilot. void SetAutopilot(bool enabled = true); @@ -34,19 +36,35 @@ namespace client { /// Return the control last applied to this vehicle. /// - /// @note The following functions do not call the simulator, they return the - /// data + /// @note This function does not call the simulator, it returns the data /// received in the last tick. - ////////////////////////////////////////////////////////////////////////////////// Control GetControl() const; PhysicsControl GetPhysicsControl() const; + /// Return the speed limit currently affecting this vehicle. + /// + /// @note This function does not call the simulator, it returns the data + /// received in the last tick. float GetSpeedLimit() const; + /// Return the state of the traffic light currently affecting this vehicle. + /// + /// @return Green If no traffic light is affecting the vehicle. + /// + /// @note This function does not call the simulator, it returns the data + /// received in the last tick. rpc::TrafficLightState GetTrafficLightState() const; + /// Return whether a traffic light is affecting this vehicle. + /// + /// @note This function does not call the simulator, it returns the data + /// received in the last tick. bool IsAtTrafficLight(); + /// Retrieve the traffic light actor currently affecting this vehicle. + /// + /// @note This function does not call the simulator, it returns the data + /// received in the last tick. SharedPtr GetTrafficLight() const; diff --git a/LibCarla/source/carla/client/Walker.h b/LibCarla/source/carla/client/Walker.h index d4648116b..bd40ac87a 100644 --- a/LibCarla/source/carla/client/Walker.h +++ b/LibCarla/source/carla/client/Walker.h @@ -19,6 +19,8 @@ namespace client { explicit Walker(ActorInitializer init) : Actor(std::move(init)) {} + using ActorState::GetBoundingBox; + /// Apply @a control to this Walker. void ApplyControl(const Control &control); diff --git a/LibCarla/source/carla/client/detail/ActorFactory.cpp b/LibCarla/source/carla/client/detail/ActorFactory.cpp index 6f654b22c..e97ec5efd 100644 --- a/LibCarla/source/carla/client/detail/ActorFactory.cpp +++ b/LibCarla/source/carla/client/detail/ActorFactory.cpp @@ -9,10 +9,11 @@ #include "carla/Logging.h" #include "carla/StringUtil.h" #include "carla/client/Actor.h" -#include "carla/client/LaneDetector.h" #include "carla/client/GnssSensor.h" +#include "carla/client/LaneDetector.h" #include "carla/client/ServerSideSensor.h" #include "carla/client/TrafficLight.h" +#include "carla/client/TrafficSign.h" #include "carla/client/Vehicle.h" #include "carla/client/Walker.h" #include "carla/client/World.h" @@ -84,6 +85,8 @@ namespace detail { return MakeActorImpl(std::move(init), gc); } else if (StringUtil::StartsWith(description.description.id, "traffic.traffic_light")) { return MakeActorImpl(std::move(init), gc); + } else if (StringUtil::StartsWith(description.description.id, "traffic.")) { + return MakeActorImpl(std::move(init), gc); } return MakeActorImpl(std::move(init), gc); } diff --git a/LibCarla/source/carla/client/detail/ActorState.h b/LibCarla/source/carla/client/detail/ActorState.h index cde421d8c..e722cfc2e 100644 --- a/LibCarla/source/carla/client/detail/ActorState.h +++ b/LibCarla/source/carla/client/detail/ActorState.h @@ -34,10 +34,6 @@ namespace detail { return _display_id; } - const geom::BoundingBox &GetBoundingBox() const { - return _description.bounding_box; - } - const std::vector &GetSemanticTags() const { return _description.semantic_tags; } @@ -57,6 +53,10 @@ namespace detail { protected: + const geom::BoundingBox &GetBoundingBox() const { + return _description.bounding_box; + } + const rpc::Actor &GetActorDescription() const { return _description; } diff --git a/PythonAPI/source/libcarla/Actor.cpp b/PythonAPI/source/libcarla/Actor.cpp index 2415978b1..43d57fb92 100644 --- a/PythonAPI/source/libcarla/Actor.cpp +++ b/PythonAPI/source/libcarla/Actor.cpp @@ -44,80 +44,85 @@ void export_actor() { ; class_>("Actor", no_init) - // work-around, force return copy to resolve Actor instead of ActorState. - .add_property("id", CALL_RETURNING_COPY(cc::Actor, GetId)) - .add_property("type_id", CALL_RETURNING_COPY(cc::Actor, GetTypeId)) - .add_property("parent", CALL_RETURNING_COPY(cc::Actor, GetParent)) - .add_property("semantic_tags", &GetSemanticTags) - .add_property("is_alive", CALL_RETURNING_COPY(cc::Actor, IsAlive)) - .add_property("attributes", +[] (const cc::Actor &self) { - boost::python::dict atttribute_dict; - for (auto &&attribute_value : self.GetAttributes()) { - atttribute_dict[attribute_value.GetId()] = attribute_value.GetValue(); - } - return atttribute_dict; - }) - .def("get_world", CALL_RETURNING_COPY(cc::Actor, GetWorld)) - .def("get_location", &cc::Actor::GetLocation) - .def("get_transform", &cc::Actor::GetTransform) - .def("get_velocity", &cc::Actor::GetVelocity) - .def("get_angular_velocity", &cc::Actor::GetAngularVelocity) - .def("get_acceleration", &cc::Actor::GetAcceleration) - .def("set_location", &cc::Actor::SetLocation, (arg("location"))) - .def("set_transform", &cc::Actor::SetTransform, (arg("transform"))) - .def("set_velocity", &cc::Actor::SetVelocity, (arg("vector"))) - .def("set_angular_velocity", &cc::Actor::SetAngularVelocity, (arg("vector"))) - .def("add_impulse", &cc::Actor::AddImpulse, (arg("vector"))) - .def("set_simulate_physics", &cc::Actor::SetSimulatePhysics, (arg("enabled") = true)) - .def("destroy", CALL_WITHOUT_GIL(cc::Actor, Destroy)) - .def(self_ns::str(self_ns::self)) + // work-around, force return copy to resolve Actor instead of ActorState. + .add_property("id", CALL_RETURNING_COPY(cc::Actor, GetId)) + .add_property("type_id", CALL_RETURNING_COPY(cc::Actor, GetTypeId)) + .add_property("parent", CALL_RETURNING_COPY(cc::Actor, GetParent)) + .add_property("semantic_tags", &GetSemanticTags) + .add_property("is_alive", CALL_RETURNING_COPY(cc::Actor, IsAlive)) + .add_property("attributes", +[] (const cc::Actor &self) { + boost::python::dict atttribute_dict; + for (auto &&attribute_value : self.GetAttributes()) { + atttribute_dict[attribute_value.GetId()] = attribute_value.GetValue(); + } + return atttribute_dict; + }) + .def("get_world", CALL_RETURNING_COPY(cc::Actor, GetWorld)) + .def("get_location", &cc::Actor::GetLocation) + .def("get_transform", &cc::Actor::GetTransform) + .def("get_velocity", &cc::Actor::GetVelocity) + .def("get_angular_velocity", &cc::Actor::GetAngularVelocity) + .def("get_acceleration", &cc::Actor::GetAcceleration) + .def("set_location", &cc::Actor::SetLocation, (arg("location"))) + .def("set_transform", &cc::Actor::SetTransform, (arg("transform"))) + .def("set_velocity", &cc::Actor::SetVelocity, (arg("vector"))) + .def("set_angular_velocity", &cc::Actor::SetAngularVelocity, (arg("vector"))) + .def("add_impulse", &cc::Actor::AddImpulse, (arg("vector"))) + .def("set_simulate_physics", &cc::Actor::SetSimulatePhysics, (arg("enabled") = true)) + .def("destroy", CALL_WITHOUT_GIL(cc::Actor, Destroy)) + .def(self_ns::str(self_ns::self)) ; - class_, boost::noncopyable, boost::shared_ptr>("Vehicle", - no_init) - .add_property("bounding_box", CALL_RETURNING_COPY(cc::Vehicle, GetBoundingBox)) - .def("apply_control", &cc::Vehicle::ApplyControl, (arg("control"))) - .def("get_control", &cc::Vehicle::GetControl) - .def("apply_physics_control", &cc::Vehicle::ApplyPhysicsControl, (arg("physics_control"))) - .def("get_physics_control", CONST_CALL_WITHOUT_GIL(cc::Vehicle, GetPhysicsControl)) - .def("set_autopilot", &cc::Vehicle::SetAutopilot, (arg("enabled") = true)) - .def("get_speed_limit", &cc::Vehicle::GetSpeedLimit) - .def("get_traffic_light_state", &cc::Vehicle::GetTrafficLightState) - .def("is_at_traffic_light", &cc::Vehicle::IsAtTrafficLight) - .def("get_traffic_light", &cc::Vehicle::GetTrafficLight) - .def(self_ns::str(self_ns::self)) + class_, boost::noncopyable, boost::shared_ptr>("Vehicle", no_init) + .add_property("bounding_box", CALL_RETURNING_COPY(cc::Vehicle, GetBoundingBox)) + .def("apply_control", &cc::Vehicle::ApplyControl, (arg("control"))) + .def("get_control", &cc::Vehicle::GetControl) + .def("apply_physics_control", &cc::Vehicle::ApplyPhysicsControl, (arg("physics_control"))) + .def("get_physics_control", CONST_CALL_WITHOUT_GIL(cc::Vehicle, GetPhysicsControl)) + .def("set_autopilot", &cc::Vehicle::SetAutopilot, (arg("enabled") = true)) + .def("get_speed_limit", &cc::Vehicle::GetSpeedLimit) + .def("get_traffic_light_state", &cc::Vehicle::GetTrafficLightState) + .def("is_at_traffic_light", &cc::Vehicle::IsAtTrafficLight) + .def("get_traffic_light", &cc::Vehicle::GetTrafficLight) + .def(self_ns::str(self_ns::self)) ; class_, boost::noncopyable, boost::shared_ptr>("Walker", no_init) - .add_property("bounding_box", CALL_RETURNING_COPY(cc::Walker, GetBoundingBox)) - .def("apply_control", &cc::Walker::ApplyControl, (arg("control"))) - .def("get_control", &cc::Walker::GetWalkerControl) - .def(self_ns::str(self_ns::self)) + .add_property("bounding_box", CALL_RETURNING_COPY(cc::Walker, GetBoundingBox)) + .def("apply_control", &cc::Walker::ApplyControl, (arg("control"))) + .def("get_control", &cc::Walker::GetWalkerControl) + .def(self_ns::str(self_ns::self)) + ; + + class_, boost::noncopyable, boost::shared_ptr>( + "TrafficSign", + no_init) + .add_property("trigger_volume", CALL_RETURNING_COPY(cc::TrafficSign, GetTriggerVolume)) ; enum_("TrafficLightState") - .value("Red", cr::TrafficLightState::Red) - .value("Yellow", cr::TrafficLightState::Yellow) - .value("Green", cr::TrafficLightState::Green) - .value("Off", cr::TrafficLightState::Off) - .value("Unknown", cr::TrafficLightState::Unknown) + .value("Red", cr::TrafficLightState::Red) + .value("Yellow", cr::TrafficLightState::Yellow) + .value("Green", cr::TrafficLightState::Green) + .value("Off", cr::TrafficLightState::Off) + .value("Unknown", cr::TrafficLightState::Unknown) ; - class_, boost::noncopyable, boost::shared_ptr>( + class_, boost::noncopyable, boost::shared_ptr>( "TrafficLight", no_init) - .add_property("state", &cc::TrafficLight::GetState) - .def("set_state", &cc::TrafficLight::SetState, (arg("state"))) - .def("get_state", &cc::TrafficLight::GetState) - .def("set_green_time", &cc::TrafficLight::SetGreenTime, (arg("green_time"))) - .def("get_green_time", &cc::TrafficLight::GetGreenTime) - .def("set_yellow_time", &cc::TrafficLight::SetYellowTime, (arg("yellow_time"))) - .def("get_yellow_time", &cc::TrafficLight::GetYellowTime) - .def("set_red_time", &cc::TrafficLight::SetRedTime, (arg("red_time"))) - .def("get_red_time", &cc::TrafficLight::GetRedTime) - .def("get_elapsed_time", &cc::TrafficLight::GetElapsedTime) - .def("freeze", &cc::TrafficLight::Freeze, (arg("freeze"))) - .def("is_frozen", &cc::TrafficLight::IsFrozen) - .def(self_ns::str(self_ns::self)) + .add_property("state", &cc::TrafficLight::GetState) + .def("set_state", &cc::TrafficLight::SetState, (arg("state"))) + .def("get_state", &cc::TrafficLight::GetState) + .def("set_green_time", &cc::TrafficLight::SetGreenTime, (arg("green_time"))) + .def("get_green_time", &cc::TrafficLight::GetGreenTime) + .def("set_yellow_time", &cc::TrafficLight::SetYellowTime, (arg("yellow_time"))) + .def("get_yellow_time", &cc::TrafficLight::GetYellowTime) + .def("set_red_time", &cc::TrafficLight::SetRedTime, (arg("red_time"))) + .def("get_red_time", &cc::TrafficLight::GetRedTime) + .def("get_elapsed_time", &cc::TrafficLight::GetElapsedTime) + .def("freeze", &cc::TrafficLight::Freeze, (arg("freeze"))) + .def("is_frozen", &cc::TrafficLight::IsFrozen) + .def(self_ns::str(self_ns::self)) ; } diff --git a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Traffic/TrafficSignBase.h b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Traffic/TrafficSignBase.h index 552169c33..c2fe59d03 100644 --- a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Traffic/TrafficSignBase.h +++ b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Traffic/TrafficSignBase.h @@ -12,6 +12,8 @@ #include "TrafficSignBase.generated.h" +class UBoxComponent; + UENUM(BlueprintType) enum class ETrafficSignState : uint8 { UNKNOWN = 0u UMETA(DisplayName = "UNKNOWN"), @@ -49,6 +51,9 @@ public: TrafficSignState = State; } + UFUNCTION(BlueprintImplementableEvent) + UBoxComponent *GetTriggerVolume() const; + private: UPROPERTY(Category = "Traffic Sign", EditAnywhere) diff --git a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Util/BoundingBoxCalculator.cpp b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Util/BoundingBoxCalculator.cpp index 49cdd790e..d0a296fba 100644 --- a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Util/BoundingBoxCalculator.cpp +++ b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Util/BoundingBoxCalculator.cpp @@ -7,6 +7,7 @@ #include "Carla.h" #include "Carla/Util/BoundingBoxCalculator.h" +#include "Carla/Traffic/TrafficSignBase.h" #include "Carla/Vehicle/CarlaWheeledVehicle.h" #include "Components/CapsuleComponent.h" @@ -39,6 +40,23 @@ FBoundingBox UBoundingBoxCalculator::GetActorBoundingBox(const AActor *Actor) return {Origin, Extent}; } } + // Traffic sign. + auto TrafficSign = Cast(Actor); + if (TrafficSign != nullptr) + { + auto TriggerVolume = TrafficSign->GetTriggerVolume(); + if (TriggerVolume != nullptr) + { + FVector Origin = TriggerVolume->GetRelativeTransform().GetTranslation(); + FVector Extent = TriggerVolume->GetScaledBoxExtent(); + return {Origin, Extent}; + } + else + { + UE_LOG(LogCarla, Warning, TEXT("Traffic sign missing trigger volume: %s"), *Actor->GetName()); + return {}; + } + } } return {}; } diff --git a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Util/BoundingBoxCalculator.h b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Util/BoundingBoxCalculator.h index 816ed173c..c1546bd09 100644 --- a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Util/BoundingBoxCalculator.h +++ b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Util/BoundingBoxCalculator.h @@ -25,6 +25,8 @@ public: /// /// @warning If the actor type is not supported a default initialized bounding /// box is returned. + /// + /// @warning Traffic signs return its trigger box instead. UFUNCTION(Category = "Carla Actor", BlueprintCallable) static FBoundingBox GetActorBoundingBox(const AActor *Actor); };