-
Notifications
You must be signed in to change notification settings - Fork 38
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add python bindings for FloatingBaseEstimator and LeggedOdometry #218
Changes from all commits
26a1884
aeee8e6
c515ba4
69f96dd
eba66c8
0a86455
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,167 @@ | ||
/** | ||
* @file FloatingBaseEstimators.cpp | ||
* @authors Prashanth Ramadoss | ||
* @copyright 2020 Istituto Italiano di Tecnologia (IIT). This software may be modified and | ||
* distributed under the terms of the GNU Lesser General Public License v2.1 or any later version. | ||
*/ | ||
|
||
#include <pybind11/eigen.h> | ||
#include <pybind11/pybind11.h> | ||
#include <pybind11/stl.h> | ||
|
||
#include <BipedalLocomotion/FloatingBaseEstimators/FloatingBaseEstimator.h> | ||
#include <BipedalLocomotion/FloatingBaseEstimators/ModelComputationsHelper.h> | ||
|
||
#include "bipedal_locomotion_framework.h" | ||
|
||
void BipedalLocomotion::bindings::CreateKinDynComputations(pybind11::module& module) | ||
{ | ||
namespace py = ::pybind11; | ||
using namespace iDynTree; | ||
py::class_<KinDynComputations, std::shared_ptr<KinDynComputations>>(module, | ||
"KinDynComputations"); | ||
} | ||
|
||
void BipedalLocomotion::bindings::CreateKinDynComputationsDescriptor(pybind11::module& module) | ||
{ | ||
namespace py = ::pybind11; | ||
using namespace BipedalLocomotion::ParametersHandler; | ||
using namespace BipedalLocomotion::Estimators; | ||
|
||
py::class_<KinDynComputationsDescriptor>(module, "KinDynComputationsDescriptor") | ||
.def(py::init()) | ||
.def_readwrite("kindyn", &KinDynComputationsDescriptor::kindyn) | ||
.def("is_valid", &KinDynComputationsDescriptor::isValid); | ||
|
||
module.def( | ||
"construct_kindyncomputations_descriptor", | ||
[](std::shared_ptr<IParametersHandler> handler) -> KinDynComputationsDescriptor { | ||
return constructKinDynComputationsDescriptor(handler); | ||
}, | ||
py::arg("handler")); | ||
} | ||
|
||
void BipedalLocomotion::bindings::CreateFloatingBaseEstimator(pybind11::module& module) | ||
{ | ||
namespace py = ::pybind11; | ||
|
||
using namespace BipedalLocomotion::System; | ||
using namespace BipedalLocomotion::ParametersHandler; | ||
using namespace BipedalLocomotion::Contacts; | ||
using namespace BipedalLocomotion::Estimators; | ||
using namespace BipedalLocomotion::Estimators::FloatingBaseEstimators; | ||
|
||
py::class_<InternalState>(module, "FloatingBaseEstimatorInternalState") | ||
.def(py::init()) | ||
.def_readwrite("imu_orientation", &InternalState::imuOrientation) | ||
.def_readwrite("imu_position", &InternalState::imuPosition) | ||
.def_readwrite("imu_linear_velocity", &InternalState::imuLinearVelocity) | ||
.def_readwrite("imu_angular_velocity", &InternalState::imuAngularVelocity) | ||
.def_readwrite("support_frame_data", &InternalState::supportFrameData) | ||
.def_readwrite("accelerometer_bias", &InternalState::accelerometerBias) | ||
.def_readwrite("gyroscope_bias", &InternalState::gyroscopeBias) | ||
.def_readwrite("l_contact_frame_orientation", &InternalState::lContactFrameOrientation) | ||
.def_readwrite("l_contact_frame_position", &InternalState::lContactFramePosition) | ||
.def_readwrite("r_contact_frame_orientation", &InternalState::rContactFrameOrientation) | ||
.def_readwrite("r_contact_frame_position", &InternalState::rContactFramePosition); | ||
|
||
py::class_<StateStdDev>(module, "FloatingBaseEstimatorStateStdDev") | ||
.def(py::init()) | ||
.def_readwrite("imu_orientation", &StateStdDev::imuOrientation) | ||
.def_readwrite("imu_position", &StateStdDev::imuPosition) | ||
.def_readwrite("imu_linear_velocity", &StateStdDev::imuLinearVelocity) | ||
.def_readwrite("accelerometer_bias", &StateStdDev::accelerometerBias) | ||
.def_readwrite("gyroscope_bias", &StateStdDev::gyroscopeBias) | ||
.def_readwrite("l_contact_frame_orientation", &StateStdDev::lContactFrameOrientation) | ||
.def_readwrite("l_contact_frame_position", &StateStdDev::lContactFramePosition) | ||
.def_readwrite("r_contact_frame_orientation", &StateStdDev::rContactFrameOrientation) | ||
.def_readwrite("r_contact_frame_position", &StateStdDev::rContactFramePosition); | ||
|
||
py::class_<Output>(module, "FloatingBaseEstimatorOutput") | ||
.def(py::init()) | ||
.def_readwrite("state", &Output::state) | ||
.def_readwrite("state_std_dev", &Output::stateStdDev) | ||
.def_readwrite("base_pose", &Output::basePose) | ||
.def_readwrite("base_twist", &Output::baseTwist); | ||
|
||
py::class_<Measurements>(module, "FloatingBaseEstimatorMeasurements") | ||
.def(py::init()) | ||
.def_readwrite("acc", &Measurements::acc) | ||
.def_readwrite("gyro", &Measurements::gyro) | ||
.def_readwrite("encoders", &Measurements::encoders) | ||
.def_readwrite("encoder_speeds", &Measurements::encodersSpeed) | ||
.def_readwrite("stamped_contact_status", &Measurements::stampedContactsStatus) | ||
.def_readwrite("lf_in_contact", &Measurements::lfInContact) | ||
.def_readwrite("rf_in_contact", &Measurements::rfInContact); | ||
|
||
py::class_<Options>(module, "FloatingBaseEstimatorOptions") | ||
.def(py::init()) | ||
.def_readwrite("imu_bias_estimation_enabled", &Options::imuBiasEstimationEnabled) | ||
.def_readwrite("static_imu_bias_initialization_enabled", | ||
&Options::staticImuBiasInitializationEnabled) | ||
.def_readwrite("nr_samples_for_imu_bias_initialization", | ||
&Options::nrSamplesForImuBiasInitialization) | ||
.def_readwrite("ekf_update_enabled", &Options::ekfUpdateEnabled) | ||
.def_readwrite("acceleration_due_to_gravity", &Options::accelerationDueToGravity); | ||
|
||
py::class_<SensorsStdDev>(module, "FloatingBaseEstimatorSensorsStdDev") | ||
.def(py::init()) | ||
.def_readwrite("accelerometer_noise", &SensorsStdDev::accelerometerNoise) | ||
.def_readwrite("gyroscope_noise", &SensorsStdDev::gyroscopeNoise) | ||
.def_readwrite("accelerometer_bias_noise", &SensorsStdDev::accelerometerBiasNoise) | ||
.def_readwrite("gyroscope_bias_noise", &SensorsStdDev::gyroscopeBiasNoise) | ||
.def_readwrite("contact_foot_lin_vel_noise", &SensorsStdDev::contactFootLinvelNoise) | ||
.def_readwrite("contact_foot_ang_vel_noise", &SensorsStdDev::contactFootAngvelNoise) | ||
.def_readwrite("swing_foot_lin_vel_noise", &SensorsStdDev::swingFootLinvelNoise) | ||
.def_readwrite("swing_foot_ang_vel_noise", &SensorsStdDev::swingFootAngvelNoise) | ||
.def_readwrite("forward_kinematics_noise", &SensorsStdDev::forwardKinematicsNoise) | ||
.def_readwrite("encoders_noise", &SensorsStdDev::encodersNoise); | ||
|
||
py::class_<Advanceable<Output>>(module, "FloatingBaseEstimatorOutputAdvanceable"); | ||
|
||
py::class_<FloatingBaseEstimator, Advanceable<Output>> floatingBaseEstimator(module, | ||
"FloatingBaseEstimator"); | ||
|
||
floatingBaseEstimator.def(py::init()) | ||
.def("set_imu_measurement", | ||
&FloatingBaseEstimator::setIMUMeasurement, | ||
py::arg("acc_meas"), | ||
py::arg("gyro_meas")) | ||
.def("set_contact_status", | ||
&FloatingBaseEstimator::setContactStatus, | ||
py::arg("name"), | ||
py::arg("contact_status"), | ||
py::arg("switch_time"), | ||
py::arg("time_now")) | ||
.def("set_kinematics", | ||
&FloatingBaseEstimator::setKinematics, | ||
py::arg("encoders"), | ||
py::arg("encoder_speeds")) | ||
.def("advance", &FloatingBaseEstimator::advance) | ||
.def("reset_estimator", | ||
py::overload_cast<const InternalState&>(&FloatingBaseEstimator::resetEstimator), | ||
py::arg("new_state")) | ||
.def("reset_estimator", | ||
py::overload_cast<const Eigen::Quaterniond&, const Eigen::Vector3d&>( | ||
&FloatingBaseEstimator::resetEstimator), | ||
py::arg("new_base_orientation"), | ||
py::arg("new_base_position")) | ||
.def("get", &FloatingBaseEstimator::get) | ||
.def("is_valid", &FloatingBaseEstimator::isValid) | ||
.def( | ||
"initialize", | ||
[](FloatingBaseEstimator& impl, | ||
std::shared_ptr<IParametersHandler> handler, | ||
std::shared_ptr<iDynTree::KinDynComputations> kinDyn) -> bool { | ||
return impl.initialize(handler, kinDyn); | ||
}, | ||
py::arg("handler"), | ||
py::arg("kindyn")); | ||
|
||
// at the moment at an interface level, this nested class need not be exposed | ||
// but in case, we want to use the FloatingBaseEstimator as base class | ||
// for python based implementations, maybe it could be useful | ||
Comment on lines
+161
to
+163
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is definitely possible with pybind, but it requires quite a lot of work since it demands creating a dummy class (called trampoline) for the interface. In my opinion, once the entire infrastructure is up and running, this could be a great alternative for prototyping, but as you wrote, let's keep this option for future work. |
||
py::class_<FloatingBaseEstimator::ModelComputations>(floatingBaseEstimator, | ||
"FloatingBaseEstimatorModelComputations") | ||
.def(py::init()); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
/** | ||
* @file LeggedOdometry.cpp | ||
* @authors Prashanth Ramadoss | ||
* @copyright 2020 Istituto Italiano di Tecnologia (IIT). This software may be modified and | ||
* distributed under the terms of the GNU Lesser General Public License v2.1 or any later version. | ||
*/ | ||
|
||
#include <pybind11/eigen.h> | ||
#include <pybind11/pybind11.h> | ||
#include <pybind11/stl.h> | ||
|
||
#include <BipedalLocomotion/FloatingBaseEstimators/FloatingBaseEstimator.h> | ||
#include <BipedalLocomotion/FloatingBaseEstimators/LeggedOdometry.h> | ||
#include "bipedal_locomotion_framework.h" | ||
|
||
void BipedalLocomotion::bindings::CreateLeggedOdometry(pybind11::module& module) | ||
{ | ||
namespace py = ::pybind11; | ||
|
||
using namespace BipedalLocomotion::System; | ||
using namespace BipedalLocomotion::ParametersHandler; | ||
using namespace BipedalLocomotion::Contacts; | ||
using namespace BipedalLocomotion::Estimators; | ||
using namespace BipedalLocomotion::Estimators::FloatingBaseEstimators; | ||
|
||
py::class_<LeggedOdometry, FloatingBaseEstimator>(module, "LeggedOdometry") | ||
.def(py::init()) | ||
.def("initialize", | ||
[](LeggedOdometry& impl, | ||
std::shared_ptr<IParametersHandler> handler, | ||
std::shared_ptr<iDynTree::KinDynComputations> kinDyn) -> bool { | ||
return impl.initialize(handler, kinDyn); | ||
}, | ||
py::arg("handler"), py::arg("kindyn")) | ||
.def("set_imu_measurement", &LeggedOdometry::setIMUMeasurement, | ||
py::arg("acc_meas"), py::arg("gyro_meas")) | ||
.def("set_contact_status", &LeggedOdometry::setContactStatus, | ||
py::arg("name"), py::arg("contact_status"), py::arg("switch_time"), py::arg("time_now")) | ||
.def("set_kinematics", &LeggedOdometry::setKinematics, | ||
py::arg("encoders"), py::arg("encoder_speeds")) | ||
.def("advance", &LeggedOdometry::advance) | ||
.def("reset_estimator", py::overload_cast<const InternalState&>(&LeggedOdometry::resetEstimator), | ||
py::arg("new_state")) | ||
.def("reset_estimator", | ||
py::overload_cast<const Eigen::Quaterniond&, const Eigen::Vector3d&>(&LeggedOdometry::resetEstimator), | ||
py::arg("new_imu_orientation"), py::arg("new_imu_position")) | ||
.def("reset_estimator", py::overload_cast<>(&LeggedOdometry::resetEstimator)) | ||
.def("reset_estimator", | ||
py::overload_cast<const std::string&, const Eigen::Quaterniond&, const Eigen::Vector3d&>(&LeggedOdometry::resetEstimator), | ||
py::arg("ref_frame_for_world"),py::arg("world_orientation_in_ref_frame"), py::arg("world_position_in_ref_frame")) | ||
.def("change_fixed_frame", | ||
py::overload_cast<const std::ptrdiff_t&>(&LeggedOdometry::changeFixedFrame), | ||
py::arg("frame_index")) | ||
.def("change_fixed_frame", | ||
py::overload_cast<const std::ptrdiff_t&, const Eigen::Quaterniond&, const Eigen::Vector3d&>(&LeggedOdometry::changeFixedFrame), | ||
py::arg("frame_index"), py::arg("frame_orientation_in_world"), py::arg("frame_position_in_world")) | ||
.def("get_fixed_frame_index", &LeggedOdometry::getFixedFrameIdx) | ||
.def("get", &LeggedOdometry::get) | ||
.def("is_valid", &LeggedOdometry::isValid); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Any reason to separate methods definition from the creation of the
py::class_
object?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It was suggested as a way to handle nested classes or internal types.
I followed examples suggested in,
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, only now I see that the object is used below, good to know!