#include #include #include #include "cddp_core/dynamical_system.hpp" #include "dynamics_model/acrobot.hpp" #include "dynamics_model/bicycle.hpp" #include "dynamics_model/car.hpp" #include "dynamics_model/cartpole.hpp" #include "dynamics_model/dreyfus_rocket.hpp" #include "dynamics_model/dubins_car.hpp" #include "dynamics_model/euler_attitude.hpp" #include "dynamics_model/forklift.hpp" #include "dynamics_model/lti_system.hpp" #include "dynamics_model/manipulator.hpp" #include "dynamics_model/mrp_attitude.hpp" #include "dynamics_model/pendulum.hpp" #include "dynamics_model/quadrotor.hpp" #include "dynamics_model/quadrotor_rate.hpp" #include "dynamics_model/quaternion_attitude.hpp" #include "dynamics_model/spacecraft_landing2d.hpp" #include "dynamics_model/spacecraft_linear.hpp" #include "dynamics_model/spacecraft_linear_fuel.hpp" #include "dynamics_model/spacecraft_nonlinear.hpp" #include "dynamics_model/spacecraft_twobody.hpp" #include "dynamics_model/unicycle.hpp" #include "dynamics_model/usv_3dof.hpp" namespace py = pybind11; class PyDynamicalSystem : public cddp::DynamicalSystem { public: using cddp::DynamicalSystem::DynamicalSystem; cddp::VectorXdual2nd getContinuousDynamicsAutodiff(const cddp::VectorXdual2nd &state, const cddp::VectorXdual2nd &control, double time) const override { throw std::runtime_error( "Python-defined DynamicalSystem objects do not support " "getContinuousDynamicsAutodiff. Override get_state_jacobian, " "get_control_jacobian, and any needed Hessian methods in Python, " "or use a built-in C++ dynamics model."); } Eigen::VectorXd getContinuousDynamics(const Eigen::VectorXd &state, const Eigen::VectorXd &control, double time) const override { // Map C++ virtual dispatch to the snake_case Python API exported below. PYBIND11_OVERRIDE_NAME(Eigen::VectorXd, cddp::DynamicalSystem, "get_continuous_dynamics", getContinuousDynamics, state, control, time); } Eigen::VectorXd getDiscreteDynamics(const Eigen::VectorXd &state, const Eigen::VectorXd &control, double time) const override { PYBIND11_OVERRIDE_NAME(Eigen::VectorXd, cddp::DynamicalSystem, "get_discrete_dynamics", getDiscreteDynamics, state, control, time); } Eigen::MatrixXd getStateJacobian(const Eigen::VectorXd &state, const Eigen::VectorXd &control, double time) const override { PYBIND11_OVERRIDE_NAME(Eigen::MatrixXd, cddp::DynamicalSystem, "get_state_jacobian", getStateJacobian, state, control, time); } Eigen::MatrixXd getControlJacobian(const Eigen::VectorXd &state, const Eigen::VectorXd &control, double time) const override { PYBIND11_OVERRIDE_NAME(Eigen::MatrixXd, cddp::DynamicalSystem, "get_control_jacobian", getControlJacobian, state, control, time); } std::vector getStateHessian(const Eigen::VectorXd &state, const Eigen::VectorXd &control, double time) const override { PYBIND11_OVERRIDE_NAME(std::vector, cddp::DynamicalSystem, "get_state_hessian", getStateHessian, state, control, time); } std::vector getControlHessian(const Eigen::VectorXd &state, const Eigen::VectorXd &control, double time) const override { PYBIND11_OVERRIDE_NAME(std::vector, cddp::DynamicalSystem, "get_control_hessian", getControlHessian, state, control, time); } std::vector getCrossHessian(const Eigen::VectorXd &state, const Eigen::VectorXd &control, double time) const override { PYBIND11_OVERRIDE_NAME(std::vector, cddp::DynamicalSystem, "get_cross_hessian", getCrossHessian, state, control, time); } }; void bind_dynamics(py::module_ &m) { py::class_(m, "DynamicalSystem") .def(py::init(), py::arg("state_dim"), py::arg("control_dim"), py::arg("timestep"), py::arg("integration_type") = "euler") .def("get_continuous_dynamics", &cddp::DynamicalSystem::getContinuousDynamics, py::arg("state"), py::arg("control"), py::arg("time") = 0.0) .def("get_discrete_dynamics", &cddp::DynamicalSystem::getDiscreteDynamics, py::arg("state"), py::arg("control"), py::arg("time") = 0.0) .def("get_state_jacobian", &cddp::DynamicalSystem::getStateJacobian, py::arg("state"), py::arg("control"), py::arg("time") = 0.0) .def("get_control_jacobian", &cddp::DynamicalSystem::getControlJacobian, py::arg("state"), py::arg("control"), py::arg("time") = 0.0) .def("get_state_hessian", &cddp::DynamicalSystem::getStateHessian, py::arg("state"), py::arg("control"), py::arg("time") = 0.0) .def("get_control_hessian", &cddp::DynamicalSystem::getControlHessian, py::arg("state"), py::arg("control"), py::arg("time") = 0.0) .def("get_cross_hessian", &cddp::DynamicalSystem::getCrossHessian, py::arg("state"), py::arg("control"), py::arg("time") = 0.0) .def_property_readonly("state_dim", &cddp::DynamicalSystem::getStateDim) .def_property_readonly("control_dim", &cddp::DynamicalSystem::getControlDim) .def_property_readonly("timestep", &cddp::DynamicalSystem::getTimestep) .def_property_readonly("integration_type", &cddp::DynamicalSystem::getIntegrationType); py::class_(m, "Pendulum") .def(py::init(), py::arg("timestep"), py::arg("length") = 1.0, py::arg("mass") = 1.0, py::arg("damping") = 0.0, py::arg("integration_type") = "euler"); py::class_(m, "Unicycle") .def(py::init(), py::arg("timestep"), py::arg("integration_type") = "euler"); py::class_(m, "Bicycle") .def(py::init(), py::arg("timestep"), py::arg("wheelbase"), py::arg("integration_type") = "euler"); py::class_(m, "Car") .def(py::init(), py::arg("timestep") = 0.03, py::arg("wheelbase") = 2.0, py::arg("integration_type") = "euler"); py::class_(m, "CartPole") .def(py::init(), py::arg("timestep"), py::arg("integration_type") = "rk4", py::arg("cart_mass") = 1.0, py::arg("pole_mass") = 0.2, py::arg("pole_length") = 0.5, py::arg("gravity") = 9.81, py::arg("damping") = 0.0); py::class_(m, "DubinsCar") .def(py::init(), py::arg("speed"), py::arg("timestep"), py::arg("integration_type") = "euler"); py::class_(m, "Forklift") .def(py::init(), py::arg("timestep") = 0.01, py::arg("wheelbase") = 2.0, py::arg("integration_type") = "euler", py::arg("rear_steer") = true, py::arg("max_steering_angle") = 0.785398); py::class_(m, "Acrobot") .def(py::init(), py::arg("timestep"), py::arg("l1") = 1.0, py::arg("l2") = 1.0, py::arg("m1") = 1.0, py::arg("m2") = 1.0, py::arg("J1") = 1.0, py::arg("J2") = 1.0, py::arg("integration_type") = "euler"); py::class_(m, "Quadrotor") .def(py::init(), py::arg("timestep"), py::arg("mass"), py::arg("inertia_matrix"), py::arg("arm_length"), py::arg("integration_type") = "euler"); py::class_(m, "QuadrotorRate") .def(py::init(), py::arg("timestep"), py::arg("mass"), py::arg("max_thrust"), py::arg("max_rate"), py::arg("integration_type") = "euler"); py::class_(m, "Manipulator") .def(py::init(), py::arg("timestep"), py::arg("integration_type") = "rk4"); py::class_(m, "HCW") .def(py::init(), py::arg("timestep"), py::arg("mean_motion"), py::arg("mass"), py::arg("integration_type") = "euler"); py::class_( m, "SpacecraftLinearFuel") .def(py::init(), py::arg("timestep"), py::arg("mean_motion"), py::arg("isp"), py::arg("g0") = 9.80665, py::arg("integration_type") = "euler"); py::class_( m, "SpacecraftNonlinear") .def(py::init(), py::arg("timestep"), py::arg("integration_type") = "rk4", py::arg("mass") = 1.0, py::arg("r_scale") = 1.0, py::arg("v_scale") = 1.0, py::arg("mu") = 1.0); py::class_(m, "DreyfusRocket") .def(py::init(), py::arg("timestep"), py::arg("integration_type") = "rk4", py::arg("thrust_acceleration") = 64.0, py::arg("gravity_acceleration") = 32.0); py::class_( m, "SpacecraftLanding2D") .def(py::init(), py::arg("timestep") = 0.1, py::arg("integration_type") = "rk4", py::arg("mass") = 100000.0, py::arg("length") = 50.0, py::arg("width") = 10.0, py::arg("min_thrust") = 880000.0, py::arg("max_thrust") = 2210000.0, py::arg("max_gimble") = 0.349066); py::class_( m, "SpacecraftTwobody") .def(py::init(), py::arg("timestep"), py::arg("mu"), py::arg("mass")); py::class_(m, "LTISystem") .def(py::init(), py::arg("A"), py::arg("B"), py::arg("timestep"), py::arg("integration_type") = "euler"); py::class_(m, "Usv3Dof") .def(py::init(), py::arg("timestep"), py::arg("integration_type") = "euler"); py::class_(m, "EulerAttitude") .def(py::init(), py::arg("timestep"), py::arg("inertia_matrix"), py::arg("integration_type") = "euler"); py::class_( m, "QuaternionAttitude") .def(py::init(), py::arg("timestep"), py::arg("inertia_matrix"), py::arg("integration_type") = "euler"); py::class_(m, "MrpAttitude") .def(py::init(), py::arg("timestep"), py::arg("inertia_matrix"), py::arg("integration_type") = "euler"); }