From 476d587a7d501abd1e4e8c9ac3f65c508b703037 Mon Sep 17 00:00:00 2001 From: nsubiron Date: Wed, 3 Apr 2019 18:22:50 +0200 Subject: [PATCH] Add carla.command to spawn actors in batch --- LibCarla/source/carla/Overload.h | 25 +++++++++++++ LibCarla/source/carla/rpc/Command.h | 17 +++++++++ PythonAPI/carla/source/libcarla/Commands.cpp | 37 ++++++++++++++++++- .../Source/Carla/Server/TheNewCarlaServer.cpp | 35 +++++++++++++----- 4 files changed, 103 insertions(+), 11 deletions(-) diff --git a/LibCarla/source/carla/Overload.h b/LibCarla/source/carla/Overload.h index 933d864c1..06d3342d9 100644 --- a/LibCarla/source/carla/Overload.h +++ b/LibCarla/source/carla/Overload.h @@ -30,11 +30,36 @@ namespace detail { using T::operator(); }; + template + struct Recursive { + + explicit Recursive(T &&func) : _func(std::move(func)) {} + + template + auto operator()(Ts &&... arguments) const { + return _func(*this, std::forward(arguments)...); + } + + private: + + T _func; + }; + } // namespace detail + template + inline static auto MakeRecursive(FuncT &&func) { + return detail::Recursive(std::forward(func)); + } + template inline static auto MakeOverload(FuncTs &&... fs) { return detail::Overload(std::forward(fs)...); } + template + inline static auto MakeRecursiveOverload(FuncTs &&... fs) { + return MakeRecursive(MakeOverload(std::forward(fs)...)); + } + } // namespace carla diff --git a/LibCarla/source/carla/rpc/Command.h b/LibCarla/source/carla/rpc/Command.h index 1180e20b6..97f4d6ef0 100644 --- a/LibCarla/source/carla/rpc/Command.h +++ b/LibCarla/source/carla/rpc/Command.h @@ -30,6 +30,22 @@ namespace rpc { public: + struct SpawnActor : CommandBase { + SpawnActor() = default; + SpawnActor(ActorDescription description, const geom::Transform &transform) + : description(std::move(description)), + transform(transform) {} + SpawnActor(ActorDescription description, const geom::Transform &transform, ActorId parent) + : description(std::move(description)), + transform(transform), + parent(parent) {} + ActorDescription description; + geom::Transform transform; + boost::optional parent; + std::vector do_after; + MSGPACK_DEFINE_ARRAY(description, transform, parent, do_after); + }; + struct DestroyActor : CommandBase { DestroyActor() = default; DestroyActor(ActorId id) : actor(id) {} @@ -102,6 +118,7 @@ namespace rpc { }; using CommandType = boost::variant< + SpawnActor, DestroyActor, ApplyVehicleControl, ApplyWalkerControl, diff --git a/PythonAPI/carla/source/libcarla/Commands.cpp b/PythonAPI/carla/source/libcarla/Commands.cpp index 565be2efe..74fb2662d 100644 --- a/PythonAPI/carla/source/libcarla/Commands.cpp +++ b/PythonAPI/carla/source/libcarla/Commands.cpp @@ -27,6 +27,18 @@ namespace command_impl { return self.attr("__init__")(Convert(args)...); } + template + static boost::python::object CustomSpawnActorInit(boost::python::object self, ArgsT... args) { + return self.attr("__init__")(carla::rpc::Command::SpawnActor{Convert(args)...}); + } + + static carla::rpc::Command::SpawnActor Then( + carla::rpc::Command::SpawnActor &self, + carla::rpc::Command command) { + self.do_after.push_back(command); + return self; + } + } // namespace command_impl void export_commands() { @@ -39,7 +51,29 @@ void export_commands() { object command_module(handle<>(borrowed(PyImport_AddModule("libcarla.command")))); scope().attr("command") = command_module; - scope io_scope = command_module; + scope submodule_scope = command_module; + + // This is a handler for passing to "SpawnActor.then" commands. + submodule_scope.attr("FutureActor") = 0u; + + class_("SpawnActor") + .def( + "__init__", + &command_impl::CustomSpawnActorInit, + (arg("blueprint"), arg("transform"))) + .def( + "__init__", + &command_impl::CustomSpawnActorInit, + (arg("blueprint"), arg("transform"), arg("parent_id"))) + .def( + "__init__", + &command_impl::CustomSpawnActorInit, + (arg("blueprint"), arg("transform"), arg("parent"))) + .def(init()) + .def_readwrite("transform", &cr::Command::SpawnActor::transform) + .def_readwrite("parent_id", &cr::Command::SpawnActor::parent) + .def("then", &command_impl::Then, (arg("command"))) + ; class_("DestroyActor") .def("__init__", &command_impl::CustomInit, (arg("actor"))) @@ -103,6 +137,7 @@ void export_commands() { .def_readwrite("enabled", &cr::Command::SetAutopilot::enabled) ; + implicitly_convertible(); implicitly_convertible(); implicitly_convertible(); implicitly_convertible(); diff --git a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Server/TheNewCarlaServer.cpp b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Server/TheNewCarlaServer.cpp index 6ce3fda25..6dfd103bd 100644 --- a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Server/TheNewCarlaServer.cpp +++ b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Server/TheNewCarlaServer.cpp @@ -776,16 +776,31 @@ void FTheNewCarlaServer::FPimpl::BindActions() using C = cr::Command; - auto command_visitor = carla::MakeOverload( - [=](const C::DestroyActor &c) { destroy_actor(c.actor); }, - [=](const C::ApplyVehicleControl &c) { apply_control_to_vehicle(c.actor, c.control); }, - [=](const C::ApplyWalkerControl &c) { apply_control_to_walker(c.actor, c.control); }, - [=](const C::ApplyTransform &c) { set_actor_transform(c.actor, c.transform); }, - [=](const C::ApplyVelocity &c) { set_actor_velocity(c.actor, c.velocity); }, - [=](const C::ApplyAngularVelocity &c) { set_actor_angular_velocity(c.actor, c.angular_velocity); }, - [=](const C::ApplyImpulse &c) { add_actor_impulse(c.actor, c.impulse); }, - [=](const C::SetSimulatePhysics &c) { set_actor_simulate_physics(c.actor, c.enabled); }, - [=](const C::SetAutopilot &c) { set_actor_autopilot(c.actor, c.enabled); }, + auto command_visitor = carla::MakeRecursiveOverload( + [=](auto self, const C::SpawnActor &c) -> void { + auto result = c.parent.has_value() ? + spawn_actor_with_parent(c.description, c.transform, *c.parent) : + spawn_actor(c.description, c.transform); + if (!result.HasError()) { + carla::ActorId id = result.Get().id; + auto set_id = carla::MakeOverload( + [](C::SpawnActor &) {}, + [id](auto &s) { s.actor = id; }); + for (auto command : c.do_after) { + boost::apply_visitor(set_id, command.command); + boost::apply_visitor(self, command.command); + } + } + }, + [=](auto, const C::DestroyActor &c) { destroy_actor(c.actor); }, + [=](auto, const C::ApplyVehicleControl &c) { apply_control_to_vehicle(c.actor, c.control); }, + [=](auto, const C::ApplyWalkerControl &c) { apply_control_to_walker(c.actor, c.control); }, + [=](auto, const C::ApplyTransform &c) { set_actor_transform(c.actor, c.transform); }, + [=](auto, const C::ApplyVelocity &c) { set_actor_velocity(c.actor, c.velocity); }, + [=](auto, const C::ApplyAngularVelocity &c) { set_actor_angular_velocity(c.actor, c.angular_velocity); }, + [=](auto, const C::ApplyImpulse &c) { add_actor_impulse(c.actor, c.impulse); }, + [=](auto, const C::SetSimulatePhysics &c) { set_actor_simulate_physics(c.actor, c.enabled); }, + [=](auto, const C::SetAutopilot &c) { set_actor_autopilot(c.actor, c.enabled); }, [](const auto &) { UE_LOG(LogCarla, Fatal, TEXT("Invalid command!")); }); BIND_SYNC(apply_batch) << [=](const std::vector &commands, bool do_tick_cue) -> R