diff --git a/LibCarla/source/carla/client/ActorList.cpp b/LibCarla/source/carla/client/ActorList.cpp index faad12923..93c38f8b2 100644 --- a/LibCarla/source/carla/client/ActorList.cpp +++ b/LibCarla/source/carla/client/ActorList.cpp @@ -23,7 +23,7 @@ namespace client { SharedPtr ActorList::Find(const ActorId actor_id) const { for (auto &actor : _actors) { if (actor_id == actor.GetId()) { - return actor.Get(_episode, shared_from_this()); + return actor.Get(_episode); } } return nullptr; diff --git a/LibCarla/source/carla/client/ActorList.h b/LibCarla/source/carla/client/ActorList.h index c99aebb98..0ffd2653a 100644 --- a/LibCarla/source/carla/client/ActorList.h +++ b/LibCarla/source/carla/client/ActorList.h @@ -21,7 +21,7 @@ namespace client { template auto MakeIterator(It it) const { return boost::make_transform_iterator(it, [this](auto &v) { - return v.Get(_episode, shared_from_this()); + return v.Get(_episode); }); } @@ -34,11 +34,11 @@ namespace client { SharedPtr Filter(const std::string &wildcard_pattern) const; SharedPtr operator[](size_t pos) const { - return _actors[pos].Get(_episode, shared_from_this()); + return _actors[pos].Get(_episode); } SharedPtr at(size_t pos) const { - return _actors.at(pos).Get(_episode, shared_from_this()); + return _actors.at(pos).Get(_episode); } auto begin() const { diff --git a/LibCarla/source/carla/client/World.cpp b/LibCarla/source/carla/client/World.cpp index 82cb4dc14..557eeab46 100644 --- a/LibCarla/source/carla/client/World.cpp +++ b/LibCarla/source/carla/client/World.cpp @@ -45,6 +45,14 @@ namespace client { _episode.Lock()->SetWeatherParameters(weather); } + SharedPtr World::GetActor(ActorId id) const { + auto simulator = _episode.Lock(); + auto description = simulator->GetActorById(id); + return description.has_value() ? + simulator->MakeActor(std::move(*description)) : + nullptr; + } + SharedPtr World::GetActors() const { return SharedPtr{new ActorList{ _episode, diff --git a/LibCarla/source/carla/client/World.h b/LibCarla/source/carla/client/World.h index f059bb86d..2110b05e6 100644 --- a/LibCarla/source/carla/client/World.h +++ b/LibCarla/source/carla/client/World.h @@ -64,6 +64,9 @@ namespace client { /// Change the weather in the simulation. void SetWeather(const rpc::WeatherParameters &weather); + /// Find actor by id, return nullptr if not found. + SharedPtr GetActor(ActorId id) const; + /// Return a list with all the actors currently present in the world. SharedPtr GetActors() const; diff --git a/LibCarla/source/carla/client/detail/ActorFactory.cpp b/LibCarla/source/carla/client/detail/ActorFactory.cpp index f89c7347f..1aabc4a7e 100644 --- a/LibCarla/source/carla/client/detail/ActorFactory.cpp +++ b/LibCarla/source/carla/client/detail/ActorFactory.cpp @@ -70,9 +70,8 @@ namespace detail { SharedPtr ActorFactory::MakeActor( EpisodeProxy episode, rpc::Actor description, - SharedPtr parent, GarbageCollectionPolicy gc) { - auto init = ActorInitializer{description, episode, parent}; + auto init = ActorInitializer{description, episode}; if (description.description.id == "sensor.other.lane_invasion") { /// @todo return MakeActorImpl(std::move(init), gc); } else if (description.description.id == "sensor.other.gnss") { /// @todo diff --git a/LibCarla/source/carla/client/detail/ActorFactory.h b/LibCarla/source/carla/client/detail/ActorFactory.h index 2258aa028..b8db136fc 100644 --- a/LibCarla/source/carla/client/detail/ActorFactory.h +++ b/LibCarla/source/carla/client/detail/ActorFactory.h @@ -24,13 +24,14 @@ namespace detail { /// Create an Actor based on the provided @a actor_description. @a episode /// must point to the episode in which the actor is living. /// + /// Do not call this class directly, use Simulator::MakeActor. + /// /// If @a garbage_collection_policy is GarbageCollectionPolicy::Enabled, the /// shared pointer returned is provided with a custom deleter that calls /// Destroy() on the actor. static SharedPtr MakeActor( EpisodeProxy episode, rpc::Actor actor_description, - SharedPtr parent, GarbageCollectionPolicy garbage_collection_policy); }; diff --git a/LibCarla/source/carla/client/detail/ActorState.cpp b/LibCarla/source/carla/client/detail/ActorState.cpp index 170e63bc1..f9a2af8b5 100644 --- a/LibCarla/source/carla/client/detail/ActorState.cpp +++ b/LibCarla/source/carla/client/detail/ActorState.cpp @@ -15,11 +15,9 @@ namespace detail { ActorState::ActorState( rpc::Actor description, - EpisodeProxy episode, - SharedPtr parent) + EpisodeProxy episode) : _description(std::move(description)), _episode(std::move(episode)), - _parent(std::move(parent)), _display_id([](const auto &desc) { using namespace std::string_literals; return @@ -30,6 +28,11 @@ namespace detail { _attributes(_description.description.attributes.begin(), _description.description.attributes.end()) {} + SharedPtr ActorState::GetParent() const { + auto parent_id = GetParentId(); + return parent_id != 0u ? GetWorld().GetActor(parent_id) : nullptr; + } + } // namespace detail } // namespace client } // namespace carla diff --git a/LibCarla/source/carla/client/detail/ActorState.h b/LibCarla/source/carla/client/detail/ActorState.h index e722cfc2e..d4f62a7b8 100644 --- a/LibCarla/source/carla/client/detail/ActorState.h +++ b/LibCarla/source/carla/client/detail/ActorState.h @@ -22,7 +22,7 @@ namespace detail { class ActorState : private MovableNonCopyable { public: - auto GetId() const { + ActorId GetId() const { return _description.id; } @@ -34,13 +34,15 @@ namespace detail { return _display_id; } + ActorId GetParentId() const { + return _description.parent_id; + } + const std::vector &GetSemanticTags() const { return _description.semantic_tags; } - SharedPtr GetParent() const { - return _parent; - } + SharedPtr GetParent() const; World GetWorld() const { return World{_episode}; @@ -73,17 +75,12 @@ namespace detail { friend class Simulator; - ActorState( - rpc::Actor description, - EpisodeProxy episode, - SharedPtr parent); + explicit ActorState(rpc::Actor description, EpisodeProxy episode); rpc::Actor _description; EpisodeProxy _episode; - SharedPtr _parent; - std::string _display_id; std::vector _attributes; diff --git a/LibCarla/source/carla/client/detail/ActorVariant.cpp b/LibCarla/source/carla/client/detail/ActorVariant.cpp index 1865bb916..6fc3b1bb2 100644 --- a/LibCarla/source/carla/client/detail/ActorVariant.cpp +++ b/LibCarla/source/carla/client/detail/ActorVariant.cpp @@ -13,18 +13,10 @@ namespace carla { namespace client { namespace detail { - void ActorVariant::MakeActor(EpisodeProxy episode, SharedPtr actor_list) const { - auto const parent_id = GetParentId(); - SharedPtr 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->Find(parent_id); - } + void ActorVariant::MakeActor(EpisodeProxy episode) const { _value = detail::ActorFactory::MakeActor( episode, boost::get(std::move(_value)), - parent, GarbageCollectionPolicy::Disabled); } diff --git a/LibCarla/source/carla/client/detail/ActorVariant.h b/LibCarla/source/carla/client/detail/ActorVariant.h index 39596dfa1..945902f05 100644 --- a/LibCarla/source/carla/client/detail/ActorVariant.h +++ b/LibCarla/source/carla/client/detail/ActorVariant.h @@ -38,9 +38,9 @@ namespace detail { return *this; } - SharedPtr Get(EpisodeProxy episode, SharedPtr actor_list = nullptr) const { + SharedPtr Get(EpisodeProxy episode) const { if (_value.which() == 0u) { - MakeActor(episode, actor_list); + MakeActor(episode); } DEBUG_ASSERT(_value.which() == 1u); return boost::get>(_value); @@ -81,7 +81,7 @@ namespace detail { } }; - void MakeActor(EpisodeProxy episode, SharedPtr actor_list) const; + void MakeActor(EpisodeProxy episode) const; mutable boost::variant> _value; }; diff --git a/LibCarla/source/carla/client/detail/CachedActorList.h b/LibCarla/source/carla/client/detail/CachedActorList.h index 8d3cf737e..cadc89de0 100644 --- a/LibCarla/source/carla/client/detail/CachedActorList.h +++ b/LibCarla/source/carla/client/detail/CachedActorList.h @@ -42,6 +42,10 @@ namespace detail { template std::vector GetMissingIds(const RangeT &range) const; + /// Retrieve the actor matching @a id, or empty optional if actor is not + /// cached. + boost::optional GetActorById(ActorId id) const; + /// Retrieve the actors matching the ids in @a range. template std::vector GetActorsById(const RangeT &range) const; @@ -89,6 +93,15 @@ namespace detail { return result; } + inline boost::optional CachedActorList::GetActorById(ActorId id) const { + std::lock_guard lock(_mutex); + auto it = _actors.find(id); + if (it != _actors.end()) { + return it->second; + } + return boost::none; + } + template inline std::vector CachedActorList::GetActorsById(const RangeT &range) const { std::vector result; diff --git a/LibCarla/source/carla/client/detail/Episode.cpp b/LibCarla/source/carla/client/detail/Episode.cpp index 8d5dc4348..21043bcd1 100644 --- a/LibCarla/source/carla/client/detail/Episode.cpp +++ b/LibCarla/source/carla/client/detail/Episode.cpp @@ -73,6 +73,18 @@ namespace detail { }); } + boost::optional Episode::GetActorById(ActorId id) { + auto actor = _actors.GetActorById(id); + if (!actor.has_value()) { + auto actor_list = _client.GetActorsById({id}); + if (!actor_list.empty()) { + actor = std::move(actor_list.front()); + _actors.Insert(*actor); + } + } + return actor; + } + std::vector Episode::GetActorsById(const std::vector &actor_ids) { return GetActorsById_Impl(_client, _actors, actor_ids); } diff --git a/LibCarla/source/carla/client/detail/Episode.h b/LibCarla/source/carla/client/detail/Episode.h index 53c54a2cf..196d1bf28 100644 --- a/LibCarla/source/carla/client/detail/Episode.h +++ b/LibCarla/source/carla/client/detail/Episode.h @@ -51,6 +51,8 @@ namespace detail { _actors.Insert(std::move(actor)); } + boost::optional GetActorById(ActorId id); + std::vector GetActorsById(const std::vector &actor_ids); std::vector GetActors(); diff --git a/LibCarla/source/carla/client/detail/Simulator.cpp b/LibCarla/source/carla/client/detail/Simulator.cpp index 3b5e18647..c69ae4e63 100644 --- a/LibCarla/source/carla/client/detail/Simulator.cpp +++ b/LibCarla/source/carla/client/detail/Simulator.cpp @@ -13,7 +13,6 @@ #include "carla/client/Map.h" #include "carla/client/Sensor.h" #include "carla/client/TimeoutException.h" -#include "carla/client/detail/ActorFactory.h" #include "carla/sensor/Deserializer.h" #include @@ -115,11 +114,7 @@ namespace detail { } SharedPtr Simulator::GetSpectator() { - return ActorFactory::MakeActor( - GetCurrentEpisode(), - _client.GetSpectator(), - nullptr, - GarbageCollectionPolicy::Disabled); + return MakeActor(_client.GetSpectator()); } // =========================================================================== @@ -147,8 +142,7 @@ namespace detail { DEBUG_ASSERT(_episode != nullptr); _episode->RegisterActor(actor); const auto gca = (gc == GarbageCollectionPolicy::Inherit ? _gc_policy : gc); - auto parent_ptr = parent != nullptr ? parent->shared_from_this() : SharedPtr(); - auto result = ActorFactory::MakeActor(GetCurrentEpisode(), actor, parent_ptr, gca); + auto result = ActorFactory::MakeActor(GetCurrentEpisode(), actor, gca); log_debug( result->GetDisplayId(), "created", diff --git a/LibCarla/source/carla/client/detail/Simulator.h b/LibCarla/source/carla/client/detail/Simulator.h index 00de27b7e..abda07a05 100644 --- a/LibCarla/source/carla/client/detail/Simulator.h +++ b/LibCarla/source/carla/client/detail/Simulator.h @@ -14,6 +14,7 @@ #include "carla/client/TrafficLight.h" #include "carla/client/Vehicle.h" #include "carla/client/Walker.h" +#include "carla/client/detail/ActorFactory.h" #include "carla/client/detail/Client.h" #include "carla/client/detail/Episode.h" #include "carla/client/detail/EpisodeProxy.h" @@ -171,6 +172,11 @@ namespace detail { // ========================================================================= /// @{ + boost::optional GetActorById(ActorId id) const { + DEBUG_ASSERT(_episode != nullptr); + return _episode->GetActorById(id); + } + std::vector GetActorsById(const std::vector &actor_ids) const { DEBUG_ASSERT(_episode != nullptr); return _episode->GetActorsById(actor_ids); @@ -181,9 +187,24 @@ namespace detail { return _episode->GetActors(); } + /// Creates an actor instance out of a description of an existing actor. + /// Note that this does not spawn an actor. + /// /// If @a gc is GarbageCollectionPolicy::Enabled, the shared pointer /// returned is provided with a custom deleter that calls Destroy() on the - /// actor. If @gc is GarbageCollectionPolicy::Enabled, the default garbage + /// actor. This method does not support GarbageCollectionPolicy::Inherit. + SharedPtr MakeActor( + rpc::Actor actor_description, + GarbageCollectionPolicy gc = GarbageCollectionPolicy::Disabled) { + RELEASE_ASSERT(gc != GarbageCollectionPolicy::Inherit); + return ActorFactory::MakeActor(GetCurrentEpisode(), std::move(actor_description), gc); + } + + /// Spawns an actor into the simulation. + /// + /// If @a gc is GarbageCollectionPolicy::Enabled, the shared pointer + /// returned is provided with a custom deleter that calls Destroy() on the + /// actor. If @gc is GarbageCollectionPolicy::Inherit, the default garbage /// collection policy is used. SharedPtr SpawnActor( const ActorBlueprint &blueprint,