diff --git a/demos/CMakeLists.txt b/demos/CMakeLists.txt index 4b0ffd1421c71d6ae56ad8704489d6c3231ec391..78d2b265912a542724c6ccaa3609638dc49259e2 100644 --- a/demos/CMakeLists.txt +++ b/demos/CMakeLists.txt @@ -8,6 +8,10 @@ if (pinocchio_FOUND) include_directories( SYSTEM ${PINOCCHIO_INCLUDE_DIRS} ) + + add_library(mcapi_utils mcapi_utils.cpp) + target_link_libraries(mcapi_utils Eigen3::Eigen) + add_executable(solo_real_povcdl_estimation solo_real_povcdl_estimation.cpp) target_link_libraries(solo_real_povcdl_estimation wolfcore @@ -16,6 +20,7 @@ if (pinocchio_FOUND) ${pinocchio_LIBRARIES} /usr/local/lib/libcnpy.so z + mcapi_utils ) add_executable(solo_imu_mocap solo_imu_mocap.cpp) diff --git a/demos/mcapi_utils.cpp b/demos/mcapi_utils.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d893b4669ce2514f3f15b3bf73500f243923e19c --- /dev/null +++ b/demos/mcapi_utils.cpp @@ -0,0 +1,77 @@ +//--------LICENSE_START-------- +// +// Copyright (C) 2020,2021,2022 Institut de Robòtica i Informà tica Industrial, CSIC-UPC. +// Authors: Joan Solà Ortega (jsola@iri.upc.edu) +// All rights reserved. +// +// This file is part of WOLF +// WOLF is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. +// +//--------LICENSE_END-------- + + +#include "mcapi_utils.h" + +Vector3d computeAccFromSpatial(const Vector3d& ddr, const Vector3d& w, const Vector3d& dr) +{ + return ddr + w.cross(dr); +} + + +std::vector<Vector3d> contacts_from_footrect_center() +{ + // compute feet corners coordinates like from the leg_X_6_joint + double lx = 0.1; + double ly = 0.065; + double lz = 0.107; + std::vector<Vector3d> contacts; contacts.resize(4); + contacts[0] = {-lx, -ly, -lz}; + contacts[1] = {-lx, ly, -lz}; + contacts[2] = { lx, -ly, -lz}; + contacts[3] = { lx, ly, -lz}; + return contacts; +} + + +Matrix<double, 6, 1> contact_force_to_wrench(const std::vector<Vector3d>& contacts, + const Matrix<double, 12, 1>& cf12) +{ + Vector3d f = cf12.segment<3>(0) + cf12.segment<3>(3) + cf12.segment<3>(6) + cf12.segment<3>(9); + Vector3d tau = contacts[0].cross(cf12.segment<3>(0)) + + contacts[1].cross(cf12.segment<3>(3)) + + contacts[2].cross(cf12.segment<3>(6)) + + contacts[3].cross(cf12.segment<3>(9)); + Matrix<double, 6, 1> wrench; wrench << f, tau; + return wrench; +} + + +Matrix3d compute_Iw(pinocchio::Model& model, + pinocchio::Data& data, + VectorXd& q_static, + Vector3d& b_p_bc) +{ + MatrixXd b_Mc = pinocchio::crba(model, data, q_static); // mass matrix at b frame expressed in b frame + // MatrixXd b_Mc = crba(model_dist, data_dist, q_static); // mass matrix at b frame expressed in b frame + MatrixXd b_I_b = b_Mc.topLeftCorner<6,6>(); // inertia matrix at b frame expressed in b frame + pinocchio::SE3 bTc (Eigen::Matrix3d::Identity(), b_p_bc); // "no free flyer robot -> c frame oriented the same as b" + pinocchio::SE3 cTb = bTc.inverse(); + // Ic = cXb^star * Ib * bXc = bXc^T * Ib * bXc + // c_I_c block diagonal: + // [m*Id3, 03; + // 0, Iw] + MatrixXd c_I_c = cTb.toDualActionMatrix() * b_I_b * bTc.toActionMatrix(); + Matrix3d b_Iw = c_I_c.bottomRightCorner<3,3>(); // meas + return b_Iw; +} diff --git a/demos/mcapi_utils.h b/demos/mcapi_utils.h new file mode 100644 index 0000000000000000000000000000000000000000..c62c4026a1dac41733350f2b96fb554285f30715 --- /dev/null +++ b/demos/mcapi_utils.h @@ -0,0 +1,76 @@ +//--------LICENSE_START-------- +// +// Copyright (C) 2020,2021,2022 Institut de Robòtica i Informà tica Industrial, CSIC-UPC. +// Authors: Joan Solà Ortega (jsola@iri.upc.edu) +// All rights reserved. +// +// This file is part of WOLF +// WOLF is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. +// +//--------LICENSE_END-------- +#include <vector> +#include "Eigen/Dense" +#include "pinocchio/algorithm/crba.hpp" + + +using namespace Eigen; + + +/** + * \brief Compute a 3D acceleration from 6D spatial acceleration + * + * \param ddr spatial acc linear part + * \param w spatial acc rotational part + * \param dr spatial velocity linear part +**/ +Vector3d computeAccFromSpatial(const Vector3d& ddr, const Vector3d& w, const Vector3d& dr); + + +/** +* \brief Compute the relative contact points from foot center of a Talos foot. +* +* Order is clockwise, starting from bottom left (looking at a forward pointing foot from above). +* Expressed in local foot coordinates. +**/ +std::vector<Vector3d> contacts_from_footrect_center(); + + +/** +* \brief Compute the wrench at the end effector center expressed in world coordinates. + +* Each contact force (at a foot for instance) is represented in MAPI as a set of +* 4 forces at the corners of the contact polygone (foot -> rectangle). These forces, +* as the other quantities, are expressed in world coordinates. From this 4 3D forces, +* we can compute the 6D wrench at the center of the origin point of the contacts vectors. + +* \param contacts std vector of 3D contact forces +* \param cforces 12D corner forces vector ordered as [fx1, fy1, fz1, fx2, fy2... fz4], same order as contacts +* \param wRl rotation matrix, orientation from world frame to foot frame +**/ +Matrix<double, 6, 1> contact_force_to_wrench(const std::vector<Vector3d>& contacts, + const Matrix<double, 12, 1>& cf12); + + +/** +* \brief Compute the centroidal angular inertia used to compute the angular momentum. + +* \param model: pinocchio robot model used +* \param data: pinocchio robot data used +* \param q_static: configuration of the robot with free flyer pose at origin (local base frame = world frame) +* \param b_p_bc: measure of the CoM position relative to the base +**/ +Matrix3d compute_Iw(pinocchio::Model& model, + pinocchio::Data& data, + VectorXd& q_static, + Vector3d& b_p_bc); diff --git a/demos/solo_imu_kine_mocap.cpp b/demos/solo_imu_kine_mocap.cpp index 68c837894f73325895b977784ebba7e5a669801b..82d2df1c42da66a66e6894fe49e037b4a04259cd 100644 --- a/demos/solo_imu_kine_mocap.cpp +++ b/demos/solo_imu_kine_mocap.cpp @@ -94,35 +94,35 @@ int main (int argc, char **argv) { // retrieve parameters from yaml file YAML::Node config = YAML::LoadFile("/home/mfourmy/Documents/Phd_LAAS/wolf/bodydynamics/demos/solo_real_estimation.yaml"); double dt = config["dt"].as<double>(); - double min_t = config["min_t"].as<double>(); + // double min_t = config["min_t"].as<double>(); double max_t = config["max_t"].as<double>(); - double solve_every_sec = config["solve_every_sec"].as<double>(); + // double solve_every_sec = config["solve_every_sec"].as<double>(); bool solve_end = config["solve_end"].as<bool>(); // robot std::string robot_urdf = config["robot_urdf"].as<std::string>(); - int dimc = config["dimc"].as<int>(); - int nb_feet = config["nb_feet"].as<int>(); + // int dimc = config["dimc"].as<int>(); + // int nb_feet = config["nb_feet"].as<int>(); // Ceres setup int max_num_iterations = config["max_num_iterations"].as<int>(); bool compute_cov = config["compute_cov"].as<bool>(); // estimator sensor noises - double std_pbc_est = config["std_pbc_est"].as<double>(); - double std_vbc_est = config["std_vbc_est"].as<double>(); - double std_f_est = config["std_f_est"].as<double>(); - double std_tau_est = config["std_tau_est"].as<double>(); + // double std_pbc_est = config["std_pbc_est"].as<double>(); + // double std_vbc_est = config["std_vbc_est"].as<double>(); + // double std_f_est = config["std_f_est"].as<double>(); + // double std_tau_est = config["std_tau_est"].as<double>(); double std_foot_nomove = config["std_foot_nomove"].as<double>(); // priors double std_prior_p = config["std_prior_p"].as<double>(); double std_prior_o = config["std_prior_o"].as<double>(); double std_prior_v = config["std_prior_v"].as<double>(); - double std_abs_bias_pbc = config["std_abs_bias_pbc"].as<double>(); + // double std_abs_bias_pbc = config["std_abs_bias_pbc"].as<double>(); double std_abs_bias_acc = config["std_abs_bias_acc"].as<double>(); double std_abs_bias_gyro = config["std_abs_bias_gyro"].as<double>(); - double std_bp_drift = config["std_bp_drift"].as<double>(); + // double std_bp_drift = config["std_bp_drift"].as<double>(); std::vector<double> bias_imu_prior_vec = config["bias_imu_prior"].as<std::vector<double>>(); Eigen::Map<Vector6d> bias_imu_prior(bias_imu_prior_vec.data()); std::vector<double> i_p_im_vec = config["i_p_im"].as<std::vector<double>>(); @@ -137,7 +137,7 @@ int main (int argc, char **argv) { // contacts std::vector<double> l_p_lg_vec = config["l_p_lg"].as<std::vector<double>>(); Eigen::Map<Vector3d> l_p_lg(l_p_lg_vec.data()); - double fz_thresh = config["fz_thresh"].as<double>(); + // double fz_thresh = config["fz_thresh"].as<double>(); std::vector<double> delta_qa_vec = config["delta_qa"].as<std::vector<double>>(); Eigen::Map<Eigen::Matrix<double,12,1>> delta_qa(delta_qa_vec.data()); @@ -159,7 +159,7 @@ int main (int argc, char **argv) { i_q_m.normalize(); assert(i_q_m.normalized().isApprox(i_q_m)); SE3 i_T_m(i_q_m, i_p_im); - Matrix3d i_R_m = i_T_m.rotation(); + // Matrix3d i_R_m = i_T_m.rotation(); // IMU to MOCAP transform SE3 m_T_i = i_T_m.inverse(); @@ -171,7 +171,7 @@ int main (int argc, char **argv) { m_q_b.normalize(); assert(m_q_b.normalized().isApprox(m_q_b)); SE3 m_T_b(m_q_b, m_p_mb); - Matrix3d m_R_b = m_T_b.rotation(); + // Matrix3d m_R_b = m_T_b.rotation(); // IMU to BASE transform (composition) SE3 i_T_b = i_T_m*m_T_b; @@ -320,8 +320,8 @@ int main (int argc, char **argv) { Quaterniond w_q_i_init = w_q_m_init*m_q_i; VectorComposite x_origin("POV", {w_p_wi_init, w_q_i_init.coeffs(), Vector3d::Zero()}); VectorComposite std_origin("POV", {std_prior_p*Vector3d::Ones(), std_prior_o*Vector3d::Ones(), std_prior_v*Vector3d::Ones()}); - // FrameBasePtr KF1 = problem->setPriorFactor(x_origin, std_origin, t0, 0.0005); // needed to anchor the problem - FrameBasePtr KF1 = problem->setPriorInitialGuess(x_origin, t0, 0.0005); // if mocap used + // FrameBasePtr KF1 = problem->setPriorFactor(x_origin, std_origin, t0); // needed to anchor the problem + FrameBasePtr KF1 = problem->setPriorInitialGuess(x_origin, t0); // if mocap used proc_imu->setOrigin(KF1); @@ -367,7 +367,7 @@ int main (int argc, char **argv) { VectorComposite curr_state = problem->getState(); Vector4d o_qvec_i_curr = curr_state['O']; Quaterniond o_q_i_curr(o_qvec_i_curr); - Vector3d o_v_oi_curr = curr_state['V']; + // Vector3d o_v_oi_curr = curr_state['V']; ////////////// @@ -421,7 +421,6 @@ int main (int argc, char **argv) { // Or else, retrieve from preprocessed dataset Eigen::Map<Matrix<double,12, 1>> l_forces(l_forces_arr+12*i); - Vector3d o_f_tot = Vector3d::Zero(); std::vector<Vector3d> l_f_l_vec; std::vector<Vector3d> o_f_l_vec; std::vector<Vector3d> i_p_il_vec; @@ -507,7 +506,6 @@ int main (int argc, char **argv) { Vector3d Qv_fbk_diag = Qv_fbk.diagonal(); Vector6d Qbi_fbk_diag = Qbi_fbk.diagonal(); Vector6d Qm_fbk_diag; Qm_fbk_diag << Qmp_fbk.diagonal(), Qmo_fbk.diagonal(); - Vector3d Qmo_fbk_diag = Qmo_fbk.diagonal(); Qp_fbk_v.push_back(Qp_fbk_diag); Qo_fbk_v.push_back(Qo_fbk_diag); @@ -659,8 +657,6 @@ int main (int argc, char **argv) { // std::cout << "Factors " << kf->getTimeStamp().get() << std::endl; FactorBasePtrList fac_lst; kf->getFactorList(fac_lst); - Vector9d imu_err = Vector9d::Zero(); - Vector6d pose_err = Vector6d::Zero(); i++; } diff --git a/demos/solo_imu_mocap.cpp b/demos/solo_imu_mocap.cpp index f7ad2d04ed1bfe843a903b768a81d8683090c254..1ffabd4c847bb9f3f0954f5eb70862cc20eedf00 100644 --- a/demos/solo_imu_mocap.cpp +++ b/demos/solo_imu_mocap.cpp @@ -134,7 +134,7 @@ int main (int argc, char **argv) { m_q_b.normalize(); assert(m_q_b.normalized().isApprox(m_q_b)); SE3 m_T_b(m_q_b, m_p_mb); - Matrix3d m_R_b = m_T_b.rotation(); + // Matrix3d m_R_b = m_T_b.rotation(); // IMU to BASE transform (composition) SE3 i_T_b = i_T_m*m_T_b; @@ -273,7 +273,7 @@ int main (int argc, char **argv) { Quaterniond w_q_i_init = w_q_m_init*m_q_i; VectorComposite x_origin("POV", {w_p_wi_init, w_q_i_init.coeffs(), Vector3d::Zero()}); VectorComposite std_origin("POV", {std_prior_p*Vector3d::Ones(), std_prior_o*Vector3d::Ones(), std_prior_v*Vector3d::Ones()}); - // FrameBasePtr KF1 = problem->setPriorFactor(x_origin, std_origin, t0, 0.0005); + // FrameBasePtr KF1 = problem->setPriorFactor(x_origin, std_origin, t0); FrameBasePtr KF1 = problem->setPriorInitialGuess(x_origin, t0); // if mocap used proc_imu->setOrigin(KF1); @@ -397,7 +397,6 @@ int main (int argc, char **argv) { Vector3d Qv_fbk_diag = Qv_fbk.diagonal(); Vector6d Qbi_fbk_diag = Qbi_fbk.diagonal(); Vector6d Qm_fbk_diag; Qm_fbk_diag << Qmp_fbk.diagonal(), Qmo_fbk.diagonal(); - Vector3d Qmo_fbk_diag = Qmo_fbk.diagonal(); Qp_fbk_v.push_back(Qp_fbk_diag); Qo_fbk_v.push_back(Qo_fbk_diag); diff --git a/demos/solo_real_povcdl_estimation.cpp b/demos/solo_real_povcdl_estimation.cpp index 44819e61223a3461f03cfaab16957676991557b9..9953db41444d0d1b1da732f5460c3bd398cd3a63 100644 --- a/demos/solo_real_povcdl_estimation.cpp +++ b/demos/solo_real_povcdl_estimation.cpp @@ -69,6 +69,8 @@ #include "bodydynamics/sensor/sensor_point_feet_nomove.h" #include "bodydynamics/processor/processor_point_feet_nomove.h" +#include "mcapi_utils.h" + using namespace Eigen; using namespace wolf; @@ -85,7 +87,7 @@ int main (int argc, char **argv) { int dimc = config["dimc"].as<int>(); double mass_offset = config["mass_offset"].as<double>(); double dt = config["dt"].as<double>(); - double min_t = config["min_t"].as<double>(); + // double min_t = config["min_t"].as<double>(); double max_t = config["max_t"].as<double>(); double solve_every_sec = config["solve_every_sec"].as<double>(); bool solve_end = config["solve_end"].as<bool>(); @@ -574,8 +576,9 @@ int main (int argc, char **argv) { } } - CapturePointFeetNomovePtr CPF = std::make_shared<CapturePointFeetNomove>(ts, sen_pfnm, kin_incontact); - CPF->process(); + // TODO: ???? kin_incontact is a map to Vector3d in this implementation, should be Vector7d [p, q] + // CapturePointFeetNomovePtr CPF = std::make_shared<CapturePointFeetNomove>(ts, sen_pfnm, kin_incontact); + // CPF->process();