Merge pull request #1008 from berndgassmann/extend_python_interface
Provide parent/attribute content of Actors via python interface
This commit is contained in:
commit
bc5a3edd3d
|
@ -90,6 +90,7 @@
|
||||||
- `parent`
|
- `parent`
|
||||||
- `semantic_tags`
|
- `semantic_tags`
|
||||||
- `is_alive`
|
- `is_alive`
|
||||||
|
- `attributes`
|
||||||
- `get_world()`
|
- `get_world()`
|
||||||
- `get_location()`
|
- `get_location()`
|
||||||
- `get_transform()`
|
- `get_transform()`
|
||||||
|
|
|
@ -12,10 +12,10 @@
|
||||||
namespace carla {
|
namespace carla {
|
||||||
namespace client {
|
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) \
|
#define LIBCARLA_THROW_BAD_VALUE_CAST(type) \
|
||||||
if (GetType() != rpc::ActorAttributeType:: 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) {
|
void ActorAttribute::Set(std::string value) {
|
||||||
|
@ -29,28 +29,29 @@ namespace client {
|
||||||
Validate();
|
Validate();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
bool ActorAttribute::As<bool>() const {
|
bool ActorAttributeValueAccess::As<bool>() const {
|
||||||
LIBCARLA_THROW_BAD_VALUE_CAST(Bool);
|
LIBCARLA_THROW_BAD_VALUE_CAST(Bool);
|
||||||
auto value = StringUtil::ToLowerCopy(_attribute.value);
|
auto value = StringUtil::ToLowerCopy(GetValue());
|
||||||
if (value == "true") {
|
if (value == "true") {
|
||||||
return true;
|
return true;
|
||||||
} else if (value == "false") {
|
} else if (value == "false") {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
LIBCARLA_THROW_INVALID_VALUE("invalid bool: " + _attribute.value);
|
LIBCARLA_THROW_INVALID_VALUE("invalid bool: " + GetValue());
|
||||||
}
|
}
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
int ActorAttribute::As<int>() const {
|
int ActorAttributeValueAccess::As<int>() const {
|
||||||
LIBCARLA_THROW_BAD_VALUE_CAST(Int);
|
LIBCARLA_THROW_BAD_VALUE_CAST(Int);
|
||||||
return std::atoi(_attribute.value.c_str());
|
return std::atoi(GetValue().c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
float ActorAttribute::As<float>() const {
|
float ActorAttributeValueAccess::As<float>() const {
|
||||||
LIBCARLA_THROW_BAD_VALUE_CAST(Float);
|
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()) ||
|
if ((x > std::numeric_limits<float>::max()) ||
|
||||||
(x < std::numeric_limits<float>::lowest())) {
|
(x < std::numeric_limits<float>::lowest())) {
|
||||||
LIBCARLA_THROW_INVALID_VALUE("float overflow");
|
LIBCARLA_THROW_INVALID_VALUE("float overflow");
|
||||||
|
@ -59,19 +60,19 @@ namespace client {
|
||||||
}
|
}
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
std::string ActorAttribute::As<std::string>() const {
|
std::string ActorAttributeValueAccess::As<std::string>() const {
|
||||||
LIBCARLA_THROW_BAD_VALUE_CAST(String);
|
LIBCARLA_THROW_BAD_VALUE_CAST(String);
|
||||||
return _attribute.value;
|
return GetValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
template <>
|
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);
|
LIBCARLA_THROW_BAD_VALUE_CAST(RGBColor);
|
||||||
|
|
||||||
std::vector<std::string> channels;
|
std::vector<std::string> channels;
|
||||||
StringUtil::Split(channels, _attribute.value, ",");
|
StringUtil::Split(channels, GetValue(), ",");
|
||||||
if (channels.size() != 3u) {
|
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)");
|
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])};
|
return {to_int(channels[0u]), to_int(channels[1u]), to_int(channels[2u])};
|
||||||
}
|
}
|
||||||
|
|
||||||
void ActorAttribute::Validate() const {
|
void ActorAttributeValueAccess::Validate() const {
|
||||||
switch (_attribute.type) {
|
switch (GetType()) {
|
||||||
case rpc::ActorAttributeType::Bool: As<rpc::ActorAttributeType::Bool>(); break;
|
case rpc::ActorAttributeType::Bool: As<rpc::ActorAttributeType::Bool>(); break;
|
||||||
case rpc::ActorAttributeType::Int: As<rpc::ActorAttributeType::Int>(); break;
|
case rpc::ActorAttributeType::Int: As<rpc::ActorAttributeType::Int>(); break;
|
||||||
case rpc::ActorAttributeType::Float: As<rpc::ActorAttributeType::Float>(); break;
|
case rpc::ActorAttributeType::Float: As<rpc::ActorAttributeType::Float>(); break;
|
||||||
|
|
|
@ -44,36 +44,20 @@ namespace client {
|
||||||
// -- ActorAttribute ---------------------------------------------------------
|
// -- ActorAttribute ---------------------------------------------------------
|
||||||
// ===========================================================================
|
// ===========================================================================
|
||||||
|
|
||||||
/// An attribute of an ActorBlueprint.
|
class ActorAttributeValueAccess
|
||||||
class ActorAttribute {
|
{
|
||||||
public:
|
public:
|
||||||
|
ActorAttributeValueAccess() = default;
|
||||||
|
ActorAttributeValueAccess(ActorAttributeValueAccess const &) = default;
|
||||||
|
ActorAttributeValueAccess(ActorAttributeValueAccess &&) = default;
|
||||||
|
virtual ~ActorAttributeValueAccess() = default;
|
||||||
|
|
||||||
ActorAttribute(rpc::ActorAttribute attribute)
|
ActorAttributeValueAccess & operator= (ActorAttributeValueAccess const & ) = default;
|
||||||
: _attribute(std::move(attribute)) {
|
ActorAttributeValueAccess & operator= (ActorAttributeValueAccess && ) = default;
|
||||||
Validate();
|
|
||||||
}
|
|
||||||
|
|
||||||
const std::string &GetId() const {
|
virtual const std::string &GetId() const = 0;
|
||||||
return _attribute.id;
|
|
||||||
}
|
|
||||||
|
|
||||||
rpc::ActorAttributeType GetType() const {
|
virtual rpc::ActorAttributeType GetType() const = 0;
|
||||||
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);
|
|
||||||
|
|
||||||
/// Cast the value to the given type.
|
/// Cast the value to the given type.
|
||||||
///
|
///
|
||||||
|
@ -96,68 +80,162 @@ namespace client {
|
||||||
return !(*this == rhs);
|
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.
|
/// Serialize this object as a carla::rpc::ActorAttributeValue.
|
||||||
operator rpc::ActorAttributeValue() const {
|
operator rpc::ActorAttributeValue() const {
|
||||||
return _attribute;
|
return _attribute;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual const std::string &GetValue() const override {
|
||||||
|
return _attribute.value;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
void Validate() const;
|
|
||||||
|
|
||||||
rpc::ActorAttribute _attribute;
|
rpc::ActorAttribute _attribute;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
bool ActorAttribute::As<bool>() const;
|
inline bool ActorAttributeValueAccess::operator==(const ActorAttribute &rhs) const {
|
||||||
|
return rhs.operator==(*this);
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace client
|
} // namespace client
|
||||||
|
|
|
@ -56,9 +56,7 @@ namespace client {
|
||||||
description.id = _id;
|
description.id = _id;
|
||||||
description.attributes.reserve(_attributes.size());
|
description.attributes.reserve(_attributes.size());
|
||||||
for (const auto &attribute : *this) {
|
for (const auto &attribute : *this) {
|
||||||
if (attribute.IsModifiable()) {
|
description.attributes.push_back(attribute);
|
||||||
description.attributes.push_back(attribute);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return description;
|
return description;
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,6 +20,18 @@ namespace client {
|
||||||
: _episode(std::move(episode)),
|
: _episode(std::move(episode)),
|
||||||
_actors(std::make_move_iterator(actors.begin()), std::make_move_iterator(actors.end())) {}
|
_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 ActorList::Filter(const std::string &wildcard_pattern) const {
|
||||||
ActorList filtered{_episode, {}};
|
ActorList filtered{_episode, {}};
|
||||||
for (auto &&actor : _actors) {
|
for (auto &&actor : _actors) {
|
||||||
|
|
|
@ -21,7 +21,7 @@ namespace client {
|
||||||
template <typename It>
|
template <typename It>
|
||||||
auto MakeIterator(It it) const {
|
auto MakeIterator(It it) const {
|
||||||
return boost::make_transform_iterator(it, [this](auto &v) {
|
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;
|
ActorList Filter(const std::string &wildcard_pattern) const;
|
||||||
|
|
||||||
SharedPtr<Actor> operator[](size_t pos) 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 {
|
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 {
|
auto begin() const {
|
||||||
|
@ -54,6 +54,8 @@ namespace client {
|
||||||
return _actors.size();
|
return _actors.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SharedPtr<Actor> GetActor(actor_id_type const actor_id) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
friend class World;
|
friend class World;
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
#include "carla/client/detail/ActorState.h"
|
#include "carla/client/detail/ActorState.h"
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <iterator>
|
||||||
|
|
||||||
namespace carla {
|
namespace carla {
|
||||||
namespace client {
|
namespace client {
|
||||||
|
@ -25,7 +26,9 @@ namespace detail {
|
||||||
"Actor "s +
|
"Actor "s +
|
||||||
std::to_string(desc.id) +
|
std::to_string(desc.id) +
|
||||||
" (" + desc.description.id + ')';
|
" (" + desc.description.id + ')';
|
||||||
}(_description)) {}
|
}(_description)),
|
||||||
|
_attributes(_description.description.attributes.begin(), _description.description.attributes.end())
|
||||||
|
{}
|
||||||
|
|
||||||
} // namespace detail
|
} // namespace detail
|
||||||
} // namespace client
|
} // namespace client
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
|
|
||||||
#include "carla/NonCopyable.h"
|
#include "carla/NonCopyable.h"
|
||||||
#include "carla/client/World.h"
|
#include "carla/client/World.h"
|
||||||
|
#include "carla/client/ActorAttribute.h"
|
||||||
#include "carla/client/detail/EpisodeProxy.h"
|
#include "carla/client/detail/EpisodeProxy.h"
|
||||||
#include "carla/rpc/Actor.h"
|
#include "carla/rpc/Actor.h"
|
||||||
|
|
||||||
|
@ -49,6 +50,11 @@ namespace detail {
|
||||||
return World{_episode};
|
return World{_episode};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const std::vector<ActorAttributeValue> &GetAttributes() const
|
||||||
|
{
|
||||||
|
return _attributes;
|
||||||
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
const rpc::Actor &GetActorDescription() const {
|
const rpc::Actor &GetActorDescription() const {
|
||||||
|
@ -79,6 +85,8 @@ namespace detail {
|
||||||
SharedPtr<Actor> _parent;
|
SharedPtr<Actor> _parent;
|
||||||
|
|
||||||
std::string _display_id;
|
std::string _display_id;
|
||||||
|
|
||||||
|
std::vector<ActorAttributeValue> _attributes;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace detail
|
} // namespace detail
|
||||||
|
|
|
@ -7,16 +7,24 @@
|
||||||
#include "carla/client/detail/ActorVariant.h"
|
#include "carla/client/detail/ActorVariant.h"
|
||||||
|
|
||||||
#include "carla/client/detail/ActorFactory.h"
|
#include "carla/client/detail/ActorFactory.h"
|
||||||
|
#include "carla/client/ActorList.h"
|
||||||
|
|
||||||
namespace carla {
|
namespace carla {
|
||||||
namespace client {
|
namespace client {
|
||||||
namespace detail {
|
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(
|
_value = detail::ActorFactory::MakeActor(
|
||||||
episode,
|
episode,
|
||||||
boost::get<rpc::Actor>(std::move(_value)),
|
boost::get<rpc::Actor>(std::move(_value)),
|
||||||
nullptr, /// @todo We need to create the parent too.
|
parent,
|
||||||
GarbageCollectionPolicy::Disabled);
|
GarbageCollectionPolicy::Disabled);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -38,9 +38,9 @@ namespace detail {
|
||||||
return *this;
|
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) {
|
if (_value.which() == 0u) {
|
||||||
MakeActor(episode);
|
MakeActor(episode, actor_list);
|
||||||
}
|
}
|
||||||
DEBUG_ASSERT(_value.which() == 1u);
|
DEBUG_ASSERT(_value.which() == 1u);
|
||||||
return boost::get<SharedPtr<client::Actor>>(_value);
|
return boost::get<SharedPtr<client::Actor>>(_value);
|
||||||
|
@ -54,6 +54,10 @@ namespace detail {
|
||||||
return Serialize().id;
|
return Serialize().id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
actor_id_type GetParentId() const {
|
||||||
|
return Serialize().parent_id;
|
||||||
|
}
|
||||||
|
|
||||||
const std::string &GetTypeId() const {
|
const std::string &GetTypeId() const {
|
||||||
return Serialize().description.id;
|
return Serialize().description.id;
|
||||||
}
|
}
|
||||||
|
@ -72,12 +76,12 @@ namespace detail {
|
||||||
const rpc::Actor &operator()(const rpc::Actor &actor) const {
|
const rpc::Actor &operator()(const rpc::Actor &actor) const {
|
||||||
return actor;
|
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();
|
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;
|
mutable boost::variant<rpc::Actor, SharedPtr<client::Actor>> _value;
|
||||||
};
|
};
|
||||||
|
|
|
@ -24,6 +24,8 @@ namespace rpc {
|
||||||
|
|
||||||
actor_id_type id = 0u;
|
actor_id_type id = 0u;
|
||||||
|
|
||||||
|
actor_id_type parent_id;
|
||||||
|
|
||||||
ActorDescription description;
|
ActorDescription description;
|
||||||
|
|
||||||
geom::BoundingBox bounding_box;
|
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
|
} // namespace rpc
|
||||||
|
|
|
@ -133,6 +133,7 @@ class World(object):
|
||||||
blueprint = self._get_random_blueprint()
|
blueprint = self._get_random_blueprint()
|
||||||
spawn_points = self.world.get_map().get_spawn_points()
|
spawn_points = self.world.get_map().get_spawn_points()
|
||||||
spawn_point = random.choice(spawn_points) if spawn_points else carla.Transform()
|
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.vehicle = self.world.spawn_actor(blueprint, spawn_point)
|
||||||
self.collision_sensor = CollisionSensor(self.vehicle, self.hud)
|
self.collision_sensor = CollisionSensor(self.vehicle, self.hud)
|
||||||
self.lane_invasion_sensor = LaneInvasionSensor(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.roll = 0.0
|
||||||
start_pose.rotation.pitch = 0.0
|
start_pose.rotation.pitch = 0.0
|
||||||
blueprint = self._get_random_blueprint()
|
blueprint = self._get_random_blueprint()
|
||||||
|
blueprint.set_attribute('role_name', 'hero')
|
||||||
|
|
||||||
self.destroy()
|
self.destroy()
|
||||||
self.vehicle = self.world.spawn_actor(blueprint, start_pose)
|
self.vehicle = self.world.spawn_actor(blueprint, start_pose)
|
||||||
self.collision_sensor = CollisionSensor(self.vehicle, self.hud)
|
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("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) {
|
||||||
|
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_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)
|
||||||
|
|
|
@ -77,6 +77,7 @@ def main():
|
||||||
if blueprint.has_attribute('color'):
|
if blueprint.has_attribute('color'):
|
||||||
color = random.choice(blueprint.get_attribute('color').recommended_values)
|
color = random.choice(blueprint.get_attribute('color').recommended_values)
|
||||||
blueprint.set_attribute('color', color)
|
blueprint.set_attribute('color', color)
|
||||||
|
blueprint.set_attribute('role_name', 'autopilot')
|
||||||
vehicle = world.try_spawn_actor(blueprint, transform)
|
vehicle = world.try_spawn_actor(blueprint, transform)
|
||||||
if vehicle is not None:
|
if vehicle is not None:
|
||||||
actor_list.append(vehicle)
|
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.Id = JoinStrings(TEXT("."), std::forward<TStrs>(Strings)...).ToLower();
|
||||||
Def.Tags = 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(
|
FActorDefinition UActorBlueprintFunctionLibrary::MakeGenericSensorDefinition(
|
||||||
|
@ -200,6 +224,7 @@ FActorDefinition UActorBlueprintFunctionLibrary::MakeGenericSensorDefinition(
|
||||||
{
|
{
|
||||||
FActorDefinition Definition;
|
FActorDefinition Definition;
|
||||||
FillIdAndTags(Definition, TEXT("sensor"), Type, Id);
|
FillIdAndTags(Definition, TEXT("sensor"), Type, Id);
|
||||||
|
AddRecommendedValuesForSensorRoleNames(Definition);
|
||||||
return Definition;
|
return Definition;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -221,6 +246,7 @@ void UActorBlueprintFunctionLibrary::MakeCameraDefinition(
|
||||||
FActorDefinition &Definition)
|
FActorDefinition &Definition)
|
||||||
{
|
{
|
||||||
FillIdAndTags(Definition, TEXT("sensor"), TEXT("camera"), Id);
|
FillIdAndTags(Definition, TEXT("sensor"), TEXT("camera"), Id);
|
||||||
|
AddRecommendedValuesForSensorRoleNames(Definition);
|
||||||
// FOV.
|
// FOV.
|
||||||
FActorVariation FOV;
|
FActorVariation FOV;
|
||||||
FOV.Id = TEXT("fov");
|
FOV.Id = TEXT("fov");
|
||||||
|
@ -239,7 +265,7 @@ void UActorBlueprintFunctionLibrary::MakeCameraDefinition(
|
||||||
ResY.RecommendedValues = { TEXT("600") };
|
ResY.RecommendedValues = { TEXT("600") };
|
||||||
ResY.bRestrictToRecommended = false;
|
ResY.bRestrictToRecommended = false;
|
||||||
|
|
||||||
Definition.Variations = {ResX, ResY, FOV};
|
Definition.Variations.Append({ResX, ResY, FOV});
|
||||||
|
|
||||||
if (bEnableModifyingPostProcessEffects)
|
if (bEnableModifyingPostProcessEffects)
|
||||||
{
|
{
|
||||||
|
@ -270,6 +296,7 @@ void UActorBlueprintFunctionLibrary::MakeLidarDefinition(
|
||||||
FActorDefinition &Definition)
|
FActorDefinition &Definition)
|
||||||
{
|
{
|
||||||
FillIdAndTags(Definition, TEXT("sensor"), TEXT("lidar"), Id);
|
FillIdAndTags(Definition, TEXT("sensor"), TEXT("lidar"), Id);
|
||||||
|
AddRecommendedValuesForSensorRoleNames(Definition);
|
||||||
// Number of channels.
|
// Number of channels.
|
||||||
FActorVariation Channels;
|
FActorVariation Channels;
|
||||||
Channels.Id = TEXT("channels");
|
Channels.Id = TEXT("channels");
|
||||||
|
@ -301,7 +328,7 @@ void UActorBlueprintFunctionLibrary::MakeLidarDefinition(
|
||||||
LowerFOV.Type = EActorAttributeType::Float;
|
LowerFOV.Type = EActorAttributeType::Float;
|
||||||
LowerFOV.RecommendedValues = { TEXT("-30.0") };
|
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);
|
Success = CheckActorDefinition(Definition);
|
||||||
}
|
}
|
||||||
|
@ -313,6 +340,7 @@ void UActorBlueprintFunctionLibrary::MakeVehicleDefinition(
|
||||||
{
|
{
|
||||||
/// @todo We need to validate here the params.
|
/// @todo We need to validate here the params.
|
||||||
FillIdAndTags(Definition, TEXT("vehicle"), Parameters.Make, Parameters.Model);
|
FillIdAndTags(Definition, TEXT("vehicle"), Parameters.Make, Parameters.Model);
|
||||||
|
AddRecommendedValuesForActorRoleName(Definition, {TEXT("autopilot"), TEXT("scenario"), TEXT("ego_vehicle")});
|
||||||
Definition.Class = Parameters.Class;
|
Definition.Class = Parameters.Class;
|
||||||
if (Parameters.RecommendedColors.Num() > 0)
|
if (Parameters.RecommendedColors.Num() > 0)
|
||||||
{
|
{
|
||||||
|
@ -326,6 +354,12 @@ void UActorBlueprintFunctionLibrary::MakeVehicleDefinition(
|
||||||
}
|
}
|
||||||
Definition.Variations.Emplace(Colors);
|
Definition.Variations.Emplace(Colors);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Definition.Attributes.Emplace(FActorAttribute{
|
||||||
|
TEXT("object_type"),
|
||||||
|
EActorAttributeType::String,
|
||||||
|
Parameters.ObjectType});
|
||||||
|
|
||||||
Definition.Attributes.Emplace(FActorAttribute{
|
Definition.Attributes.Emplace(FActorAttribute{
|
||||||
TEXT("number_of_wheels"),
|
TEXT("number_of_wheels"),
|
||||||
EActorAttributeType::Int,
|
EActorAttributeType::Int,
|
||||||
|
|
|
@ -34,6 +34,9 @@ struct CARLA_API FVehicleParameters
|
||||||
UPROPERTY(EditAnywhere, BlueprintReadWrite)
|
UPROPERTY(EditAnywhere, BlueprintReadWrite)
|
||||||
int32 NumberOfWheels = 4;
|
int32 NumberOfWheels = 4;
|
||||||
|
|
||||||
|
UPROPERTY(EditAnywhere, BlueprintReadWrite)
|
||||||
|
FString ObjectType;
|
||||||
|
|
||||||
UPROPERTY(EditAnywhere, BlueprintReadWrite)
|
UPROPERTY(EditAnywhere, BlueprintReadWrite)
|
||||||
TArray<FColor> RecommendedColors;
|
TArray<FColor> RecommendedColors;
|
||||||
};
|
};
|
||||||
|
|
|
@ -133,6 +133,7 @@ public:
|
||||||
Actor.id = ActorView.GetActorId();
|
Actor.id = ActorView.GetActorId();
|
||||||
if (ActorView.IsValid())
|
if (ActorView.IsValid())
|
||||||
{
|
{
|
||||||
|
Actor.parent_id = Episode->GetActorRegistry().Find(ActorView.GetActor()->GetOwner()).GetActorId();
|
||||||
Actor.description = *ActorView.GetActorDescription();
|
Actor.description = *ActorView.GetActorDescription();
|
||||||
Actor.bounding_box = GetActorBoundingBox(*ActorView.GetActor());
|
Actor.bounding_box = GetActorBoundingBox(*ActorView.GetActor());
|
||||||
Actor.semantic_tags.reserve(ActorView.GetSemanticTags().Num());
|
Actor.semantic_tags.reserve(ActorView.GetSemanticTags().Num());
|
||||||
|
|
Loading…
Reference in New Issue