6 #include <dynamic-graph/factory.h> 
    8 #include <sot/core/debug.hh> 
    9 #include <sot/core/stop-watch.hh> 
   13 #include "pinocchio/algorithm/frames.hpp" 
   18 namespace dg = ::dynamicgraph;
 
   20 using namespace dg::command;
 
   22 using namespace pinocchio;
 
   23 using boost::math::normal;  
 
   25 void se3Interp(
const pinocchio::SE3& s1, 
const pinocchio::SE3& s2,
 
   26                const double alpha, pinocchio::SE3& s12) {
 
   27   const Eigen::Vector3d t_(s1.translation() * alpha +
 
   28                            s2.translation() * (1 - alpha));
 
   30   const Eigen::Vector3d w(pinocchio::log3(s1.rotation()) * alpha +
 
   31                           pinocchio::log3(s2.rotation()) * (1 - alpha));
 
   33   s12 = pinocchio::SE3(pinocchio::exp3(w), t_);
 
   35 void rpyToMatrix(
double roll, 
double pitch, 
double yaw, Eigen::Matrix3d& R) {
 
   36   Eigen::AngleAxisd rollAngle(roll, Eigen::Vector3d::UnitX());
 
   37   Eigen::AngleAxisd pitchAngle(pitch, Eigen::Vector3d::UnitY());
 
   38   Eigen::AngleAxisd yawAngle(yaw, Eigen::Vector3d::UnitZ());
 
   39   Eigen::Quaternion<double> q = yawAngle * pitchAngle * rollAngle;
 
   43 void rpyToMatrix(
const Eigen::Vector3d& rpy, Eigen::Matrix3d& R) {
 
   47 void matrixToRpy(
const Eigen::Matrix3d& M, Eigen::Vector3d& rpy) {
 
   48   double m = sqrt(M(2, 1) * M(2, 1) + M(2, 2) * M(2, 2));
 
   49   rpy(1) = atan2(-M(2, 0), m);
 
   50   if (fabs(fabs(rpy(1)) - 0.5 * M_PI) < 0.001) {
 
   52     rpy(2) = -atan2(M(0, 1), M(1, 1));
 
   54     rpy(2) = atan2(M(1, 0), M(0, 0));  
 
   55     rpy(0) = atan2(M(2, 1), M(2, 2));  
 
   60                      Eigen::Vector4d& q12) {
 
   61   q12(0) = q2(0) * q1(0) - q2(1) * q1(1) - q2(2) * q1(2) - q2(3) * q1(3);
 
   62   q12(1) = q2(0) * q1(1) + q2(1) * q1(0) - q2(2) * q1(3) + q2(3) * q1(2);
 
   63   q12(2) = q2(0) * q1(2) + q2(1) * q1(3) + q2(2) * q1(0) - q2(3) * q1(1);
 
   64   q12(3) = q2(0) * q1(3) - q2(1) * q1(2) + q2(2) * q1(1) + q2(3) * q1(0);
 
   68                                const Eigen::Vector4d& quat,
 
   69                                Eigen::Vector3d& rotatedPoint) {
 
   70   const Eigen::Vector4d p4(0.0, point(0), point(1), point(2));
 
   71   const Eigen::Vector4d quat_conj(quat(0), -quat(1), -quat(2), -quat(3));
 
   72   Eigen::Vector4d q_tmp1, q_tmp2;
 
   75   rotatedPoint(0) = q_tmp2(1);
 
   76   rotatedPoint(1) = q_tmp2(2);
 
   77   rotatedPoint(2) = q_tmp2(3);
 
   80 #define PROFILE_BASE_POSITION_ESTIMATION "base-est position estimation" 
   81 #define PROFILE_BASE_VELOCITY_ESTIMATION "base-est velocity estimation" 
   82 #define PROFILE_BASE_KINEMATICS_COMPUTATION "base-est kinematics computation" 
   84 #define INPUT_SIGNALS                                                         \ 
   85   m_joint_positionsSIN << m_joint_velocitiesSIN << m_imu_quaternionSIN        \ 
   86                        << m_forceLLEGSIN << m_forceRLEGSIN << m_dforceLLEGSIN \ 
   87                        << m_dforceRLEGSIN << m_w_lf_inSIN << m_w_rf_inSIN     \ 
   88                        << m_K_fb_feet_posesSIN << m_lf_ref_xyzquatSIN         \ 
   89                        << m_rf_ref_xyzquatSIN << m_accelerometerSIN           \ 
   91 #define OUTPUT_SIGNALS                                                         \ 
   92   m_qSOUT << m_vSOUT << m_v_kinSOUT << m_v_flexSOUT << m_v_imuSOUT             \ 
   93           << m_v_gyrSOUT << m_lf_xyzquatSOUT << m_rf_xyzquatSOUT << m_a_acSOUT \ 
   94           << m_v_acSOUT << m_q_lfSOUT << m_q_rfSOUT << m_q_imuSOUT             \ 
   95           << m_w_lfSOUT << m_w_rfSOUT << m_w_lf_filteredSOUT                   \ 
   96           << m_w_rf_filteredSOUT 
  110       CONSTRUCT_SIGNAL_IN(joint_positions, 
dynamicgraph::Vector),
 
  111       CONSTRUCT_SIGNAL_IN(joint_velocities, 
dynamicgraph::Vector),
 
  112       CONSTRUCT_SIGNAL_IN(imu_quaternion, 
dynamicgraph::Vector),
 
  117       CONSTRUCT_SIGNAL_IN(w_lf_in, double),
 
  118       CONSTRUCT_SIGNAL_IN(w_rf_in, double),
 
  119       CONSTRUCT_SIGNAL_IN(K_fb_feet_poses, double),
 
  120       CONSTRUCT_SIGNAL_IN(lf_ref_xyzquat, 
dynamicgraph::Vector),
 
  121       CONSTRUCT_SIGNAL_IN(rf_ref_xyzquat, 
dynamicgraph::Vector),
 
  122       CONSTRUCT_SIGNAL_IN(accelerometer, 
dynamicgraph::Vector),
 
  124       CONSTRUCT_SIGNAL_INNER(kinematics_computations, 
dynamicgraph::Vector,
 
  125                              m_joint_positionsSIN << m_joint_velocitiesSIN),
 
  127                            m_kinematics_computationsSINNER
 
  128                                << m_joint_positionsSIN << m_imu_quaternionSIN
 
  129                                << m_forceLLEGSIN << m_forceRLEGSIN
 
  130                                << m_w_lf_inSIN << m_w_rf_inSIN
 
  131                                << m_K_fb_feet_posesSIN << m_w_lf_filteredSOUT
 
  132                                << m_w_rf_filteredSOUT << m_lf_ref_xyzquatSIN
 
  133                                << m_rf_ref_xyzquatSIN),
 
  135                            m_kinematics_computationsSINNER
 
  136                                << m_accelerometerSIN << m_gyroscopeSIN
 
  137                                << m_qSOUT << m_dforceLLEGSIN
 
  139       CONSTRUCT_SIGNAL_OUT(v_kin, 
dynamicgraph::Vector, m_vSOUT),
 
  140       CONSTRUCT_SIGNAL_OUT(v_flex, 
dynamicgraph::Vector, m_vSOUT),
 
  141       CONSTRUCT_SIGNAL_OUT(v_imu, 
dynamicgraph::Vector, m_vSOUT),
 
  142       CONSTRUCT_SIGNAL_OUT(v_gyr, 
dynamicgraph::Vector, m_vSOUT),
 
  143       CONSTRUCT_SIGNAL_OUT(lf_xyzquat, 
dynamicgraph::Vector, m_qSOUT),
 
  144       CONSTRUCT_SIGNAL_OUT(rf_xyzquat, 
dynamicgraph::Vector, m_qSOUT),
 
  145       CONSTRUCT_SIGNAL_OUT(a_ac, 
dynamicgraph::Vector, m_vSOUT),
 
  146       CONSTRUCT_SIGNAL_OUT(v_ac, 
dynamicgraph::Vector, m_vSOUT),
 
  147       CONSTRUCT_SIGNAL_OUT(q_lf, 
dynamicgraph::Vector, m_qSOUT),
 
  148       CONSTRUCT_SIGNAL_OUT(q_rf, 
dynamicgraph::Vector, m_qSOUT),
 
  150                            m_qSOUT << m_imu_quaternionSIN),
 
  151       CONSTRUCT_SIGNAL_OUT(w_lf, double, m_forceLLEGSIN),
 
  152       CONSTRUCT_SIGNAL_OUT(w_rf, double, m_forceRLEGSIN),
 
  153       CONSTRUCT_SIGNAL_OUT(w_lf_filtered, double, m_w_lfSOUT),
 
  154       CONSTRUCT_SIGNAL_OUT(w_rf_filtered, double, m_w_rfSOUT),
 
  155       m_initSucceeded(false),
 
  156       m_reset_foot_pos(true),
 
  158       m_zmp_std_dev_rf(1.0),
 
  159       m_zmp_std_dev_lf(1.0),
 
  160       m_fz_std_dev_rf(1.0),
 
  161       m_fz_std_dev_lf(1.0),
 
  162       m_zmp_margin_lf(0.0),
 
  163       m_zmp_margin_rf(0.0) {
 
  166   m_K_rf << 4034, 23770, 239018, 707, 502, 936;
 
  167   m_K_lf << 4034, 23770, 239018, 707, 502, 936;
 
  175                  docCommandVoid2(
"Initialize the entity.", 
"time step (double)",
 
  176                                  "URDF file path (string)")));
 
  178   addCommand(
"set_fz_stable_windows_size",
 
  182                      "Set the windows size used to detect that feet is stable",
 
  184   addCommand(
"set_alpha_w_filter",
 
  187                  docCommandVoid1(
"Set the filter parameter to filter weights",
 
  192                        docCommandVoid1(
"Set the filter parameter for removing " 
  193                                        "DC from accelerometer data",
 
  195   addCommand(
"set_alpha_DC_vel",
 
  198                  docCommandVoid1(
"Set the filter parameter for removing DC " 
  199                                  "from velocity integrated from acceleration",
 
  202       "reset_foot_positions",
 
  204                        docCommandVoid0(
"Reset the position of the feet.")));
 
  209           docDirectGetter(
"Weight of imu-based orientation in sensor fusion",
 
  211   addCommand(
"set_imu_weight",
 
  215                      "Set the weight of imu-based orientation in sensor fusion",
 
  218       "set_zmp_std_dev_right_foot",
 
  220                        docCommandVoid1(
"Set the standard deviation of the ZMP " 
  221                                        "measurement errors for the right foot",
 
  224       "set_zmp_std_dev_left_foot",
 
  226                        docCommandVoid1(
"Set the standard deviation of the ZMP " 
  227                                        "measurement errors for the left foot",
 
  229   addCommand(
"set_normal_force_std_dev_right_foot",
 
  232                  docCommandVoid1(
"Set the standard deviation of the normal " 
  233                                  "force measurement errors for the right foot",
 
  235   addCommand(
"set_normal_force_std_dev_left_foot",
 
  238                  docCommandVoid1(
"Set the standard deviation of the normal " 
  239                                  "force measurement errors for the left foot",
 
  241   addCommand(
"set_stiffness_right_foot",
 
  245                      "Set the 6d stiffness of the spring at the right foot",
 
  248       "set_stiffness_left_foot",
 
  251           docCommandVoid1(
"Set the 6d stiffness of the spring at the left foot",
 
  254       "set_right_foot_sizes",
 
  258               "Set the size of the right foot (pos x, neg x, pos y, neg y)",
 
  261       "set_left_foot_sizes",
 
  265               "Set the size of the left foot (pos x, neg x, pos y, neg y)",
 
  268       "set_zmp_margin_right_foot",
 
  271           docCommandVoid1(
"Set the ZMP margin for the right foot", 
"double")));
 
  273       "set_zmp_margin_left_foot",
 
  276           docCommandVoid1(
"Set the ZMP margin for the left foot", 
"double")));
 
  278       "set_normal_force_margin_right_foot",
 
  281           docCommandVoid1(
"Set the normal force margin for the right foot",
 
  284       "set_normal_force_margin_left_foot",
 
  287           docCommandVoid1(
"Set the normal force margin for the left foot",
 
  295     std::string localName(robotRef);
 
  296     if (isNameInRobotUtil(localName)) {
 
  298       std::cerr << 
"m_robot_util:" << 
m_robot_util << std::endl;
 
  301           "You should have an entity controller manager initialized before",
 
  306     pinocchio::urdf::buildModel(
m_robot_util->m_urdf_filename,
 
  307                                 pinocchio::JointModelFreeFlyer(), 
m_model);
 
  331         SE3(Matrix3::Identity(),
 
  332             -Eigen::Map<const Vector3>(
 
  333                 &
m_robot_util->m_foot_util.m_Right_Foot_Force_Sensor_XYZ(0)));
 
  349   } 
catch (
const std::exception& e) {
 
  350     std::cout << e.what();
 
  351     SEND_MSG(
"Init failed: Could load URDF :" + 
m_robot_util->m_urdf_filename,
 
  361     return SEND_MSG(
"windows_size should be a positive integer",
 
  367   if (a < 0.0 || a > 1.0)
 
  368     return SEND_MSG(
"alpha should be in [0..1]", MSG_TYPE_ERROR);
 
  373   if (a < 0.0 || a > 1.0)
 
  374     return SEND_MSG(
"alpha should be in [0..1]", MSG_TYPE_ERROR);
 
  379   if (a < 0.0 || a > 1.0)
 
  380     return SEND_MSG(
"alpha should be in [0..1]", MSG_TYPE_ERROR);
 
  388     return SEND_MSG(
"Imu weight must be nonnegative", MSG_TYPE_ERROR);
 
  395         "Stiffness vector should have size 6, not " + toString(k.size()),
 
  403         "Stiffness vector should have size 6, not " + toString(k.size()),
 
  410     return SEND_MSG(
"Standard deviation must be a positive number",
 
  417     return SEND_MSG(
"Standard deviation must be a positive number",
 
  424     return SEND_MSG(
"Standard deviation must be a positive number",
 
  431     return SEND_MSG(
"Standard deviation must be a positive number",
 
  439         "Foot size vector should have size 4, not " + toString(s.size()),
 
  447         "Foot size vector should have size 4, not " + toString(s.size()),
 
  469   pinocchio::Force f(w);
 
  471   if (f.linear()[2] == 0.0) 
return;
 
  472   zmp[0] = -f.angular()[1] / f.linear()[2];
 
  473   zmp[1] = f.angular()[0] / f.linear()[2];
 
  477                                          const Vector4& foot_sizes,
 
  478                                          double std_dev, 
double margin) {
 
  479   double fs0 = foot_sizes[0] - margin;
 
  480   double fs1 = foot_sizes[1] + margin;
 
  481   double fs2 = foot_sizes[2] - margin;
 
  482   double fs3 = foot_sizes[3] + margin;
 
  484   if (zmp[0] > fs0 || zmp[0] < fs1 || zmp[1] > fs2 || zmp[1] < fs3) 
return 0;
 
  486   double cdx = ((cdf(
m_normal, (fs0 - zmp[0]) / std_dev) -
 
  487                  cdf(
m_normal, (fs1 - zmp[0]) / std_dev)) -
 
  490   double cdy = ((cdf(
m_normal, (fs2 - zmp[1]) / std_dev) -
 
  491                  cdf(
m_normal, (fs3 - zmp[1]) / std_dev)) -
 
  499   if (fz < margin) 
return 0.0;
 
  500   return (cdf(
m_normal, (fz - margin) / std_dev) - 0.5) * 2.0;
 
  504                                               const Vector6& ftrf) {
 
  506   SE3 
dummy, dummy1, lfMff, rfMff;
 
  514                         lfMff, 
dummy, dummy1);
 
  517   const Vector3& ankle_2_sole_xyz =
 
  519   const SE3 groundMfoot(Matrix3::Identity(), -1.0 * ankle_2_sole_xyz);
 
  520   lfMff = groundMfoot * lfMff;
 
  521   rfMff = groundMfoot * rfMff;
 
  524   const Vector3 w(0.5 * (pinocchio::log3(lfMff.rotation()) +
 
  525                          pinocchio::log3(rfMff.rotation())));
 
  526   SE3 oMff = SE3(pinocchio::exp3(w),
 
  527                  0.5 * (lfMff.translation() + rfMff.translation()));
 
  529   oMff.translation()(0) += 9.562e-03;
 
  531   m_oMlfs = oMff * lfMff.inverse() * groundMfoot;
 
  532   m_oMrfs = oMff * rfMff.inverse() * groundMfoot;
 
  535   Eigen::Quaternion<double> quat_lf(
m_oMlfs.rotation());
 
  542   Eigen::Quaternion<double> quat_rf(
m_oMrfs.rotation());
 
  552   sendMsg(
"Reference pos of left foot:\n" + toString(
m_oMlfs), MSG_TYPE_INFO);
 
  553   sendMsg(
"Reference pos of right foot:\n" + toString(
m_oMrfs), MSG_TYPE_INFO);
 
  567                                           const SE3& oMfs, 
const int foot_id,
 
  568                                           SE3& oMff, SE3& oMfa, SE3& fsMff) {
 
  570   xyz << -ft[0] / K(0), -ft[1] / K(1), -ft[2] / K(2);
 
  572   rpyToMatrix(-ft[3] / K(3), -ft[4] / K(4), -ft[5] / K(5), R);
 
  573   const SE3 fsMfa(R, xyz);                          
 
  575   const SE3 faMff(
m_data->oMf[foot_id].inverse());  
 
  580   fsMff = fsMfa * faMff;  
 
  588   if (!m_initSucceeded) {
 
  589     SEND_WARNING_STREAM_MSG(
 
  590         "Cannot compute signal kinematics_computations before initialization!");
 
  594   const Eigen::VectorXd& qj = m_joint_positionsSIN(iter);  
 
  595   const Eigen::VectorXd& dq = m_joint_velocitiesSIN(iter);
 
  597              static_cast<Eigen::VectorXd::Index
>(m_robot_util->m_nbJoints) &&
 
  598          "Unexpected size of signal joint_positions");
 
  600              static_cast<Eigen::VectorXd::Index
>(m_robot_util->m_nbJoints) &&
 
  601          "Unexpected size of signal joint_velocities");
 
  604   m_robot_util->joints_sot_to_urdf(qj, m_q_pin.tail(m_robot_util->m_nbJoints));
 
  605   m_robot_util->joints_sot_to_urdf(dq, m_v_pin.tail(m_robot_util->m_nbJoints));
 
  610   m_q_pin.head<6>().setZero();
 
  612   m_v_pin.head<6>().setZero();
 
  613   pinocchio::forwardKinematics(m_model, *m_data, m_q_pin, m_v_pin);
 
  614   pinocchio::framesForwardKinematics(m_model, *m_data);
 
  622   if (!m_initSucceeded) {
 
  623     SEND_WARNING_STREAM_MSG(
"Cannot compute signal q before initialization!");
 
  627       static_cast<Eigen::VectorXd::Index
>(m_robot_util->m_nbJoints + 6))
 
  628     s.resize(m_robot_util->m_nbJoints + 6);
 
  630   const Eigen::VectorXd& qj = m_joint_positionsSIN(iter);  
 
  631   const Eigen::Vector4d& quatIMU_vec = m_imu_quaternionSIN(iter);
 
  632   const Vector6& ftrf = m_forceRLEGSIN(iter);
 
  633   const Vector6& ftlf = m_forceLLEGSIN(iter);
 
  638   if (m_w_lf_inSIN.isPlugged())
 
  639     wL = m_w_lf_inSIN(iter);
 
  641     wL = m_w_lf_filteredSOUT(iter);
 
  642     if (m_left_foot_is_stable == 
false) wL = 0.0;
 
  644   if (m_w_rf_inSIN.isPlugged())
 
  645     wR = m_w_rf_inSIN(iter);
 
  647     wR = m_w_rf_filteredSOUT(iter);
 
  648     if (m_right_foot_is_stable == 
false) wR = 0.0;
 
  652              static_cast<Eigen::VectorXd::Index
>(m_robot_util->m_nbJoints) &&
 
  653          "Unexpected size of signal joint_positions");
 
  657   if (wR == 0.0 && wL == 0.0) {
 
  658     SEND_WARNING_STREAM_MSG(
 
  659         "The robot is flying!" +
 
  660         (
"- forceRLEG: " + toString(ftrf.transpose())) +
 
  661         "- forceLLEG: " + toString(ftlf.transpose()) +
 
  662         "- m_right_foot_is_stable: " + toString(m_right_foot_is_stable) +
 
  663         "- m_left_foot_is_stable: " + toString(m_left_foot_is_stable));
 
  668   m_kinematics_computationsSINNER(iter);
 
  670   if (m_reset_foot_pos) reset_foot_positions_impl(ftlf, ftrf);
 
  674     SE3 oMlfa, oMrfa, lfsMff, rfsMff;
 
  675     kinematics_estimation(ftrf, m_K_rf, m_oMrfs,
 
  676                           static_cast<int>(m_right_foot_id), m_oMff_rf, oMrfa,
 
  678     kinematics_estimation(ftlf, m_K_lf, m_oMlfs,
 
  679                           static_cast<int>(m_left_foot_id), m_oMff_lf, oMlfa,
 
  684         m_data->oMf[m_IMU_body_id]);  
 
  686     const SE3 chestMff(ffMchest.inverse());  
 
  689     Vector3 rpy_chest, rpy_chest_lf, rpy_chest_rf,
 
  693     matrixToRpy((m_oMff_lf * ffMchest).rotation(), rpy_chest_lf);
 
  694     matrixToRpy((m_oMff_rf * ffMchest).rotation(), rpy_chest_rf);
 
  695     Eigen::Quaternion<double> quatIMU(quatIMU_vec[0], quatIMU_vec[1],
 
  696                                       quatIMU_vec[2], quatIMU_vec[3]);
 
  697     matrixToRpy(quatIMU.toRotationMatrix(), rpy_chest_imu);
 
  700     double wSum = wL + wR + m_w_imu;
 
  701     rpy_chest(0) = (rpy_chest_lf[0] * wL + rpy_chest_rf[0] * wR +
 
  702                     rpy_chest_imu[0] * m_w_imu) /
 
  704     rpy_chest(1) = (rpy_chest_lf[1] * wL + rpy_chest_rf[1] * wR +
 
  705                     rpy_chest_imu[1] * m_w_imu) /
 
  707     rpy_chest(2) = (rpy_chest_lf[2] * wL + rpy_chest_rf[2] * wR) / (wL + wR);
 
  710     m_oRff = m_oRchest * chestMff.rotation();
 
  716         m_oRff * m_data->oMf[m_left_foot_id].translation();
 
  718         m_oRff * m_data->oMf[m_right_foot_id].translation();
 
  720     m_q_pin.head<3>() = ((oMlfa.translation() - pos_lf_ff) * wL +
 
  721                          (oMrfa.translation() - pos_rf_ff) * wR) /
 
  724     m_q_sot.tail(m_robot_util->m_nbJoints) = qj;
 
  725     base_se3_to_sot(m_q_pin.head<3>(), m_oRff, m_q_sot.head<6>());
 
  730     const SE3 oMff_est(m_oRff, m_q_pin.head<3>());
 
  733     if (m_K_fb_feet_posesSIN.isPlugged()) {
 
  734       const double K_fb = m_K_fb_feet_posesSIN(iter);
 
  735       if (K_fb > 0.0 && m_w_imu > 0.0) {
 
  736         assert(m_w_imu > 0.0 &&
 
  737                "Update of the feet 6d poses should not be done if wIMU = 0.0");
 
  739                "Feedback gain on foot correction should be less than 1.0 " 
  740                "(K_fb_feet_poses>1.0)");
 
  742         const SE3 oMlfs_est(oMff_est * (lfsMff.inverse()));
 
  743         const SE3 oMrfs_est(oMff_est * (rfsMff.inverse()));
 
  745         SE3 leftDrift = m_oMlfs.inverse() * oMlfs_est;
 
  746         SE3 rightDrift = m_oMrfs.inverse() * oMrfs_est;
 
  750         SE3 rightDrift_delta;
 
  751         se3Interp(leftDrift, SE3::Identity(), K_fb * wR, leftDrift_delta);
 
  752         se3Interp(rightDrift, SE3::Identity(), K_fb * wL, rightDrift_delta);
 
  755         if (m_right_foot_is_stable == 
false) rightDrift_delta = rightDrift;
 
  756         if (m_left_foot_is_stable == 
false) leftDrift_delta = leftDrift;
 
  757         if (m_right_foot_is_stable == 
false && m_left_foot_is_stable == 
false) {
 
  759           rightDrift_delta = SE3::Identity();
 
  760           leftDrift_delta = SE3::Identity();
 
  762         m_oMlfs = m_oMlfs * leftDrift_delta;
 
  763         m_oMrfs = m_oMrfs * rightDrift_delta;
 
  765         SE3 oMlfs_ref, oMrfs_ref;
 
  766         if (m_lf_ref_xyzquatSIN.isPlugged() and
 
  767             m_rf_ref_xyzquatSIN.isPlugged()) {
 
  769           const Vector7& lf_ref_xyzquat_vec = m_lf_ref_xyzquatSIN(iter);
 
  770           const Vector7& rf_ref_xyzquat_vec = m_rf_ref_xyzquatSIN(iter);
 
  771           const Eigen::Quaterniond ql(
 
  772               m_lf_ref_xyzquatSIN(iter)(3), m_lf_ref_xyzquatSIN(iter)(4),
 
  773               m_lf_ref_xyzquatSIN(iter)(5), m_lf_ref_xyzquatSIN(iter)(6));
 
  774           const Eigen::Quaterniond qr(
 
  775               m_rf_ref_xyzquatSIN(iter)(3), m_rf_ref_xyzquatSIN(iter)(4),
 
  776               m_rf_ref_xyzquatSIN(iter)(5), m_rf_ref_xyzquatSIN(iter)(6));
 
  777           oMlfs_ref = SE3(ql.toRotationMatrix(), lf_ref_xyzquat_vec.head<3>());
 
  778           oMrfs_ref = SE3(qr.toRotationMatrix(), rf_ref_xyzquat_vec.head<3>());
 
  780           oMlfs_ref = m_oMlfs_default_ref;
 
  781           oMrfs_ref = m_oMrfs_default_ref;
 
  785         const Vector3 translation_feet_drift =
 
  786             0.5 * ((oMlfs_ref.translation() - m_oMlfs.translation()) +
 
  787                    (oMrfs_ref.translation() - m_oMrfs.translation()));
 
  789         const Vector3 V_ref = oMrfs_ref.translation() - oMlfs_ref.translation();
 
  790         const Vector3 V_est = m_oMrfs.translation() - m_oMlfs.translation();
 
  793         const double yaw_drift =
 
  794             (atan2(V_ref(1), V_ref(0)) - atan2(V_est(1), V_est(0)));
 
  797         const Vector3 rpy_feet_drift(0., 0., yaw_drift);
 
  798         Matrix3 rotation_feet_drift;
 
  800         const SE3 drift_to_ref(rotation_feet_drift, translation_feet_drift);
 
  801         m_oMlfs = m_oMlfs * drift_to_ref;
 
  802         m_oMrfs = m_oMrfs * drift_to_ref;
 
  807     m_oMlfs_xyzquat.head<3>() = m_oMlfs.translation();
 
  808     Eigen::Quaternion<double> quat_lf(m_oMlfs.rotation());
 
  809     m_oMlfs_xyzquat(3) = quat_lf.w();
 
  810     m_oMlfs_xyzquat(4) = quat_lf.x();
 
  811     m_oMlfs_xyzquat(5) = quat_lf.y();
 
  812     m_oMlfs_xyzquat(6) = quat_lf.z();
 
  814     m_oMrfs_xyzquat.head<3>() = m_oMrfs.translation();
 
  815     Eigen::Quaternion<double> quat_rf(m_oMrfs.rotation());
 
  816     m_oMrfs_xyzquat(3) = quat_rf.w();
 
  817     m_oMrfs_xyzquat(4) = quat_rf.x();
 
  818     m_oMrfs_xyzquat(5) = quat_rf.y();
 
  819     m_oMrfs_xyzquat(6) = quat_rf.z();
 
  826   if (!m_initSucceeded) {
 
  827     SEND_WARNING_STREAM_MSG(
 
  828         "Cannot compute signal lf_xyzquat before initialization! iter" +
 
  832   if (s.size() != 7) s.resize(7);
 
  838   if (!m_initSucceeded) {
 
  839     SEND_WARNING_STREAM_MSG(
 
  840         "Cannot compute signal rf_xyzquat before initialization! iter" +
 
  844   if (s.size() != 7) s.resize(7);
 
  850   if (!m_initSucceeded) {
 
  851     SEND_WARNING_STREAM_MSG(
 
  852         "Cannot compute signal q_lf before initialization!");
 
  856       static_cast<Eigen::VectorXd::Index
>(m_robot_util->m_nbJoints + 6))
 
  857     s.resize(m_robot_util->m_nbJoints + 6);
 
  859   const Eigen::VectorXd& q = m_qSOUT(iter);
 
  860   s.tail(m_robot_util->m_nbJoints) = q.tail(m_robot_util->m_nbJoints);
 
  861   base_se3_to_sot(m_oMff_lf.translation(), m_oMff_lf.rotation(), s.head<6>());
 
  867   if (!m_initSucceeded) {
 
  868     SEND_WARNING_STREAM_MSG(
 
  869         "Cannot compute signal q_rf before initialization!");
 
  873       static_cast<Eigen::VectorXd::Index
>(m_robot_util->m_nbJoints + 6))
 
  874     s.resize(m_robot_util->m_nbJoints + 6);
 
  876   const Eigen::VectorXd& q = m_qSOUT(iter);
 
  877   s.tail(m_robot_util->m_nbJoints) = q.tail(m_robot_util->m_nbJoints);
 
  878   base_se3_to_sot(m_oMff_rf.translation(), m_oMff_rf.rotation(), s.head<6>());
 
  884   if (!m_initSucceeded) {
 
  885     SEND_WARNING_STREAM_MSG(
 
  886         "Cannot compute signal q_imu before initialization!");
 
  890       static_cast<Eigen::VectorXd::Index
>(m_robot_util->m_nbJoints + 6))
 
  891     s.resize(m_robot_util->m_nbJoints + 6);
 
  893   const Eigen::VectorXd& q = m_qSOUT(iter);
 
  894   s.tail(m_robot_util->m_nbJoints) = q.tail(m_robot_util->m_nbJoints);
 
  896   const Eigen::Vector4d& quatIMU_vec = m_imu_quaternionSIN(iter);
 
  897   Eigen::Quaternion<double> quatIMU(quatIMU_vec);
 
  898   base_se3_to_sot(q.head<3>(), quatIMU.toRotationMatrix(), s.head<6>());
 
  904   if (!m_initSucceeded) {
 
  905     SEND_WARNING_STREAM_MSG(
 
  906         "Cannot compute signal w_lf before initialization!");
 
  910   const Vector6& wrench = m_forceLLEGSIN(iter);
 
  913   compute_zmp(wrench, zmp);
 
  914   double w_zmp = compute_zmp_weight(zmp, m_left_foot_sizes, m_zmp_std_dev_lf,
 
  917       compute_force_weight(wrench(2), m_fz_std_dev_lf, m_fz_margin_lf);
 
  920   if (wrench(2) > m_fz_margin_lf)
 
  921     m_lf_fz_stable_cpt++;
 
  923     m_lf_fz_stable_cpt = 0;
 
  925   if (m_lf_fz_stable_cpt >= m_fz_stable_windows_size) {
 
  926     m_lf_fz_stable_cpt = m_fz_stable_windows_size;
 
  927     m_left_foot_is_stable = 
true;
 
  929     m_left_foot_is_stable = 
false;
 
  936   if (!m_initSucceeded) {
 
  937     SEND_WARNING_STREAM_MSG(
 
  938         "Cannot compute signal w_rf before initialization!");
 
  942   const Vector6& wrench = m_forceRLEGSIN(iter);
 
  945   compute_zmp(wrench, zmp);
 
  946   double w_zmp = compute_zmp_weight(zmp, m_right_foot_sizes, m_zmp_std_dev_rf,
 
  949       compute_force_weight(wrench(2), m_fz_std_dev_rf, m_fz_margin_rf);
 
  952   if (wrench(2) > m_fz_margin_rf)
 
  953     m_rf_fz_stable_cpt++;
 
  955     m_rf_fz_stable_cpt = 0;
 
  957   if (m_rf_fz_stable_cpt >= m_fz_stable_windows_size) {
 
  958     m_rf_fz_stable_cpt = m_fz_stable_windows_size;
 
  959     m_right_foot_is_stable = 
true;
 
  961     m_right_foot_is_stable = 
false;
 
  968   if (!m_initSucceeded) {
 
  969     SEND_WARNING_STREAM_MSG(
 
  970         "Cannot compute signal w_rf_filtered before initialization!");
 
  973   double w_rf = m_w_rfSOUT(iter);
 
  975       m_alpha_w_filter * w_rf +
 
  976       (1 - m_alpha_w_filter) * m_w_rf_filtered;  
 
  982   if (!m_initSucceeded) {
 
  983     SEND_WARNING_STREAM_MSG(
 
  984         "Cannot compute signal w_lf_filtered before initialization!");
 
  987   double w_lf = m_w_lfSOUT(iter);
 
  989       m_alpha_w_filter * w_lf +
 
  990       (1 - m_alpha_w_filter) * m_w_lf_filtered;  
 
  996   if (!m_initSucceeded) {
 
  997     SEND_WARNING_STREAM_MSG(
"Cannot compute signal v before initialization!");
 
 1001       static_cast<Eigen::VectorXd::Index
>(m_robot_util->m_nbJoints + 6))
 
 1002     s.resize(m_robot_util->m_nbJoints + 6);
 
 1004   m_kinematics_computationsSINNER(iter);
 
 1009     const Eigen::VectorXd& dq = m_joint_velocitiesSIN(iter);
 
 1010     const Eigen::Vector3d& acc_imu = m_accelerometerSIN(iter);
 
 1011     const Eigen::Vector3d& gyr_imu = m_gyroscopeSIN(iter);
 
 1012     const Vector6& dftrf = m_dforceRLEGSIN(iter);
 
 1013     const Vector6& dftlf = m_dforceLLEGSIN(iter);
 
 1015                static_cast<Eigen::VectorXd::Index
>(m_robot_util->m_nbJoints) &&
 
 1016            "Unexpected size of signal joint_velocities");
 
 1022     if (m_w_lf_inSIN.isPlugged())
 
 1023       wL = m_w_lf_inSIN(iter);
 
 1025       wL = m_w_lf_filteredSOUT(iter);
 
 1026       if (m_left_foot_is_stable == 
false) wL = 0.0;
 
 1028     if (m_w_rf_inSIN.isPlugged())
 
 1029       wR = m_w_rf_inSIN(iter);
 
 1031       wR = m_w_rf_filteredSOUT(iter);
 
 1032       if (m_right_foot_is_stable == 
false) wR = 0.0;
 
 1036     if (wR == 0.0 && wL == 0.0) {
 
 1042     const Frame& f_lf = m_model.frames[m_left_foot_id];
 
 1043     const Motion v_lf_local = m_data->v[f_lf.parent];
 
 1044     const SE3 ffMlf = m_data->oMi[f_lf.parent];
 
 1046         -ffMlf.act(v_lf_local).toVector();  
 
 1048     v_kin_l.head<3>() = m_oRff * v_kin_l.head<3>();
 
 1049     v_kin_l.segment<3>(3) = m_oRff * v_kin_l.segment<3>(3);
 
 1051     const Frame& f_rf = m_model.frames[m_right_foot_id];
 
 1052     const Motion v_rf_local = m_data->v[f_rf.parent];
 
 1053     const SE3 ffMrf = m_data->oMi[f_rf.parent];
 
 1055         -ffMrf.act(v_rf_local).toVector();  
 
 1057     v_kin_r.head<3>() = m_oRff * v_kin_r.head<3>();
 
 1058     v_kin_r.segment<3>(3) = m_oRff * v_kin_r.segment<3>(3);
 
 1060     m_v_kin.head<6>() = (wR * v_kin_r + wL * v_kin_l) / (wL + wR);
 
 1065     v_flex_l << -dftlf[0] / m_K_lf(0), -dftlf[1] / m_K_lf(1),
 
 1066         -dftlf[2] / m_K_lf(2), -dftlf[3] / m_K_lf(3), -dftlf[4] / m_K_lf(4),
 
 1067         -dftlf[5] / m_K_lf(5);
 
 1068     v_flex_r << -dftrf[0] / m_K_rf(0), -dftrf[1] / m_K_rf(1),
 
 1069         -dftrf[2] / m_K_rf(2), -dftrf[3] / m_K_rf(3), -dftrf[4] / m_K_rf(4),
 
 1070         -dftrf[5] / m_K_rf(5);
 
 1071     const Eigen::Matrix<double, 6, 6> lfAff = ffMlf.inverse().toActionMatrix();
 
 1072     const Eigen::Matrix<double, 6, 6> rfAff = ffMrf.inverse().toActionMatrix();
 
 1073     Eigen::Matrix<double, 12, 6> A;
 
 1075     Eigen::Matrix<double, 12, 1> b;
 
 1076     b << v_flex_l, v_flex_r;
 
 1079     m_v_flex.head<6>() = (A.transpose() * A).ldlt().solve(A.transpose() * b);
 
 1080     m_v_flex.head<3>() = m_oRff * m_v_flex.head<3>();
 
 1085     const Matrix3 ffRimu = (m_data->oMf[m_IMU_body_id]).rotation();
 
 1086     const Matrix3 lfRimu = ffMlf.rotation().transpose() * ffRimu;
 
 1087     const Matrix3 rfRimu = ffMrf.rotation().transpose() * ffRimu;
 
 1089     const SE3 chestMimu(
 
 1090         Matrix3::Identity(),
 
 1094     const SE3 ffMchest(m_data->oMf[m_IMU_body_id]);
 
 1095     const SE3 imuMff = (ffMchest * chestMimu).inverse();
 
 1098     const Frame& f_imu = m_model.frames[m_IMU_body_id];
 
 1100                       (imuMff * ffMlf).act(v_lf_local).angular() -
 
 1101                       m_data->v[f_imu.parent].angular();
 
 1103                       (imuMff * ffMrf).act(v_rf_local).angular() -
 
 1104                       m_data->v[f_imu.parent].angular();
 
 1105     Motion v_gyr_ankle_l(
Vector3(0., 0., 0.), lfRimu * gVo_a_l);
 
 1106     Motion v_gyr_ankle_r(
Vector3(0., 0., 0.), rfRimu * gVo_a_r);
 
 1107     Vector6 v_gyr_l = -ffMlf.inverse().act(v_gyr_ankle_l).toVector();
 
 1108     Vector6 v_gyr_r = -ffMrf.inverse().act(v_gyr_ankle_r).toVector();
 
 1109     m_v_gyr.head<6>() = (wL * v_gyr_l + wR * v_gyr_r) / (wL + wR);
 
 1117     const Vector3 acc_world = m_oRchest * acc_imu;
 
 1127     if (m_isFirstIterFlag) {
 
 1128       m_last_DCacc = acc_world;  
 
 1129       m_isFirstIterFlag = 
false;
 
 1130       sendMsg(
"iter:" + toString(iter) + 
"\n", MSG_TYPE_INFO);
 
 1133         acc_world * (1 - m_alpha_DC_acc) + m_last_DCacc * (m_alpha_DC_acc);
 
 1136     m_last_DCacc = DCacc;
 
 1137     const Vector3 ACacc = acc_world - DCacc;
 
 1140     const Vector3 vel = m_last_vel + ACacc * m_dt;
 
 1145         vel * (1 - m_alpha_DC_vel) + m_last_DCvel * (m_alpha_DC_vel);
 
 1146     m_last_DCvel = DCvel;
 
 1147     const Vector3 ACvel = vel - DCvel;
 
 1152     const Vector3 imuVimu = m_oRchest.transpose() * ACvel;
 
 1154     const Motion imuWimu(imuVimu, gyr_imu);
 
 1160     const SE3 ffMimu = ffMchest * chestMimu;
 
 1161     const Motion v = ffMimu.act(imuWimu);  
 
 1162     m_v_imu.head<6>() = v.toVector();
 
 1163     m_v_imu.head<3>() = m_oRff * m_v_imu.head<3>();
 
 1167     m_v_sot.head<6>() = m_v_gyr.head<6>() + m_v_kin.head<6>();
 
 1171     m_v_sot.tail(m_robot_util->m_nbJoints) = dq;
 
 1172     m_v_kin.tail(m_robot_util->m_nbJoints) = dq;
 
 1173     m_v_flex.tail(m_robot_util->m_nbJoints) = dq;
 
 1174     m_v_gyr.tail(m_robot_util->m_nbJoints) = dq;
 
 1175     m_v_imu.tail(m_robot_util->m_nbJoints) = dq;
 
 1183   if (!m_initSucceeded) {
 
 1184     SEND_WARNING_STREAM_MSG(
 
 1185         "Cannot compute signal v_kin before initialization!");
 
 1194   if (!m_initSucceeded) {
 
 1195     SEND_WARNING_STREAM_MSG(
 
 1196         "Cannot compute signal v_flex before initialization!");
 
 1200   s = m_v_flex + m_v_kin;
 
 1205   if (!m_initSucceeded) {
 
 1206     SEND_WARNING_STREAM_MSG(
 
 1207         "Cannot compute signal v_imu before initialization!");
 
 1216   if (!m_initSucceeded) {
 
 1217     SEND_WARNING_STREAM_MSG(
 
 1218         "Cannot compute signal v_gyr before initialization!");
 
 1227   if (!m_initSucceeded) {
 
 1228     SEND_WARNING_STREAM_MSG(
 
 1229         "Cannot compute signal v_ac before initialization!");
 
 1238   if (!m_initSucceeded) {
 
 1239     SEND_WARNING_STREAM_MSG(
 
 1240         "Cannot compute signal a_ac before initialization!");
 
 1255   os << 
"BaseEstimator " << getName();
 
 1257     getProfiler().report_all(3, os);
 
 1258   } 
catch (ExceptionSignal e) {
 
#define PROFILE_BASE_POSITION_ESTIMATION
 
#define PROFILE_BASE_VELOCITY_ESTIMATION
 
#define PROFILE_BASE_KINEMATICS_COMPUTATION
 
void sendMsg(const std::string &msg, MsgType t=MSG_TYPE_INFO, const char *="", int=0)
 
double m_fz_margin_lf
margin used for computing zmp weight
 
SE3 m_oMlfs
world-to-base transformation obtained through right foot
 
void reset_foot_positions_impl(const Vector6 &ftlf, const Vector6 &ftrf)
 
Eigen::VectorXd m_v_pin
robot configuration according to SoT convention
 
EIGEN_MAKE_ALIGNED_OPERATOR_NEW BaseEstimator(const std::string &name)
 
pinocchio::FrameIndex m_left_foot_id
 
bool m_isFirstIterFlag
Normal distribution.
 
void set_stiffness_left_foot(const dynamicgraph::Vector &k)
 
Vector4 m_right_foot_sizes
 
Eigen::VectorXd m_v_kin
6d stiffness of left foot spring
 
void kinematics_estimation(const Vector6 &ft, const Vector6 &K, const SE3 &oMfs, const int foot_id, SE3 &oMff, SE3 &oMfa, SE3 &fsMff)
 
RobotUtilShrPtr m_robot_util
sampling time step
 
Vector3 m_last_vel
base orientation in the world
 
pinocchio::Data * m_data
Pinocchio robot model.
 
double m_zmp_margin_rf
margin used for computing zmp weight
 
void set_zmp_margin_left_foot(const double &margin)
 
double m_zmp_std_dev_rf
weight of IMU for sensor fusion
 
bool m_left_foot_is_stable
 
double m_dt
true after the command resetFootPositions is called
 
double m_fz_margin_rf
margin used for computing normal force weight
 
void set_stiffness_right_foot(const dynamicgraph::Vector &k)
 
virtual void display(std::ostream &os) const
filtered weight of the estimation coming from the right foot
 
void set_zmp_margin_right_foot(const double &margin)
 
void set_imu_weight(const double &w)
 
void set_normal_force_margin_right_foot(const double &margin)
 
double compute_zmp_weight(const Vector2 &zmp, const Vector4 &foot_sizes, double std_dev, double margin)
 
void set_zmp_std_dev_right_foot(const double &std_dev)
 
void compute_zmp(const Vector6 &w, Vector2 &zmp)
 
void set_alpha_DC_acc(const double &a)
 
void set_zmp_std_dev_left_foot(const double &std_dev)
 
void set_fz_stable_windows_size(const int &ws)
 
void set_normal_force_std_dev_right_foot(const double &std_dev)
 
Vector4 m_left_foot_sizes
 
void init(const double &dt, const std::string &urdfFile)
 
double compute_force_weight(double fz, double std_dev, double margin)
 
void reset_foot_positions()
 
Eigen::VectorXd m_v_sot
robot velocities according to pinocchio convention
 
int m_fz_stable_windows_size
 
Eigen::VectorXd m_q_sot
robot configuration according to pinocchio convention
 
Vector6 m_K_rf
margin used for computing normal force weight
 
bool m_reset_foot_pos
true if the entity has been successfully initialized
 
Vector7 m_oMlfs_xyzquat
transformation from world to right foot sole
 
bool m_right_foot_is_stable
 
void set_alpha_DC_vel(const double &a)
 
SE3 m_oMrfs
transformation from world to left foot sole
 
pinocchio::FrameIndex m_right_foot_id
foot sole to F/T sensor transformation
 
void set_right_foot_sizes(const dynamicgraph::Vector &s)
 
void set_normal_force_std_dev_left_foot(const double &std_dev)
 
void set_alpha_w_filter(const double &a)
 
pinocchio::FrameIndex m_IMU_body_id
 
Vector6 m_K_lf
6d stiffness of right foot spring
 
void set_left_foot_sizes(const dynamicgraph::Vector &s)
 
void set_normal_force_margin_left_foot(const double &margin)
 
DEFINE_SIGNAL_OUT_FUNCTION(u, dynamicgraph::Vector)
 
void pointRotationByQuaternion(const Eigen::Vector3d &point, const Eigen::Vector4d &quat, Eigen::Vector3d &rotatedPoint)
 
void quanternionMult(const Eigen::Vector4d &q1, const Eigen::Vector4d &q2, Eigen::Vector4d &q12)
 
AdmittanceController EntityClassName
 
Eigen::Matrix< double, 3, 1 > Vector3
 
DEFINE_SIGNAL_INNER_FUNCTION(kinematics_computations, dynamicgraph::Vector)
 
Eigen::Matrix< double, 6, 1 > Vector6
 
DYNAMICGRAPH_FACTORY_ENTITY_PLUGIN(AdmittanceController, "AdmittanceController")
 
void se3Interp(const pinocchio::SE3 &s1, const pinocchio::SE3 &s2, const double alpha, pinocchio::SE3 &s12)
 
void rpyToMatrix(double r, double p, double y, Eigen::Matrix3d &R)
 
void matrixToRpy(const Eigen::Matrix3d &M, Eigen::Vector3d &rpy)
 
Eigen::Matrix< double, 2, 1 > Vector2