Expose traffic sign's trigger volumes on Python API

This commit is contained in:
nsubiron 2019-02-08 14:37:31 +01:00
parent 6701f22ab1
commit 3e93782c98
11 changed files with 167 additions and 80 deletions

View File

@ -20,7 +20,7 @@
* Fixed static objects present in the map were marked as "movable" * Fixed static objects present in the map were marked as "movable"
* Fixed BP_MultipleFloor, tweaked offset in BaseFloor to adjust meshes between them * 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 * 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 ## CARLA 0.9.3

View File

@ -6,43 +6,52 @@
#pragma once #pragma once
#include "carla/client/Actor.h" #include "carla/client/TrafficSign.h"
#include "carla/rpc/TrafficLightState.h" #include "carla/rpc/TrafficLightState.h"
namespace carla { namespace carla {
namespace client { namespace client {
class TrafficLight : public Actor { class TrafficLight : public TrafficSign {
public: 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. /// Return the current state of the traffic light.
/// ///
/// @note These functions do not call the simulator, they return the /// @note This function does not call the simulator, it returns the data
/// data received in the last tick. /// received in the last tick.
void SetState(rpc::TrafficLightState state);
rpc::TrafficLightState GetState() const; rpc::TrafficLightState GetState() const;
void SetGreenTime(float green_time); 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; float GetGreenTime() const;
void SetYellowTime(float yellow_time); 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; float GetYellowTime() const;
void SetRedTime(float red_time); 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; float GetRedTime() const;
/// @note This function does not call the simulator, it returns the data
/// received in the last tick.
float GetElapsedTime() const; float GetElapsedTime() const;
void Freeze(bool freeze); void Freeze(bool freeze);
/// @note This function does not call the simulator, it returns the data
/// received in the last tick.
bool IsFrozen() const; bool IsFrozen() const;
}; };
} // namespace client } // namespace client

View File

@ -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 <https://opensource.org/licenses/MIT>.
#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

View File

@ -23,6 +23,8 @@ namespace client {
explicit Vehicle(ActorInitializer init) : Actor(std::move(init)) {} explicit Vehicle(ActorInitializer init) : Actor(std::move(init)) {}
using ActorState::GetBoundingBox;
/// Switch on/off this vehicle's autopilot. /// Switch on/off this vehicle's autopilot.
void SetAutopilot(bool enabled = true); void SetAutopilot(bool enabled = true);
@ -34,19 +36,35 @@ namespace client {
/// Return the control last applied to this vehicle. /// Return the control last applied to this vehicle.
/// ///
/// @note The following functions do not call the simulator, they return the /// @note This function does not call the simulator, it returns the data
/// data
/// received in the last tick. /// received in the last tick.
//////////////////////////////////////////////////////////////////////////////////
Control GetControl() const; Control GetControl() const;
PhysicsControl GetPhysicsControl() 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; 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; 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(); 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<TrafficLight> GetTrafficLight() const; SharedPtr<TrafficLight> GetTrafficLight() const;

View File

@ -19,6 +19,8 @@ namespace client {
explicit Walker(ActorInitializer init) : Actor(std::move(init)) {} explicit Walker(ActorInitializer init) : Actor(std::move(init)) {}
using ActorState::GetBoundingBox;
/// Apply @a control to this Walker. /// Apply @a control to this Walker.
void ApplyControl(const Control &control); void ApplyControl(const Control &control);

View File

@ -9,10 +9,11 @@
#include "carla/Logging.h" #include "carla/Logging.h"
#include "carla/StringUtil.h" #include "carla/StringUtil.h"
#include "carla/client/Actor.h" #include "carla/client/Actor.h"
#include "carla/client/LaneDetector.h"
#include "carla/client/GnssSensor.h" #include "carla/client/GnssSensor.h"
#include "carla/client/LaneDetector.h"
#include "carla/client/ServerSideSensor.h" #include "carla/client/ServerSideSensor.h"
#include "carla/client/TrafficLight.h" #include "carla/client/TrafficLight.h"
#include "carla/client/TrafficSign.h"
#include "carla/client/Vehicle.h" #include "carla/client/Vehicle.h"
#include "carla/client/Walker.h" #include "carla/client/Walker.h"
#include "carla/client/World.h" #include "carla/client/World.h"
@ -84,6 +85,8 @@ namespace detail {
return MakeActorImpl<Walker>(std::move(init), gc); return MakeActorImpl<Walker>(std::move(init), gc);
} else if (StringUtil::StartsWith(description.description.id, "traffic.traffic_light")) { } else if (StringUtil::StartsWith(description.description.id, "traffic.traffic_light")) {
return MakeActorImpl<TrafficLight>(std::move(init), gc); return MakeActorImpl<TrafficLight>(std::move(init), gc);
} else if (StringUtil::StartsWith(description.description.id, "traffic.")) {
return MakeActorImpl<TrafficSign>(std::move(init), gc);
} }
return MakeActorImpl<Actor>(std::move(init), gc); return MakeActorImpl<Actor>(std::move(init), gc);
} }

View File

@ -34,10 +34,6 @@ namespace detail {
return _display_id; return _display_id;
} }
const geom::BoundingBox &GetBoundingBox() const {
return _description.bounding_box;
}
const std::vector<uint8_t> &GetSemanticTags() const { const std::vector<uint8_t> &GetSemanticTags() const {
return _description.semantic_tags; return _description.semantic_tags;
} }
@ -57,6 +53,10 @@ namespace detail {
protected: protected:
const geom::BoundingBox &GetBoundingBox() const {
return _description.bounding_box;
}
const rpc::Actor &GetActorDescription() const { const rpc::Actor &GetActorDescription() const {
return _description; return _description;
} }

View File

@ -44,80 +44,85 @@ void export_actor() {
; ;
class_<cc::Actor, boost::noncopyable, boost::shared_ptr<cc::Actor>>("Actor", no_init) class_<cc::Actor, boost::noncopyable, boost::shared_ptr<cc::Actor>>("Actor", no_init)
// work-around, force return copy to resolve Actor instead of ActorState. // work-around, force return copy to resolve Actor instead of ActorState.
.add_property("id", CALL_RETURNING_COPY(cc::Actor, GetId)) .add_property("id", CALL_RETURNING_COPY(cc::Actor, GetId))
.add_property("type_id", CALL_RETURNING_COPY(cc::Actor, GetTypeId)) .add_property("type_id", CALL_RETURNING_COPY(cc::Actor, GetTypeId))
.add_property("parent", CALL_RETURNING_COPY(cc::Actor, GetParent)) .add_property("parent", CALL_RETURNING_COPY(cc::Actor, GetParent))
.add_property("semantic_tags", &GetSemanticTags) .add_property("semantic_tags", &GetSemanticTags)
.add_property("is_alive", CALL_RETURNING_COPY(cc::Actor, IsAlive)) .add_property("is_alive", CALL_RETURNING_COPY(cc::Actor, IsAlive))
.add_property("attributes", +[] (const cc::Actor &self) { .add_property("attributes", +[] (const cc::Actor &self) {
boost::python::dict atttribute_dict; boost::python::dict atttribute_dict;
for (auto &&attribute_value : self.GetAttributes()) { for (auto &&attribute_value : self.GetAttributes()) {
atttribute_dict[attribute_value.GetId()] = attribute_value.GetValue(); atttribute_dict[attribute_value.GetId()] = attribute_value.GetValue();
} }
return atttribute_dict; return atttribute_dict;
}) })
.def("get_world", CALL_RETURNING_COPY(cc::Actor, GetWorld)) .def("get_world", CALL_RETURNING_COPY(cc::Actor, GetWorld))
.def("get_location", &cc::Actor::GetLocation) .def("get_location", &cc::Actor::GetLocation)
.def("get_transform", &cc::Actor::GetTransform) .def("get_transform", &cc::Actor::GetTransform)
.def("get_velocity", &cc::Actor::GetVelocity) .def("get_velocity", &cc::Actor::GetVelocity)
.def("get_angular_velocity", &cc::Actor::GetAngularVelocity) .def("get_angular_velocity", &cc::Actor::GetAngularVelocity)
.def("get_acceleration", &cc::Actor::GetAcceleration) .def("get_acceleration", &cc::Actor::GetAcceleration)
.def("set_location", &cc::Actor::SetLocation, (arg("location"))) .def("set_location", &cc::Actor::SetLocation, (arg("location")))
.def("set_transform", &cc::Actor::SetTransform, (arg("transform"))) .def("set_transform", &cc::Actor::SetTransform, (arg("transform")))
.def("set_velocity", &cc::Actor::SetVelocity, (arg("vector"))) .def("set_velocity", &cc::Actor::SetVelocity, (arg("vector")))
.def("set_angular_velocity", &cc::Actor::SetAngularVelocity, (arg("vector"))) .def("set_angular_velocity", &cc::Actor::SetAngularVelocity, (arg("vector")))
.def("add_impulse", &cc::Actor::AddImpulse, (arg("vector"))) .def("add_impulse", &cc::Actor::AddImpulse, (arg("vector")))
.def("set_simulate_physics", &cc::Actor::SetSimulatePhysics, (arg("enabled") = true)) .def("set_simulate_physics", &cc::Actor::SetSimulatePhysics, (arg("enabled") = true))
.def("destroy", CALL_WITHOUT_GIL(cc::Actor, Destroy)) .def("destroy", CALL_WITHOUT_GIL(cc::Actor, Destroy))
.def(self_ns::str(self_ns::self)) .def(self_ns::str(self_ns::self))
; ;
class_<cc::Vehicle, bases<cc::Actor>, boost::noncopyable, boost::shared_ptr<cc::Vehicle>>("Vehicle", class_<cc::Vehicle, bases<cc::Actor>, boost::noncopyable, boost::shared_ptr<cc::Vehicle>>("Vehicle", no_init)
no_init) .add_property("bounding_box", CALL_RETURNING_COPY(cc::Vehicle, GetBoundingBox))
.add_property("bounding_box", CALL_RETURNING_COPY(cc::Vehicle, GetBoundingBox)) .def("apply_control", &cc::Vehicle::ApplyControl, (arg("control")))
.def("apply_control", &cc::Vehicle::ApplyControl, (arg("control"))) .def("get_control", &cc::Vehicle::GetControl)
.def("get_control", &cc::Vehicle::GetControl) .def("apply_physics_control", &cc::Vehicle::ApplyPhysicsControl, (arg("physics_control")))
.def("apply_physics_control", &cc::Vehicle::ApplyPhysicsControl, (arg("physics_control"))) .def("get_physics_control", CONST_CALL_WITHOUT_GIL(cc::Vehicle, GetPhysicsControl))
.def("get_physics_control", CONST_CALL_WITHOUT_GIL(cc::Vehicle, GetPhysicsControl)) .def("set_autopilot", &cc::Vehicle::SetAutopilot, (arg("enabled") = true))
.def("set_autopilot", &cc::Vehicle::SetAutopilot, (arg("enabled") = true)) .def("get_speed_limit", &cc::Vehicle::GetSpeedLimit)
.def("get_speed_limit", &cc::Vehicle::GetSpeedLimit) .def("get_traffic_light_state", &cc::Vehicle::GetTrafficLightState)
.def("get_traffic_light_state", &cc::Vehicle::GetTrafficLightState) .def("is_at_traffic_light", &cc::Vehicle::IsAtTrafficLight)
.def("is_at_traffic_light", &cc::Vehicle::IsAtTrafficLight) .def("get_traffic_light", &cc::Vehicle::GetTrafficLight)
.def("get_traffic_light", &cc::Vehicle::GetTrafficLight) .def(self_ns::str(self_ns::self))
.def(self_ns::str(self_ns::self))
; ;
class_<cc::Walker, bases<cc::Actor>, boost::noncopyable, boost::shared_ptr<cc::Walker>>("Walker", no_init) class_<cc::Walker, bases<cc::Actor>, boost::noncopyable, boost::shared_ptr<cc::Walker>>("Walker", no_init)
.add_property("bounding_box", CALL_RETURNING_COPY(cc::Walker, GetBoundingBox)) .add_property("bounding_box", CALL_RETURNING_COPY(cc::Walker, GetBoundingBox))
.def("apply_control", &cc::Walker::ApplyControl, (arg("control"))) .def("apply_control", &cc::Walker::ApplyControl, (arg("control")))
.def("get_control", &cc::Walker::GetWalkerControl) .def("get_control", &cc::Walker::GetWalkerControl)
.def(self_ns::str(self_ns::self)) .def(self_ns::str(self_ns::self))
;
class_<cc::TrafficSign, bases<cc::Actor>, boost::noncopyable, boost::shared_ptr<cc::TrafficSign>>(
"TrafficSign",
no_init)
.add_property("trigger_volume", CALL_RETURNING_COPY(cc::TrafficSign, GetTriggerVolume))
; ;
enum_<cr::TrafficLightState>("TrafficLightState") enum_<cr::TrafficLightState>("TrafficLightState")
.value("Red", cr::TrafficLightState::Red) .value("Red", cr::TrafficLightState::Red)
.value("Yellow", cr::TrafficLightState::Yellow) .value("Yellow", cr::TrafficLightState::Yellow)
.value("Green", cr::TrafficLightState::Green) .value("Green", cr::TrafficLightState::Green)
.value("Off", cr::TrafficLightState::Off) .value("Off", cr::TrafficLightState::Off)
.value("Unknown", cr::TrafficLightState::Unknown) .value("Unknown", cr::TrafficLightState::Unknown)
; ;
class_<cc::TrafficLight, bases<cc::Actor>, boost::noncopyable, boost::shared_ptr<cc::TrafficLight>>( class_<cc::TrafficLight, bases<cc::TrafficSign>, boost::noncopyable, boost::shared_ptr<cc::TrafficLight>>(
"TrafficLight", "TrafficLight",
no_init) no_init)
.add_property("state", &cc::TrafficLight::GetState) .add_property("state", &cc::TrafficLight::GetState)
.def("set_state", &cc::TrafficLight::SetState, (arg("state"))) .def("set_state", &cc::TrafficLight::SetState, (arg("state")))
.def("get_state", &cc::TrafficLight::GetState) .def("get_state", &cc::TrafficLight::GetState)
.def("set_green_time", &cc::TrafficLight::SetGreenTime, (arg("green_time"))) .def("set_green_time", &cc::TrafficLight::SetGreenTime, (arg("green_time")))
.def("get_green_time", &cc::TrafficLight::GetGreenTime) .def("get_green_time", &cc::TrafficLight::GetGreenTime)
.def("set_yellow_time", &cc::TrafficLight::SetYellowTime, (arg("yellow_time"))) .def("set_yellow_time", &cc::TrafficLight::SetYellowTime, (arg("yellow_time")))
.def("get_yellow_time", &cc::TrafficLight::GetYellowTime) .def("get_yellow_time", &cc::TrafficLight::GetYellowTime)
.def("set_red_time", &cc::TrafficLight::SetRedTime, (arg("red_time"))) .def("set_red_time", &cc::TrafficLight::SetRedTime, (arg("red_time")))
.def("get_red_time", &cc::TrafficLight::GetRedTime) .def("get_red_time", &cc::TrafficLight::GetRedTime)
.def("get_elapsed_time", &cc::TrafficLight::GetElapsedTime) .def("get_elapsed_time", &cc::TrafficLight::GetElapsedTime)
.def("freeze", &cc::TrafficLight::Freeze, (arg("freeze"))) .def("freeze", &cc::TrafficLight::Freeze, (arg("freeze")))
.def("is_frozen", &cc::TrafficLight::IsFrozen) .def("is_frozen", &cc::TrafficLight::IsFrozen)
.def(self_ns::str(self_ns::self)) .def(self_ns::str(self_ns::self))
; ;
} }

View File

@ -12,6 +12,8 @@
#include "TrafficSignBase.generated.h" #include "TrafficSignBase.generated.h"
class UBoxComponent;
UENUM(BlueprintType) UENUM(BlueprintType)
enum class ETrafficSignState : uint8 { enum class ETrafficSignState : uint8 {
UNKNOWN = 0u UMETA(DisplayName = "UNKNOWN"), UNKNOWN = 0u UMETA(DisplayName = "UNKNOWN"),
@ -49,6 +51,9 @@ public:
TrafficSignState = State; TrafficSignState = State;
} }
UFUNCTION(BlueprintImplementableEvent)
UBoxComponent *GetTriggerVolume() const;
private: private:
UPROPERTY(Category = "Traffic Sign", EditAnywhere) UPROPERTY(Category = "Traffic Sign", EditAnywhere)

View File

@ -7,6 +7,7 @@
#include "Carla.h" #include "Carla.h"
#include "Carla/Util/BoundingBoxCalculator.h" #include "Carla/Util/BoundingBoxCalculator.h"
#include "Carla/Traffic/TrafficSignBase.h"
#include "Carla/Vehicle/CarlaWheeledVehicle.h" #include "Carla/Vehicle/CarlaWheeledVehicle.h"
#include "Components/CapsuleComponent.h" #include "Components/CapsuleComponent.h"
@ -39,6 +40,23 @@ FBoundingBox UBoundingBoxCalculator::GetActorBoundingBox(const AActor *Actor)
return {Origin, Extent}; return {Origin, Extent};
} }
} }
// Traffic sign.
auto TrafficSign = Cast<ATrafficSignBase>(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 {}; return {};
} }

View File

@ -25,6 +25,8 @@ public:
/// ///
/// @warning If the actor type is not supported a default initialized bounding /// @warning If the actor type is not supported a default initialized bounding
/// box is returned. /// box is returned.
///
/// @warning Traffic signs return its trigger box instead.
UFUNCTION(Category = "Carla Actor", BlueprintCallable) UFUNCTION(Category = "Carla Actor", BlueprintCallable)
static FBoundingBox GetActorBoundingBox(const AActor *Actor); static FBoundingBox GetActorBoundingBox(const AActor *Actor);
}; };