From 9045f355dd0197662ecd3a9539fa2c69fe2c100a Mon Sep 17 00:00:00 2001 From: Mikael Arguedas Date: Fri, 22 Dec 2017 16:10:00 +0100 Subject: [PATCH 1/3] move to pybind and move simulator initialization to Python side remove unnecessary include_directories and find_package since SearchForStuff CMake refactor import multiple symbols in simgle import call --- backend/CMakeLists.txt | 9 ------ backend/python_bindings_example.py | 24 ++++++++++++++-- backend/simulation_runner.h | 1 - backend/simulation_runner_py.cc | 44 ++++++++++++++++++------------ 4 files changed, 48 insertions(+), 30 deletions(-) diff --git a/backend/CMakeLists.txt b/backend/CMakeLists.txt index bc3de3198..f58cc7da5 100644 --- a/backend/CMakeLists.txt +++ b/backend/CMakeLists.txt @@ -1,7 +1,5 @@ include (${project_cmake_dir}/Utils.cmake) include_directories(${PYTHON_INCLUDE_DIRS}) -include_directories(${pybind11_INCLUDE_DIRS}) - # ---------------------------------------- # Prepare sources set (sources @@ -40,13 +38,6 @@ delphyne_build_tests(${gtest_sources}) # ---------------------------------------- # Python bindings -# Find necessary packages -find_package(PythonLibs 2.7 REQUIRED) -include_directories(${PYTHON_INCLUDE_DIRS}) - -find_package(Boost COMPONENTS python REQUIRED) -include_directories(${Boost_INCLUDE_DIR}) - # Build the simulation support for python bindings as a library. add_library(simulation-support STATIC diff --git a/backend/python_bindings_example.py b/backend/python_bindings_example.py index 8ffa8e7ac..2adaecda5 100644 --- a/backend/python_bindings_example.py +++ b/backend/python_bindings_example.py @@ -46,7 +46,14 @@ import time from launcher import Launcher -from simulation_runner_py import SimulatorRunner + +from pydrake.common import AddResourceSearchPath + +from simulation_runner_py import ( + AutomotiveSimulator, + SimpleCarState, + SimulatorRunner +) def get_from_env_or_fail(var): @@ -102,6 +109,15 @@ def random_print(): print("One in five hundred") +def create_and_init_automotive_simulator(): + simulator = AutomotiveSimulator() + state = SimpleCarState() + state.y = 0.0 + simulator.AddPriusSimpleCar("0", "DRIVING_COMMAND_0", state) + + return simulator + + def main(): """Spawn an automotive simulator making use of the python bindings""" stats = SimulationStats() @@ -111,6 +127,10 @@ def main(): lcm_ign_bridge = "duplex-ign-lcm-bridge" ign_visualizer = "visualizer" + drake_install_path = get_from_env_or_fail('DRAKE_INSTALL_PATH') + AddResourceSearchPath(os.path.join(drake_install_path, "share", "drake")) + + simulator = create_and_init_automotive_simulator() try: launcher.launch([lcm_ign_bridge, "1"]) teleop_config = os.path.join(delphyne_ws_dir, @@ -120,7 +140,7 @@ def main(): "layoutWithTeleop.config") launcher.launch([ign_visualizer, teleop_config]) - runner = SimulatorRunner() + runner = SimulatorRunner(simulator, 0.001) # Add a callback to record and print statistics runner.AddStepCallback(stats.record_tick) # Add a second callback that prints a message roughly every 500 calls diff --git a/backend/simulation_runner.h b/backend/simulation_runner.h index 213cda81c..41bfc01fd 100644 --- a/backend/simulation_runner.h +++ b/backend/simulation_runner.h @@ -39,7 +39,6 @@ #include #include -#include #include #include "backend/automotive_simulator.h" diff --git a/backend/simulation_runner_py.cc b/backend/simulation_runner_py.cc index 0ea925de8..08549e8f1 100644 --- a/backend/simulation_runner_py.cc +++ b/backend/simulation_runner_py.cc @@ -35,7 +35,11 @@ #include "backend/automotive_simulator.h" #include "backend/simulation_runner.h" +namespace py = pybind11; + +using delphyne::backend::AutomotiveSimulator; using delphyne::backend::SimulatorRunner; +using drake::automotive::SimpleCarState; // Since we are not yet exporting the AutomotiveSimulator class we need to // provide a ready-to-run SimulatorRunner. To do so we create a parameterless @@ -43,33 +47,37 @@ using delphyne::backend::SimulatorRunner; // keep adding python bindings to C++ classes this code will be moved to the // python scripts that launches the simulation. -namespace py = pybind11; - namespace { PYBIND11_MODULE(simulation_runner_py, m) { py::class_(m, "SimulatorRunner") - .def(py::init([](void) { - // TODO(mikaelaguedas) All this should be done in Python using pydrake - // and custom bindings for AutomotiveSimulator and SimpleCarState - drake::AddResourceSearchPath(std::string(std::getenv("DRAKE_INSTALL_PATH")) + - "/share/drake"); - - auto simulator = - std::make_unique>(); - - // Add a Prius car. - drake::automotive::SimpleCarState state; - state.set_y(0.0); - simulator->AddPriusSimpleCar("0", "DRIVING_COMMAND_0", state); - - // Instantiate the simulator runner and pass the simulator. - const double time_step = 0.001; + .def(py::init([](std::unique_ptr> simulator, double time_step) { return std::make_unique(std::move(simulator), time_step); })) .def("Start", &SimulatorRunner::Start) .def("Stop", &SimulatorRunner::Stop) .def("AddStepCallback", &SimulatorRunner::AddStepCallback); ; + py::class_, std::unique_ptr>>(m, "AutomotiveSimulator") + .def(py::init([](void) { + return std::make_unique>(); + })) + .def("Start", &AutomotiveSimulator::Start) + .def("AddPriusSimpleCar", &AutomotiveSimulator::AddPriusSimpleCar) + .def("AddMobilControlledSimpleCar", &AutomotiveSimulator::AddMobilControlledSimpleCar) + // TODO(mikaelarguedas) bind more method depending on what we need + // .def("AddPriusTrajectoryCar", &AutomotiveSimulator::AddPriusTrajectoryCar) + // .def("AddPriusMaliputRailcar", &AutomotiveSimulator::AddPriusMaliputRailcar) + // .def("AddIdmControlledPriusMaliputRailcar", &AutomotiveSimulator::AddIdmControlledPriusMaliputRailcar) + // .def("SetMaliputRailcarAccelerationCommand", &AutomotiveSimulator::SetMaliputRailcarAccelerationCommand) + ; + py::class_>(m, "SimpleCarState") + .def(py::init<>()) + .def_property("x", &SimpleCarState::x, &SimpleCarState::set_x) + .def_property("y", &SimpleCarState::y, &SimpleCarState::set_y) + .def_property("heading", &SimpleCarState::heading, &SimpleCarState::set_heading) + .def_property("velocity", &SimpleCarState::velocity, &SimpleCarState::set_velocity) + .def("get_coordinates_names", &SimpleCarState::GetCoordinateNames) + ; } } // namespace From 06edbb03dabe0b655b9a7e251786179db7dbb93f Mon Sep 17 00:00:00 2001 From: Mikael Arguedas Date: Fri, 22 Dec 2017 16:23:49 +0100 Subject: [PATCH 2/3] document missing bindings and their dependencies add todo for contributing some bindings upstream --- backend/simulation_runner_py.cc | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/backend/simulation_runner_py.cc b/backend/simulation_runner_py.cc index 08549e8f1..8417a7e60 100644 --- a/backend/simulation_runner_py.cc +++ b/backend/simulation_runner_py.cc @@ -65,11 +65,32 @@ PYBIND11_MODULE(simulation_runner_py, m) { .def("AddPriusSimpleCar", &AutomotiveSimulator::AddPriusSimpleCar) .def("AddMobilControlledSimpleCar", &AutomotiveSimulator::AddMobilControlledSimpleCar) // TODO(mikaelarguedas) bind more method depending on what we need + // Needs drake::automotive::Curve2& // .def("AddPriusTrajectoryCar", &AutomotiveSimulator::AddPriusTrajectoryCar) + // Needs: + // - drake::automotive::LaneDirection + // - drake::automotive::MaliputRailcarParams + // - drake::automotive::MaliputRailcarState // .def("AddPriusMaliputRailcar", &AutomotiveSimulator::AddPriusMaliputRailcar) + // Needs: + // - drake::automotive::LaneDirection + // - drake::automotive::MaliputRailcarParams + // - drake::automotive::MaliputRailcarState // .def("AddIdmControlledPriusMaliputRailcar", &AutomotiveSimulator::AddIdmControlledPriusMaliputRailcar) // .def("SetMaliputRailcarAccelerationCommand", &AutomotiveSimulator::SetMaliputRailcarAccelerationCommand) + // Needs drake::maliput::api::RoadGeometry binding + // .def("SetRoadGeometry", &AutomotiveSimulator::SetRoadGeometry) + // Needs drake::maliput::api::Lane binding + // .def("FindLane", &AutomotiveSimulator::FindLane) + // Needs drake::systems::System binding + // .def("GetDiagramSystemByName", &AutomotiveSimulator::GetDiagramSystemByName) + // .def("Build", &AutomotiveSimulator::Build) + // .def("GetDiagram", &AutomotiveSimulator::GetDiagram) + // .def("StepBy", &AutomotiveSimulator::StepBy) + // Needs drake::systems::rendering::PoseBundle binding + // .def("GetCurrentPoses", &AutomotiveSimulator::GetCurrentPoses) ; + // TODO(mikaelarguedas) Submit this to upstream Drake py::class_>(m, "SimpleCarState") .def(py::init<>()) .def_property("x", &SimpleCarState::x, &SimpleCarState::set_x) From 57dea01ffb1610fd809d6e03e38fe7704c92f09d Mon Sep 17 00:00:00 2001 From: Mikael Arguedas Date: Tue, 2 Jan 2018 17:32:09 +0100 Subject: [PATCH 3/3] address review comments --- backend/python_bindings_example.py | 5 +---- backend/simulation_runner_py.cc | 2 +- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/backend/python_bindings_example.py b/backend/python_bindings_example.py index 2adaecda5..6bf105273 100644 --- a/backend/python_bindings_example.py +++ b/backend/python_bindings_example.py @@ -66,10 +66,7 @@ def get_from_env_or_fail(var): # Since it is an environment variable, the very end may have a colon; # strip it here - if value[-1] == ':': - value = value[:-1] - - return value + return value.rstrip(':') class SimulationStats(object): diff --git a/backend/simulation_runner_py.cc b/backend/simulation_runner_py.cc index 8417a7e60..52b4af624 100644 --- a/backend/simulation_runner_py.cc +++ b/backend/simulation_runner_py.cc @@ -57,7 +57,7 @@ PYBIND11_MODULE(simulation_runner_py, m) { .def("Stop", &SimulatorRunner::Stop) .def("AddStepCallback", &SimulatorRunner::AddStepCallback); ; - py::class_, std::unique_ptr>>(m, "AutomotiveSimulator") + py::class_>(m, "AutomotiveSimulator") .def(py::init([](void) { return std::make_unique>(); }))