Provide parent/attribute content of Actors via python interface
While creating the new carla ros bridge some extensions became necessary within CARLA: The parent property of an actor via python interface is not yet filled. Therefore, the parent_id of Actors has to be transferred from the CARLA server via rpc interface. In addition, actor attributes are published via python interface. Changes in detail: carla/rpc/Actor.h: - add parent_id field to the Actor class for rpc transport TheNewCarlaServer.cpp: - fill the parent_id field with the appropriate value client/ActorList: - added GetActor() function to get an actor by id client/ActorVariant: - added actor_list optional parameter to Get() and MakeActor() function which allows to query for the parent actor in case the actor_list is available client/ActorAttribute: - solved problem of independent rpc::ActorAttribute* classes by introduction of ActorAttributeValueAccess class, to be able to reuse most of the functions for both ActorAttribueValues and ActorAttributes ActorBlueprintFunctionLibrary: - extended actor attributes by attribute 'role_name' having {autopilot, scenario, ego_vehicle} as recommended values for vehicles or {front,back,...} for sensors to be able to distiguish the different actors in a meaningful way when transferring to ROS topic names - extended vehicle attributes by not-modifiable attribute 'object_type' to be defined at blueprint creation time to provide ground truth object classification type PythonAPI: - libcarla: provide the actor attributes within python as dictionary - make use of role_name attribute to provide information required for ROS bridge to distinguish ego vehicle from others
This commit is contained in:
parent
fd54b3ccf7
commit
bd710c339c
|
@ -90,6 +90,7 @@
|
|||
- `parent`
|
||||
- `semantic_tags`
|
||||
- `is_alive`
|
||||
- `attributes`
|
||||
- `get_world()`
|
||||
- `get_location()`
|
||||
- `get_transform()`
|
||||
|
|
|
@ -12,10 +12,10 @@
|
|||
namespace carla {
|
||||
namespace client {
|
||||
|
||||
#define LIBCARLA_THROW_INVALID_VALUE(message) throw InvalidAttributeValue(_attribute.id + ": " + message);
|
||||
#define LIBCARLA_THROW_INVALID_VALUE(message) throw InvalidAttributeValue(GetId() + ": " + message);
|
||||
#define LIBCARLA_THROW_BAD_VALUE_CAST(type) \
|
||||
if (GetType() != rpc::ActorAttributeType:: type) { \
|
||||
throw BadAttributeCast(_attribute.id + ": bad attribute cast: cannot convert to " #type); \
|
||||
throw BadAttributeCast(GetId() + ": bad attribute cast: cannot convert to " #type); \
|
||||
}
|
||||
|
||||
void ActorAttribute::Set(std::string value) {
|
||||
|
@ -29,28 +29,29 @@ namespace client {
|
|||
Validate();
|
||||
}
|
||||
|
||||
|
||||
template <>
|
||||
bool ActorAttribute::As<bool>() const {
|
||||
bool ActorAttributeValueAccess::As<bool>() const {
|
||||
LIBCARLA_THROW_BAD_VALUE_CAST(Bool);
|
||||
auto value = StringUtil::ToLowerCopy(_attribute.value);
|
||||
auto value = StringUtil::ToLowerCopy(GetValue());
|
||||
if (value == "true") {
|
||||
return true;
|
||||
} else if (value == "false") {
|
||||
return false;
|
||||
}
|
||||
LIBCARLA_THROW_INVALID_VALUE("invalid bool: " + _attribute.value);
|
||||
LIBCARLA_THROW_INVALID_VALUE("invalid bool: " + GetValue());
|
||||
}
|
||||
|
||||
template<>
|
||||
int ActorAttribute::As<int>() const {
|
||||
int ActorAttributeValueAccess::As<int>() const {
|
||||
LIBCARLA_THROW_BAD_VALUE_CAST(Int);
|
||||
return std::atoi(_attribute.value.c_str());
|
||||
return std::atoi(GetValue().c_str());
|
||||
}
|
||||
|
||||
template<>
|
||||
float ActorAttribute::As<float>() const {
|
||||
float ActorAttributeValueAccess::As<float>() const {
|
||||
LIBCARLA_THROW_BAD_VALUE_CAST(Float);
|
||||
double x = std::atof(_attribute.value.c_str());
|
||||
double x = std::atof(GetValue().c_str());
|
||||
if ((x > std::numeric_limits<float>::max()) ||
|
||||
(x < std::numeric_limits<float>::lowest())) {
|
||||
LIBCARLA_THROW_INVALID_VALUE("float overflow");
|
||||
|
@ -59,19 +60,19 @@ namespace client {
|
|||
}
|
||||
|
||||
template <>
|
||||
std::string ActorAttribute::As<std::string>() const {
|
||||
std::string ActorAttributeValueAccess::As<std::string>() const {
|
||||
LIBCARLA_THROW_BAD_VALUE_CAST(String);
|
||||
return _attribute.value;
|
||||
return GetValue();
|
||||
}
|
||||
|
||||
template <>
|
||||
sensor::data::Color ActorAttribute::As<sensor::data::Color>() const {
|
||||
sensor::data::Color ActorAttributeValueAccess::As<sensor::data::Color>() const {
|
||||
LIBCARLA_THROW_BAD_VALUE_CAST(RGBColor);
|
||||
|
||||
std::vector<std::string> channels;
|
||||
StringUtil::Split(channels, _attribute.value, ",");
|
||||
StringUtil::Split(channels, GetValue(), ",");
|
||||
if (channels.size() != 3u) {
|
||||
log_error("invalid color", _attribute.value);
|
||||
log_error("invalid color", GetValue());
|
||||
LIBCARLA_THROW_INVALID_VALUE("colors must have 3 channels (R,G,B)");
|
||||
}
|
||||
|
||||
|
@ -86,8 +87,8 @@ namespace client {
|
|||
return {to_int(channels[0u]), to_int(channels[1u]), to_int(channels[2u])};
|
||||
}
|
||||
|
||||
void ActorAttribute::Validate() const {
|
||||
switch (_attribute.type) {
|
||||
void ActorAttributeValueAccess::Validate() const {
|
||||
switch (GetType()) {
|
||||
case rpc::ActorAttributeType::Bool: As<rpc::ActorAttributeType::Bool>(); break;
|
||||
case rpc::ActorAttributeType::Int: As<rpc::ActorAttributeType::Int>(); break;
|
||||
case rpc::ActorAttributeType::Float: As<rpc::ActorAttributeType::Float>(); break;
|
||||
|
|
|
@ -44,36 +44,20 @@ namespace client {
|
|||
// -- ActorAttribute ---------------------------------------------------------
|
||||
// ===========================================================================
|
||||
|
||||
/// An attribute of an ActorBlueprint.
|
||||
class ActorAttribute {
|
||||
class ActorAttributeValueAccess
|
||||
{
|
||||
public:
|
||||
ActorAttributeValueAccess() = default;
|
||||
ActorAttributeValueAccess(ActorAttributeValueAccess const &) = default;
|
||||
ActorAttributeValueAccess(ActorAttributeValueAccess &&) = default;
|
||||
virtual ~ActorAttributeValueAccess() = default;
|
||||
|
||||
ActorAttribute(rpc::ActorAttribute attribute)
|
||||
: _attribute(std::move(attribute)) {
|
||||
Validate();
|
||||
}
|
||||
ActorAttributeValueAccess & operator= (ActorAttributeValueAccess const & ) = default;
|
||||
ActorAttributeValueAccess & operator= (ActorAttributeValueAccess && ) = default;
|
||||
|
||||
const std::string &GetId() const {
|
||||
return _attribute.id;
|
||||
}
|
||||
virtual const std::string &GetId() const = 0;
|
||||
|
||||
rpc::ActorAttributeType GetType() const {
|
||||
return _attribute.type;
|
||||
}
|
||||
|
||||
const std::vector<std::string> &GetRecommendedValues() const {
|
||||
return _attribute.recommended_values;
|
||||
}
|
||||
|
||||
bool IsModifiable() const {
|
||||
return _attribute.is_modifiable;
|
||||
}
|
||||
|
||||
/// Set the value of this attribute.
|
||||
///
|
||||
/// @throw InvalidAttributeValue if attribute is not modifiable.
|
||||
/// @throw InvalidAttributeValue if format does not match this type.
|
||||
void Set(std::string value);
|
||||
virtual rpc::ActorAttributeType GetType() const = 0;
|
||||
|
||||
/// Cast the value to the given type.
|
||||
///
|
||||
|
@ -96,68 +80,162 @@ namespace client {
|
|||
return !(*this == rhs);
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual const std::string &GetValue() const = 0;
|
||||
|
||||
void Validate() const;
|
||||
};
|
||||
|
||||
template <>
|
||||
bool ActorAttributeValueAccess::As<bool>() const;
|
||||
|
||||
template <>
|
||||
int ActorAttributeValueAccess::As<int>() const;
|
||||
|
||||
template <>
|
||||
float ActorAttributeValueAccess::As<float>() const;
|
||||
|
||||
template <>
|
||||
std::string ActorAttributeValueAccess::As<std::string>() const;
|
||||
|
||||
template <>
|
||||
sensor::data::Color ActorAttributeValueAccess::As<sensor::data::Color>() const;
|
||||
|
||||
template <>
|
||||
inline auto ActorAttributeValueAccess::As<rpc::ActorAttributeType::Bool>() const {
|
||||
return As<bool>();
|
||||
}
|
||||
|
||||
template <>
|
||||
inline auto ActorAttributeValueAccess::As<rpc::ActorAttributeType::Int>() const {
|
||||
return As<int>();
|
||||
}
|
||||
|
||||
template <>
|
||||
inline auto ActorAttributeValueAccess::As<rpc::ActorAttributeType::Float>() const {
|
||||
return As<float>();
|
||||
}
|
||||
|
||||
template <>
|
||||
inline auto ActorAttributeValueAccess::As<rpc::ActorAttributeType::String>() const {
|
||||
return As<std::string>();
|
||||
}
|
||||
|
||||
template <>
|
||||
inline auto ActorAttributeValueAccess::As<rpc::ActorAttributeType::RGBColor>() const {
|
||||
return As<sensor::data::Color>();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline bool ActorAttributeValueAccess::operator==(const T &rhs) const {
|
||||
return As<T>() == rhs;
|
||||
}
|
||||
|
||||
template <>
|
||||
inline bool ActorAttributeValueAccess::operator==(const ActorAttributeValueAccess &rhs) const {
|
||||
return
|
||||
(GetType() == rhs.GetType()) &&
|
||||
(GetValue() == rhs.GetValue());
|
||||
}
|
||||
|
||||
class ActorAttributeValue: public ActorAttributeValueAccess {
|
||||
|
||||
public:
|
||||
ActorAttributeValue(rpc::ActorAttributeValue attribute):
|
||||
_attribute(std::move(attribute))
|
||||
{
|
||||
Validate();
|
||||
}
|
||||
ActorAttributeValue(ActorAttributeValue const &) = default;
|
||||
ActorAttributeValue(ActorAttributeValue &&) = default;
|
||||
virtual ~ActorAttributeValue() = default;
|
||||
|
||||
ActorAttributeValue & operator= (ActorAttributeValue const & ) = default;
|
||||
ActorAttributeValue & operator= (ActorAttributeValue && ) = default;
|
||||
|
||||
virtual const std::string &GetId() const override {
|
||||
return _attribute.id;
|
||||
}
|
||||
|
||||
virtual rpc::ActorAttributeType GetType() const override {
|
||||
return _attribute.type;
|
||||
}
|
||||
|
||||
/// Serialize this object as a carla::rpc::ActorAttributeValue.
|
||||
operator rpc::ActorAttributeValue() const{
|
||||
return _attribute;
|
||||
}
|
||||
|
||||
virtual const std::string &GetValue() const override {
|
||||
return _attribute.value;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
rpc::ActorAttributeValue _attribute;
|
||||
};
|
||||
|
||||
template <>
|
||||
inline bool ActorAttributeValueAccess::operator==(const ActorAttributeValue &rhs) const {
|
||||
return rhs.operator==(*this);
|
||||
}
|
||||
|
||||
/// An attribute of an ActorBlueprint.
|
||||
class ActorAttribute: public ActorAttributeValueAccess {
|
||||
|
||||
public:
|
||||
ActorAttribute(rpc::ActorAttribute attribute)
|
||||
: ActorAttributeValueAccess(),
|
||||
_attribute(std::move(attribute)) {
|
||||
Validate();
|
||||
}
|
||||
|
||||
ActorAttribute(ActorAttribute const &) = default;
|
||||
ActorAttribute(ActorAttribute &&) = default;
|
||||
virtual ~ActorAttribute() = default;
|
||||
|
||||
ActorAttribute & operator= (ActorAttribute const & ) = default;
|
||||
ActorAttribute & operator= (ActorAttribute && ) = default;
|
||||
|
||||
virtual const std::string &GetId() const override {
|
||||
return _attribute.id;
|
||||
}
|
||||
|
||||
virtual rpc::ActorAttributeType GetType() const override {
|
||||
return _attribute.type;
|
||||
}
|
||||
|
||||
const std::vector<std::string> &GetRecommendedValues() const {
|
||||
return _attribute.recommended_values;
|
||||
}
|
||||
|
||||
bool IsModifiable() const {
|
||||
return _attribute.is_modifiable;
|
||||
}
|
||||
|
||||
/// Set the value of this attribute.
|
||||
///
|
||||
/// @throw InvalidAttributeValue if attribute is not modifiable.
|
||||
/// @throw InvalidAttributeValue if format does not match this type.
|
||||
void Set(std::string value);
|
||||
|
||||
/// Serialize this object as a carla::rpc::ActorAttributeValue.
|
||||
operator rpc::ActorAttributeValue() const {
|
||||
return _attribute;
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual const std::string &GetValue() const override {
|
||||
return _attribute.value;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
void Validate() const;
|
||||
|
||||
rpc::ActorAttribute _attribute;
|
||||
};
|
||||
|
||||
template <>
|
||||
bool ActorAttribute::As<bool>() const;
|
||||
|
||||
template <>
|
||||
int ActorAttribute::As<int>() const;
|
||||
|
||||
template <>
|
||||
float ActorAttribute::As<float>() const;
|
||||
|
||||
template <>
|
||||
std::string ActorAttribute::As<std::string>() const;
|
||||
|
||||
template <>
|
||||
sensor::data::Color ActorAttribute::As<sensor::data::Color>() const;
|
||||
|
||||
template <>
|
||||
inline auto ActorAttribute::As<rpc::ActorAttributeType::Bool>() const {
|
||||
return As<bool>();
|
||||
}
|
||||
|
||||
template <>
|
||||
inline auto ActorAttribute::As<rpc::ActorAttributeType::Int>() const {
|
||||
return As<int>();
|
||||
}
|
||||
|
||||
template <>
|
||||
inline auto ActorAttribute::As<rpc::ActorAttributeType::Float>() const {
|
||||
return As<float>();
|
||||
}
|
||||
|
||||
template <>
|
||||
inline auto ActorAttribute::As<rpc::ActorAttributeType::String>() const {
|
||||
return As<std::string>();
|
||||
}
|
||||
|
||||
template <>
|
||||
inline auto ActorAttribute::As<rpc::ActorAttributeType::RGBColor>() const {
|
||||
return As<sensor::data::Color>();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline bool ActorAttribute::operator==(const T &rhs) const {
|
||||
return As<T>() == rhs;
|
||||
}
|
||||
|
||||
template <>
|
||||
inline bool ActorAttribute::operator==(const ActorAttribute &rhs) const {
|
||||
return
|
||||
(_attribute.type == rhs._attribute.type) &&
|
||||
(_attribute.value == rhs._attribute.value);
|
||||
inline bool ActorAttributeValueAccess::operator==(const ActorAttribute &rhs) const {
|
||||
return rhs.operator==(*this);
|
||||
}
|
||||
|
||||
} // namespace client
|
||||
|
|
|
@ -56,9 +56,7 @@ namespace client {
|
|||
description.id = _id;
|
||||
description.attributes.reserve(_attributes.size());
|
||||
for (const auto &attribute : *this) {
|
||||
if (attribute.IsModifiable()) {
|
||||
description.attributes.push_back(attribute);
|
||||
}
|
||||
description.attributes.push_back(attribute);
|
||||
}
|
||||
return description;
|
||||
}
|
||||
|
|
|
@ -20,6 +20,18 @@ namespace client {
|
|||
: _episode(std::move(episode)),
|
||||
_actors(std::make_move_iterator(actors.begin()), std::make_move_iterator(actors.end())) {}
|
||||
|
||||
SharedPtr<Actor> ActorList::GetActor(actor_id_type const actor_id) const
|
||||
{
|
||||
for (auto &actor: _actors)
|
||||
{
|
||||
if (actor_id == actor.GetId())
|
||||
{
|
||||
return actor.Get(_episode, shared_from_this());
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
ActorList ActorList::Filter(const std::string &wildcard_pattern) const {
|
||||
ActorList filtered{_episode, {}};
|
||||
for (auto &&actor : _actors) {
|
||||
|
|
|
@ -21,7 +21,7 @@ namespace client {
|
|||
template <typename It>
|
||||
auto MakeIterator(It it) const {
|
||||
return boost::make_transform_iterator(it, [this](auto &v) {
|
||||
return v.Get(_episode);
|
||||
return v.Get(_episode, shared_from_this());
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -31,11 +31,11 @@ namespace client {
|
|||
ActorList Filter(const std::string &wildcard_pattern) const;
|
||||
|
||||
SharedPtr<Actor> operator[](size_t pos) const {
|
||||
return _actors[pos].Get(_episode);
|
||||
return _actors[pos].Get(_episode, shared_from_this());
|
||||
}
|
||||
|
||||
SharedPtr<Actor> at(size_t pos) const {
|
||||
return _actors.at(pos).Get(_episode);
|
||||
return _actors.at(pos).Get(_episode, shared_from_this());
|
||||
}
|
||||
|
||||
auto begin() const {
|
||||
|
@ -54,6 +54,8 @@ namespace client {
|
|||
return _actors.size();
|
||||
}
|
||||
|
||||
SharedPtr<Actor> GetActor(actor_id_type const actor_id) const;
|
||||
|
||||
private:
|
||||
|
||||
friend class World;
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
#include "carla/client/detail/ActorState.h"
|
||||
|
||||
#include <string>
|
||||
#include <iterator>
|
||||
|
||||
namespace carla {
|
||||
namespace client {
|
||||
|
@ -25,7 +26,9 @@ namespace detail {
|
|||
"Actor "s +
|
||||
std::to_string(desc.id) +
|
||||
" (" + desc.description.id + ')';
|
||||
}(_description)) {}
|
||||
}(_description)),
|
||||
_attributes(_description.description.attributes.begin(), _description.description.attributes.end())
|
||||
{}
|
||||
|
||||
} // namespace detail
|
||||
} // namespace client
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
|
||||
#include "carla/NonCopyable.h"
|
||||
#include "carla/client/World.h"
|
||||
#include "carla/client/ActorAttribute.h"
|
||||
#include "carla/client/detail/EpisodeProxy.h"
|
||||
#include "carla/rpc/Actor.h"
|
||||
|
||||
|
@ -49,6 +50,11 @@ namespace detail {
|
|||
return World{_episode};
|
||||
}
|
||||
|
||||
const std::vector<ActorAttributeValue> &GetAttributes() const
|
||||
{
|
||||
return _attributes;
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
const rpc::Actor &GetActorDescription() const {
|
||||
|
@ -79,6 +85,8 @@ namespace detail {
|
|||
SharedPtr<Actor> _parent;
|
||||
|
||||
std::string _display_id;
|
||||
|
||||
std::vector<ActorAttributeValue> _attributes;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
|
|
@ -7,16 +7,24 @@
|
|||
#include "carla/client/detail/ActorVariant.h"
|
||||
|
||||
#include "carla/client/detail/ActorFactory.h"
|
||||
#include "carla/client/ActorList.h"
|
||||
|
||||
namespace carla {
|
||||
namespace client {
|
||||
namespace detail {
|
||||
|
||||
void ActorVariant::MakeActor(EpisodeProxy episode) const {
|
||||
void ActorVariant::MakeActor(EpisodeProxy episode, SharedPtr<const client::ActorList> actor_list) const {
|
||||
auto const parent_id = GetParentId();
|
||||
SharedPtr<client::Actor> parent = nullptr;
|
||||
if ( (actor_list != nullptr) && (parent_id != 0) )
|
||||
{
|
||||
// in case we have an actor list as context, we are able to actually create the parent actor
|
||||
parent = actor_list->GetActor(parent_id);
|
||||
}
|
||||
_value = detail::ActorFactory::MakeActor(
|
||||
episode,
|
||||
boost::get<rpc::Actor>(std::move(_value)),
|
||||
nullptr, /// @todo We need to create the parent too.
|
||||
parent,
|
||||
GarbageCollectionPolicy::Disabled);
|
||||
}
|
||||
|
||||
|
|
|
@ -38,9 +38,9 @@ namespace detail {
|
|||
return *this;
|
||||
}
|
||||
|
||||
SharedPtr<client::Actor> Get(EpisodeProxy episode) const {
|
||||
SharedPtr<client::Actor> Get(EpisodeProxy episode, SharedPtr<const client::ActorList> actor_list = nullptr) const {
|
||||
if (_value.which() == 0u) {
|
||||
MakeActor(episode);
|
||||
MakeActor(episode, actor_list);
|
||||
}
|
||||
DEBUG_ASSERT(_value.which() == 1u);
|
||||
return boost::get<SharedPtr<client::Actor>>(_value);
|
||||
|
@ -54,6 +54,10 @@ namespace detail {
|
|||
return Serialize().id;
|
||||
}
|
||||
|
||||
actor_id_type GetParentId() const {
|
||||
return Serialize().parent_id;
|
||||
}
|
||||
|
||||
const std::string &GetTypeId() const {
|
||||
return Serialize().description.id;
|
||||
}
|
||||
|
@ -72,12 +76,12 @@ namespace detail {
|
|||
const rpc::Actor &operator()(const rpc::Actor &actor) const {
|
||||
return actor;
|
||||
}
|
||||
const rpc::Actor &operator()(const SharedPtr<client::Actor> &actor) const {
|
||||
const rpc::Actor &operator()(const SharedPtr<const client::Actor> &actor) const {
|
||||
return actor->Serialize();
|
||||
}
|
||||
};
|
||||
|
||||
void MakeActor(EpisodeProxy episode) const;
|
||||
void MakeActor(EpisodeProxy episode, SharedPtr<const client::ActorList> actor_list) const;
|
||||
|
||||
mutable boost::variant<rpc::Actor, SharedPtr<client::Actor>> _value;
|
||||
};
|
||||
|
|
|
@ -24,6 +24,8 @@ namespace rpc {
|
|||
|
||||
actor_id_type id = 0u;
|
||||
|
||||
actor_id_type parent_id;
|
||||
|
||||
ActorDescription description;
|
||||
|
||||
geom::BoundingBox bounding_box;
|
||||
|
@ -49,7 +51,7 @@ namespace rpc {
|
|||
|
||||
/// @}
|
||||
|
||||
MSGPACK_DEFINE_ARRAY(id, description, bounding_box, semantic_tags, stream_token);
|
||||
MSGPACK_DEFINE_ARRAY(id, parent_id, description, bounding_box, semantic_tags, stream_token);
|
||||
};
|
||||
|
||||
} // namespace rpc
|
||||
|
|
|
@ -133,6 +133,7 @@ class World(object):
|
|||
blueprint = self._get_random_blueprint()
|
||||
spawn_points = self.world.get_map().get_spawn_points()
|
||||
spawn_point = random.choice(spawn_points) if spawn_points else carla.Transform()
|
||||
blueprint.set_attribute('role_name', 'hero')
|
||||
self.vehicle = self.world.spawn_actor(blueprint, spawn_point)
|
||||
self.collision_sensor = CollisionSensor(self.vehicle, self.hud)
|
||||
self.lane_invasion_sensor = LaneInvasionSensor(self.vehicle, self.hud)
|
||||
|
@ -150,6 +151,8 @@ class World(object):
|
|||
start_pose.rotation.roll = 0.0
|
||||
start_pose.rotation.pitch = 0.0
|
||||
blueprint = self._get_random_blueprint()
|
||||
blueprint.set_attribute('role_name', 'hero')
|
||||
|
||||
self.destroy()
|
||||
self.vehicle = self.world.spawn_actor(blueprint, start_pose)
|
||||
self.collision_sensor = CollisionSensor(self.vehicle, self.hud)
|
||||
|
|
|
@ -47,6 +47,13 @@ void export_actor() {
|
|||
.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)
|
||||
|
|
|
@ -77,6 +77,7 @@ def main():
|
|||
if blueprint.has_attribute('color'):
|
||||
color = random.choice(blueprint.get_attribute('color').recommended_values)
|
||||
blueprint.set_attribute('color', color)
|
||||
blueprint.set_attribute('role_name', 'autopilot')
|
||||
vehicle = world.try_spawn_actor(blueprint, transform)
|
||||
if vehicle is not None:
|
||||
actor_list.append(vehicle)
|
||||
|
|
|
@ -192,6 +192,30 @@ static void FillIdAndTags(FActorDefinition &Def, TStrs &&... Strings)
|
|||
{
|
||||
Def.Id = JoinStrings(TEXT("."), std::forward<TStrs>(Strings)...).ToLower();
|
||||
Def.Tags = JoinStrings(TEXT(","), std::forward<TStrs>(Strings)...).ToLower();
|
||||
// each actor gets an actor role name attribute (empty by default)
|
||||
FActorVariation ActorRole;
|
||||
ActorRole.Id = TEXT("role_name");
|
||||
ActorRole.Type = EActorAttributeType::String;
|
||||
ActorRole.RecommendedValues = { TEXT("default") };
|
||||
ActorRole.bRestrictToRecommended = false;
|
||||
Def.Variations.Emplace(ActorRole);
|
||||
}
|
||||
|
||||
static void AddRecommendedValuesForActorRoleName(FActorDefinition &Definition, TArray<FString> &&RecommendedValues)
|
||||
{
|
||||
for (auto &&ActorVariation: Definition.Variations)
|
||||
{
|
||||
if ( ActorVariation.Id == "role_name" )
|
||||
{
|
||||
ActorVariation.RecommendedValues = RecommendedValues;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void AddRecommendedValuesForSensorRoleNames(FActorDefinition &Definition)
|
||||
{
|
||||
AddRecommendedValuesForActorRoleName(Definition, {TEXT("front"), TEXT("back"), TEXT("left"), TEXT("right"), TEXT("front_left"), TEXT("front_right"), TEXT("back_left"), TEXT("back_right")});
|
||||
}
|
||||
|
||||
FActorDefinition UActorBlueprintFunctionLibrary::MakeGenericSensorDefinition(
|
||||
|
@ -200,6 +224,7 @@ FActorDefinition UActorBlueprintFunctionLibrary::MakeGenericSensorDefinition(
|
|||
{
|
||||
FActorDefinition Definition;
|
||||
FillIdAndTags(Definition, TEXT("sensor"), Type, Id);
|
||||
AddRecommendedValuesForSensorRoleNames(Definition);
|
||||
return Definition;
|
||||
}
|
||||
|
||||
|
@ -221,6 +246,7 @@ void UActorBlueprintFunctionLibrary::MakeCameraDefinition(
|
|||
FActorDefinition &Definition)
|
||||
{
|
||||
FillIdAndTags(Definition, TEXT("sensor"), TEXT("camera"), Id);
|
||||
AddRecommendedValuesForSensorRoleNames(Definition);
|
||||
// FOV.
|
||||
FActorVariation FOV;
|
||||
FOV.Id = TEXT("fov");
|
||||
|
@ -239,7 +265,7 @@ void UActorBlueprintFunctionLibrary::MakeCameraDefinition(
|
|||
ResY.RecommendedValues = { TEXT("600") };
|
||||
ResY.bRestrictToRecommended = false;
|
||||
|
||||
Definition.Variations = {ResX, ResY, FOV};
|
||||
Definition.Variations.Append({ResX, ResY, FOV});
|
||||
|
||||
if (bEnableModifyingPostProcessEffects)
|
||||
{
|
||||
|
@ -270,6 +296,7 @@ void UActorBlueprintFunctionLibrary::MakeLidarDefinition(
|
|||
FActorDefinition &Definition)
|
||||
{
|
||||
FillIdAndTags(Definition, TEXT("sensor"), TEXT("lidar"), Id);
|
||||
AddRecommendedValuesForSensorRoleNames(Definition);
|
||||
// Number of channels.
|
||||
FActorVariation Channels;
|
||||
Channels.Id = TEXT("channels");
|
||||
|
@ -301,7 +328,7 @@ void UActorBlueprintFunctionLibrary::MakeLidarDefinition(
|
|||
LowerFOV.Type = EActorAttributeType::Float;
|
||||
LowerFOV.RecommendedValues = { TEXT("-30.0") };
|
||||
|
||||
Definition.Variations = {Channels, Range, PointsPerSecond, Frequency, UpperFOV, LowerFOV};
|
||||
Definition.Variations.Append({Channels, Range, PointsPerSecond, Frequency, UpperFOV, LowerFOV});
|
||||
|
||||
Success = CheckActorDefinition(Definition);
|
||||
}
|
||||
|
@ -313,6 +340,7 @@ void UActorBlueprintFunctionLibrary::MakeVehicleDefinition(
|
|||
{
|
||||
/// @todo We need to validate here the params.
|
||||
FillIdAndTags(Definition, TEXT("vehicle"), Parameters.Make, Parameters.Model);
|
||||
AddRecommendedValuesForActorRoleName(Definition, {TEXT("autopilot"), TEXT("scenario"), TEXT("ego_vehicle")});
|
||||
Definition.Class = Parameters.Class;
|
||||
if (Parameters.RecommendedColors.Num() > 0)
|
||||
{
|
||||
|
@ -326,6 +354,12 @@ void UActorBlueprintFunctionLibrary::MakeVehicleDefinition(
|
|||
}
|
||||
Definition.Variations.Emplace(Colors);
|
||||
}
|
||||
|
||||
Definition.Attributes.Emplace(FActorAttribute{
|
||||
TEXT("object_type"),
|
||||
EActorAttributeType::String,
|
||||
Parameters.ObjectType});
|
||||
|
||||
Definition.Attributes.Emplace(FActorAttribute{
|
||||
TEXT("number_of_wheels"),
|
||||
EActorAttributeType::Int,
|
||||
|
|
|
@ -34,6 +34,9 @@ struct CARLA_API FVehicleParameters
|
|||
UPROPERTY(EditAnywhere, BlueprintReadWrite)
|
||||
int32 NumberOfWheels = 4;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite)
|
||||
FString ObjectType;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite)
|
||||
TArray<FColor> RecommendedColors;
|
||||
};
|
||||
|
|
|
@ -133,6 +133,7 @@ public:
|
|||
Actor.id = ActorView.GetActorId();
|
||||
if (ActorView.IsValid())
|
||||
{
|
||||
Actor.parent_id = Episode->GetActorRegistry().Find(ActorView.GetActor()->GetOwner()).GetActorId();
|
||||
Actor.description = *ActorView.GetActorDescription();
|
||||
Actor.bounding_box = GetActorBoundingBox(*ActorView.GetActor());
|
||||
Actor.semantic_tags.reserve(ActorView.GetSemanticTags().Num());
|
||||
|
|
Loading…
Reference in New Issue