From 1ef6b7c25d057b21d1152700992f361b6a5cb4ff Mon Sep 17 00:00:00 2001 From: Mikael Arguedas Date: Fri, 22 Dec 2017 16:10:00 +0100 Subject: [PATCH] move to pybind and move simulator initialization to Python side --- backend/CMakeLists.txt | 4 +-- backend/python_bindings_example.py | 20 +++++++++++++- backend/simulation_runner.h | 1 - backend/simulation_runner_py.cc | 44 ++++++++++++++++++------------ 4 files changed, 47 insertions(+), 22 deletions(-) diff --git a/backend/CMakeLists.txt b/backend/CMakeLists.txt index bc3de3198..f462dade8 100644 --- a/backend/CMakeLists.txt +++ b/backend/CMakeLists.txt @@ -44,8 +44,8 @@ delphyne_build_tests(${gtest_sources}) find_package(PythonLibs 2.7 REQUIRED) include_directories(${PYTHON_INCLUDE_DIRS}) -find_package(Boost COMPONENTS python REQUIRED) -include_directories(${Boost_INCLUDE_DIR}) +find_package(pybind11 REQUIRED) +include_directories(${pybind11_INCLUDE_DIRS}) # Build the simulation support for python bindings as a library. add_library(simulation-support diff --git a/backend/python_bindings_example.py b/backend/python_bindings_example.py index 8ffa8e7ac..5dad1b50e 100644 --- a/backend/python_bindings_example.py +++ b/backend/python_bindings_example.py @@ -46,6 +46,11 @@ import time from launcher import Launcher + +from pydrake.common import AddResourceSearchPath + +from simulation_runner_py import AutomotiveSimulator +from simulation_runner_py import SimpleCarState from simulation_runner_py import SimulatorRunner @@ -102,6 +107,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 +125,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 +138,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