diff --git a/include/sdf/World.hh b/include/sdf/World.hh index 0afc85472..22a61862d 100644 --- a/include/sdf/World.hh +++ b/include/sdf/World.hh @@ -278,6 +278,20 @@ namespace sdf /// \return True if there exists an actor with the given name. public: bool ActorNameExists(const std::string &_name) const; + /// \brief Get an actor based on a name. + /// \param[in] _name Name of the actor. + /// \return Pointer to the actor. Nullptr if an actor with the given name + /// does not exist. + /// \sa bool ActorNameExists(const std::string &_name) const + public: const Actor *ActorByName(const std::string &_name) const; + + /// \brief Get a mutable actor based on a name. + /// \param[in] _name Name of the actor. + /// \return Pointer to the actor. Nullptr if an actor with the given name + /// does not exist. + /// \sa bool ActorNameExists(const std::string &_name) const + public: Actor *ActorByName(const std::string &_name); + /// \brief Get the number of explicit frames that are immediate (not nested) /// children of this World object. /// \remark FrameByName() can find explicit frames that are not immediate diff --git a/python/src/sdf/pyWorld.cc b/python/src/sdf/pyWorld.cc index 41b930fc4..c215033ba 100644 --- a/python/src/sdf/pyWorld.cc +++ b/python/src/sdf/pyWorld.cc @@ -98,13 +98,13 @@ void defineWorld(pybind11::object module) pybind11::overload_cast( &sdf::World::ModelByIndex), pybind11::return_value_policy::reference_internal, - "Get a mutable immediate (not nested) child joint model on an index.") + "Get a mutable immediate (not nested) model based on an index.") .def("model_by_name", pybind11::overload_cast( &sdf::World::ModelByName), pybind11::return_value_policy::reference_internal, - "Get a mutable immediate (not nested) mutable child model based on an " - "index.") + "Get a mutable immediate (not nested) mutable child model based on a " + "name.") .def("model_name_exists", &sdf::World::ModelNameExists, "Get whether a model name exists.") .def("name_exists_in_frame_attached_to_graph", @@ -137,6 +137,16 @@ void defineWorld(pybind11::object module) "Remove all joints.") .def("actor_count", &sdf::World::ActorCount, "Get the number of actors.") + .def("actor_by_index", + pybind11::overload_cast( + &sdf::World::ActorByIndex), + pybind11::return_value_policy::reference_internal, + "Get a mutable actor based on an index.") + .def("actor_by_name", + pybind11::overload_cast( + &sdf::World::ActorByName), + pybind11::return_value_policy::reference_internal, + "Get a mutable actor based on a name.") .def("frame_count", &sdf::World::FrameCount, "Get the number of explicit frames that are immediate (not nested) " "children of this World object.") diff --git a/src/World.cc b/src/World.cc index 09bb82a76..47706a03e 100644 --- a/src/World.cc +++ b/src/World.cc @@ -757,14 +757,27 @@ Actor *World::ActorByIndex(uint64_t _index) ///////////////////////////////////////////////// bool World::ActorNameExists(const std::string &_name) const { - for (auto const &a : this->dataPtr->actors) + return nullptr != this->ActorByName(_name); +} + +///////////////////////////////////////////////// +const Actor *World::ActorByName(const std::string &_name) const +{ + for (const Actor &a : this->dataPtr->actors) { if (a.Name() == _name) { - return true; + return &a; } } - return false; + return nullptr; +} + +///////////////////////////////////////////////// +Actor *World::ActorByName(const std::string &_name) +{ + return const_cast( + static_cast(this)->ActorByName(_name)); } ////////////////////////////////////////////////// diff --git a/src/World_TEST.cc b/src/World_TEST.cc index b1f93b92e..3083aca3c 100644 --- a/src/World_TEST.cc +++ b/src/World_TEST.cc @@ -58,6 +58,9 @@ TEST(DOMWorld, Construction) EXPECT_EQ(nullptr, world.ModelByName("a::b::c")); EXPECT_EQ(nullptr, world.ModelByName("::::")); + EXPECT_EQ(nullptr, world.ActorByName("")); + EXPECT_EQ(nullptr, world.ActorByName("default")); + EXPECT_EQ(0u, world.FrameCount()); EXPECT_EQ(nullptr, world.FrameByIndex(0)); EXPECT_EQ(nullptr, world.FrameByIndex(1)); @@ -452,15 +455,27 @@ TEST(DOMWorld, AddActor) EXPECT_EQ(1u, world.ActorCount()); EXPECT_FALSE(world.AddActor(actor)); EXPECT_EQ(1u, world.ActorCount()); + EXPECT_NE(nullptr, world.ActorByName("actor1")); world.ClearActors(); EXPECT_EQ(0u, world.ActorCount()); + EXPECT_EQ(nullptr, world.ActorByName("actor1")); EXPECT_TRUE(world.AddActor(actor)); EXPECT_EQ(1u, world.ActorCount()); const sdf::Actor *actorFromWorld = world.ActorByIndex(0); ASSERT_NE(nullptr, actorFromWorld); EXPECT_EQ(actorFromWorld->Name(), actor.Name()); + + const sdf::Actor *actorFromWorldByName = world.ActorByName("actor1"); + ASSERT_NE(nullptr, actorFromWorldByName); + EXPECT_EQ(actorFromWorldByName->Name(), actor.Name()); + + sdf::Actor *mutableActorFromWorldByName = world.ActorByName("actor1"); + ASSERT_NE(nullptr, mutableActorFromWorldByName); + EXPECT_EQ(mutableActorFromWorldByName->Name(), actor.Name()); + mutableActorFromWorldByName->SetName("new_name"); + EXPECT_NE(mutableActorFromWorldByName->Name(), actor.Name()); } /////////////////////////////////////////////////