00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036 #include <jsk_topic_tools/rosparam_utils.h>
00037 #include "jsk_footstep_controller/footcoords.h"
00038 #include <std_msgs/String.h>
00039 #include <tf_conversions/tf_eigen.h>
00040 #include <jsk_pcl_ros/pcl_conversion_util.h>
00041 #include <kdl/chainfksolverpos_recursive.hpp>
00042 #include <kdl/chainfksolvervel_recursive.hpp>
00043 #include <tf_conversions/tf_kdl.h>
00044 #include <geometry_msgs/TwistStamped.h>
00045 #include <kdl_conversions/kdl_msg.h>
00046 #include <boost/assign/list_of.hpp>
00047
00048 namespace jsk_footstep_controller
00049 {
00050
00051 Footcoords::Footcoords():
00052 diagnostic_updater_(new diagnostic_updater::Updater)
00053 {
00054 ros::NodeHandle nh, pnh("~");
00055 tf_listener_.reset(new tf::TransformListener());
00056 odom_status_ = UNINITIALIZED;
00057 odom_pose_ = Eigen::Affine3d::Identity();
00058 ground_transform_.setRotation(tf::Quaternion(0, 0, 0, 1));
00059 root_link_pose_.setIdentity();
00060 midcoords_.setRotation(tf::Quaternion(0, 0, 0, 1));
00061 estimated_odom_pose_.setRotation(tf::Quaternion(0, 0, 0, 1));
00062 diagnostic_updater_->setHardwareID("none");
00063 diagnostic_updater_->add("Support Leg Status", this,
00064 &Footcoords::updateLegDiagnostics);
00065
00066
00067 pnh.param("alpha", alpha_, 0.1);
00068 pnh.param("sampling_time_", sampling_time_, 0.2);
00069 pnh.param("output_frame_id", output_frame_id_,
00070 std::string("odom_on_ground"));
00071 pnh.param("zmp_frame_id", zmp_frame_id_,
00072 std::string("zmp"));
00073
00074 pnh.param("parent_frame_id", parent_frame_id_, std::string("odom"));
00075 pnh.param("midcoords_frame_id", midcoords_frame_id_, std::string("ground"));
00076 pnh.param("root_frame_id", root_frame_id_, std::string("BODY"));
00077 pnh.param("body_on_odom_frame", body_on_odom_frame_, std::string("body_on_odom"));
00078 pnh.param("odom_init_frame_id", odom_init_frame_id_, std::string("odom_init"));
00079 pnh.param("invert_odom_init", invert_odom_init_, true);
00080 pnh.param("lfoot_frame_id", lfoot_frame_id_,
00081 std::string("lleg_end_coords"));
00082 pnh.param("rfoot_frame_id", rfoot_frame_id_,
00083 std::string("rleg_end_coords"));
00084 pnh.param("publish_odom_tf", publish_odom_tf_, true);
00085 urdf::Model robot_model;
00086 KDL::Tree tree;
00087 robot_model.initParam("robot_description");
00088 if (!kdl_parser::treeFromUrdfModel(robot_model, tree)) {
00089 ROS_FATAL("Failed to load robot_description");
00090 return;
00091 }
00092
00093 tree.getChain(root_frame_id_, lfoot_frame_id_, lfoot_chain_);
00094 tree.getChain(root_frame_id_, rfoot_frame_id_, rfoot_chain_);
00095 for (size_t i=0; i < lfoot_chain_.getNrOfSegments(); i++){
00096 ROS_INFO_STREAM("kdl_chain(" << i << ") "
00097 << lfoot_chain_.getSegment(i).getJoint().getName().c_str());
00098 }
00099 for (size_t i=0; i < rfoot_chain_.getNrOfSegments(); i++){
00100 ROS_INFO_STREAM("kdl_chain(" << i << ") "
00101 << rfoot_chain_.getSegment(i).getJoint().getName().c_str());
00102 }
00103 pnh.param("lfoot_sensor_frame", lfoot_sensor_frame_, std::string("lleg_end_coords"));
00104 pnh.param("rfoot_sensor_frame", rfoot_sensor_frame_, std::string("rleg_end_coords"));
00105
00106
00107 pnh.param("force_threshold", force_thr_, 200.0);
00108 support_status_ = AIR;
00109 pub_low_level_ = pnh.advertise<jsk_footstep_controller::FootCoordsLowLevelInfo>("low_level_info", 1);
00110 pub_state_ = pnh.advertise<std_msgs::String>("state", 1);
00111 pub_contact_state_ = pnh.advertise<jsk_footstep_controller::GroundContactState>("contact_state", 1);
00112 pub_synchronized_forces_ = pnh.advertise<jsk_footstep_controller::SynchronizedForces>("synchronized_forces", 1);
00113 pub_debug_lfoot_pos_ = pnh.advertise<geometry_msgs::Pose>("debug/lfoot_pose", 1);
00114 pub_debug_rfoot_pos_ = pnh.advertise<geometry_msgs::Pose>("debug/rfoot_pose", 1);
00115 pub_leg_odometory_ = pnh.advertise<geometry_msgs::PoseStamped>("leg_odometry", 1);
00116 pub_twist_ = pnh.advertise<geometry_msgs::TwistStamped>("base_vel", 1);
00117 pub_odom_init_transform_ = pnh.advertise<geometry_msgs::TransformStamped>("odom_init_transform", 1, true);
00118 pub_odom_init_pose_stamped_ = pnh.advertise<geometry_msgs::PoseStamped>("odom_init_pose_stamped", 1, true);
00119 before_on_the_air_ = true;
00120 pnh.param("use_imu", use_imu_, false);
00121 pnh.param("use_imu_yaw", use_imu_yaw_, true);
00122 if (publish_odom_tf_) {
00123 odom_sub_.subscribe(pnh, "/odom", 50);
00124 imu_sub_.subscribe(pnh, "/imu", 50);
00125 odom_imu_sync_ = boost::make_shared<message_filters::Synchronizer<OdomImuSyncPolicy> >(100);
00126 odom_imu_sync_->connectInput(odom_sub_, imu_sub_);
00127 odom_imu_sync_->registerCallback(boost::bind(&Footcoords::odomImuCallback, this, _1, _2));
00128 }
00129 odom_init_pose_ = Eigen::Affine3d::Identity();
00130 odom_init_trigger_sub_ = pnh.subscribe("/odom_init_trigger", 1,
00131 &Footcoords::odomInitTriggerCallback, this);
00132 periodic_update_timer_ = pnh.createTimer(ros::Duration(1.0 / 25),
00133 boost::bind(&Footcoords::periodicTimerCallback, this, _1));
00134 sub_lfoot_force_.subscribe(nh, "lfsensor", 50);
00135 sub_rfoot_force_.subscribe(nh, "rfsensor", 50);
00136 sub_joint_states_.subscribe(nh, "joint_states",50);
00137 sub_zmp_.subscribe(nh, "zmp", 50);
00138 floor_coeffs_sub_ = pnh.subscribe("/floor_coeffs", 1,
00139 &Footcoords::floorCoeffsCallback, this);
00140 floor_coeffs_ = boost::assign::list_of(0)(0)(1)(0);
00141 sync_ = boost::make_shared<message_filters::Synchronizer<SyncPolicy> >(100);
00142 sync_->connectInput(sub_lfoot_force_, sub_rfoot_force_, sub_joint_states_, sub_zmp_);
00143 sync_->registerCallback(boost::bind(&Footcoords::synchronizeForces, this, _1, _2, _3, _4));
00144 synchronized_forces_sub_ = pnh.subscribe("synchronized_forces", 20,
00145 &Footcoords::filter, this);
00146 }
00147
00148 Footcoords::~Footcoords()
00149 {
00150
00151 }
00152
00153 void Footcoords::updateLegDiagnostics(diagnostic_updater::DiagnosticStatusWrapper &stat)
00154 {
00155
00156
00157 if (support_status_ == AIR) {
00158 stat.summary(diagnostic_msgs::DiagnosticStatus::WARN, "On Air");
00159 }
00160 else {
00161 if (support_status_ == LLEG_GROUND) {
00162 stat.summary(diagnostic_msgs::DiagnosticStatus::OK, "Left leg on the ground");
00163 }
00164 else if (support_status_ == RLEG_GROUND) {
00165 stat.summary(diagnostic_msgs::DiagnosticStatus::OK, "Right leg on the ground");
00166 }
00167 else if (support_status_ == BOTH_GROUND) {
00168 stat.summary(diagnostic_msgs::DiagnosticStatus::OK, "Both legs on the ground");
00169 }
00170 }
00171 }
00172
00173 double Footcoords::applyLowPassFilter(double current_val, double prev_val) const
00174 {
00175 return prev_val + alpha_ * (current_val - prev_val);
00176 }
00177
00178 bool Footcoords::allValueLargerThan(TimeStampedVector<ValueStamped::Ptr>& values,
00179 double threshold)
00180 {
00181 for (size_t i = 0; i < values.size(); i++) {
00182 if (values[i]->value < threshold) {
00183 return false;
00184 }
00185 }
00186 return true;
00187 }
00188
00189 bool Footcoords::allValueSmallerThan(TimeStampedVector<ValueStamped::Ptr>& values,
00190 double threshold)
00191 {
00192 for (size_t i = 0; i < values.size(); i++) {
00193 if (values[i]->value > threshold) {
00194 return false;
00195 }
00196 }
00197 return true;
00198 }
00199
00200 bool Footcoords::resolveForceTf(const geometry_msgs::WrenchStamped& lfoot,
00201 const geometry_msgs::WrenchStamped& rfoot,
00202 tf::Vector3& lfoot_force,
00203 tf::Vector3& rfoot_force)
00204 {
00205 try {
00206 if (!waitForSensorFrameTransformation(lfoot.header.stamp, rfoot.header.stamp, lfoot.header.frame_id, rfoot.header.frame_id)) {
00207 ROS_ERROR("[Footcoords::resolveForceTf] failed to lookup transformation for sensor value");
00208 return false;
00209 }
00210 tf::StampedTransform lfoot_transform, rfoot_transform;
00211 tf_listener_->lookupTransform(
00212 lfoot.header.frame_id, lfoot_sensor_frame_, lfoot.header.stamp, lfoot_transform);
00213 tf_listener_->lookupTransform(
00214 rfoot.header.frame_id, rfoot_sensor_frame_, rfoot.header.stamp, rfoot_transform);
00215
00216 lfoot_transform.setOrigin(tf::Vector3(0, 0, 0));
00217 rfoot_transform.setOrigin(tf::Vector3(0, 0, 0));
00218
00219 tf::Vector3 lfoot_local, rfoot_local;
00220 tf::vector3MsgToTF(lfoot.wrench.force, lfoot_local);
00221 tf::vector3MsgToTF(rfoot.wrench.force, rfoot_local);
00222 lfoot_force = lfoot_transform * lfoot_local;
00223 rfoot_force = rfoot_transform * rfoot_local;
00224
00225
00226 return true;
00227 }
00228 catch (tf2::ConnectivityException &e) {
00229 ROS_ERROR("[Footcoords::resolveForceTf] transform error: %s", e.what());
00230 return false;
00231 }
00232 catch (tf2::InvalidArgumentException &e) {
00233 ROS_ERROR("[Footcoords::resolveForceTf] transform error: %s", e.what());
00234 return false;
00235 }
00236 catch (tf2::ExtrapolationException &e) {
00237 ROS_ERROR("[Footcoords::resolveForceTf] transform error: %s", e.what());
00238 return false;
00239 }
00240 catch (tf2::LookupException &e) {
00241 ROS_ERROR("[Footcoords::resolveForceTf] transform error: %s", e.what());
00242 return false;
00243 }
00244 }
00245
00246 void Footcoords::periodicTimerCallback(const ros::TimerEvent& event)
00247 {
00248 boost::mutex::scoped_lock lock(mutex_);
00249 bool success_to_update = computeMidCoords(event.current_real);
00250 if (support_status_ == AIR || support_status_ == BOTH_GROUND) {
00251 publishState("ground");
00252 }
00253 else {
00254 if (support_status_ == LLEG_GROUND) {
00255 publishState("lfoot");
00256 }
00257 else if (support_status_ == RLEG_GROUND) {
00258 publishState("rfoot");
00259 }
00260 }
00261
00262 tf::StampedTransform root_transform;
00263 try {
00264
00265
00266
00267 }
00268 catch (tf2::ConnectivityException &e) {
00269 ROS_ERROR("[Footcoords::resolveForceTf] transform error: %s", e.what());
00270 }
00271 catch (tf2::InvalidArgumentException &e) {
00272 ROS_ERROR("[Footcoords::resolveForceTf] transform error: %s", e.what());
00273 }
00274 catch (tf2::ExtrapolationException &e) {
00275 ROS_ERROR("[Footcoords::resolveForceTf] transform error: %s", e.what());
00276 }
00277 catch (tf2::LookupException &e) {
00278 ROS_ERROR("[Footcoords::resolveForceTf] transform error: %s", e.what());
00279 }
00280
00281
00282
00283
00284
00285
00286
00287
00288
00289 ground_transform_ = midcoords_;
00290 publishTF(event.current_real);
00291 diagnostic_updater_->update();
00292 publishContactState(event.current_real);
00293 }
00294
00295 void Footcoords::synchronizeForces(const geometry_msgs::WrenchStamped::ConstPtr& lfoot,
00296 const geometry_msgs::WrenchStamped::ConstPtr& rfoot,
00297 const sensor_msgs::JointState::ConstPtr& joint_states,
00298 const geometry_msgs::PointStamped::ConstPtr& zmp)
00299 {
00300 jsk_footstep_controller::SynchronizedForces forces;
00301 forces.header = lfoot->header;
00302 forces.lleg_force = *lfoot;
00303 forces.rleg_force = *rfoot;
00304 forces.joint_angles = *joint_states;
00305 forces.zmp = *zmp;
00306 pub_synchronized_forces_.publish(forces);
00307 Eigen::Vector3d zmp_point;
00308 tf::pointMsgToEigen(zmp->point, zmp_point);
00309
00310 if (zmp->point.z < 0) {
00311 geometry_msgs::TransformStamped ros_zmp_coords;
00312 ros_zmp_coords.header = zmp->header;
00313 ros_zmp_coords.child_frame_id = zmp_frame_id_;
00314 Eigen::Affine3d zmp_pose = Eigen::Affine3d::Identity() * Eigen::Translation3d(zmp_point);
00315 tf::transformEigenToMsg(zmp_pose, ros_zmp_coords.transform);
00316 std::vector<geometry_msgs::TransformStamped> tf_transforms;
00317 tf_transforms.push_back(ros_zmp_coords);
00318 {
00319 boost::mutex::scoped_lock lock(mutex_);
00320 tf_broadcaster_.sendTransform(tf_transforms);
00321 }
00322 }
00323 }
00324
00325 void Footcoords::updateChain(std::map<std::string, double>& joint_angles,
00326 KDL::Chain& chain,
00327 tf::Pose& output_pose)
00328 {
00329 KDL::JntArray jnt_pos(chain.getNrOfJoints());
00330 for (int i = 0, j = 0; i < chain.getNrOfSegments(); i++) {
00331
00332
00333
00334
00335 std::string joint_name = chain.getSegment(i).getJoint().getName();
00336 if (joint_angles.find(joint_name) != joint_angles.end()) {
00337 jnt_pos(j++) = joint_angles[joint_name];
00338 }
00339 }
00340 KDL::ChainFkSolverPos_recursive fk_solver(chain);
00341 KDL::Frame pose;
00342 if (fk_solver.JntToCart(jnt_pos, pose) < 0) {
00343 ROS_FATAL("Failed to compute FK");
00344 }
00345 tf::poseKDLToTF(pose, output_pose);
00346 }
00347
00348 void Footcoords::updateRobotModel(std::map<std::string, double>& joint_angles)
00349 {
00350
00351 updateChain(joint_angles, lfoot_chain_, lfoot_pose_);
00352 updateChain(joint_angles, rfoot_chain_, rfoot_pose_);
00353 geometry_msgs::Pose ros_lfoot_pose, ros_rfoot_pose;
00354 tf::poseTFToMsg(lfoot_pose_, ros_lfoot_pose);
00355 tf::poseTFToMsg(rfoot_pose_, ros_rfoot_pose);
00356 pub_debug_lfoot_pos_.publish(ros_lfoot_pose);
00357 pub_debug_rfoot_pos_.publish(ros_rfoot_pose);
00358 }
00359
00360 void Footcoords::computeVelicity(double dt,
00361 std::map<std::string, double>& joint_angles,
00362 KDL::Chain& chain,
00363 geometry_msgs::Twist& output)
00364 {
00365 KDL::ChainFkSolverVel_recursive fk_solver(chain);
00366 KDL::JntArrayVel jnt_pos(chain.getNrOfJoints());
00367 KDL::JntArray q(chain.getNrOfJoints()), qdot(chain.getNrOfJoints());
00368 for (int i = 0, j = 0; i < chain.getNrOfSegments(); i++) {
00369 std::string joint_name = chain.getSegment(i).getJoint().getName();
00370 if (joint_angles.find(joint_name) != joint_angles.end()) {
00371 qdot(j) = (joint_angles[joint_name] - prev_joints_[joint_name]) / dt;
00372 q(j++) = joint_angles[joint_name];
00373 }
00374 }
00375 jnt_pos.q = q;
00376 jnt_pos.qdot = qdot;
00377 KDL::FrameVel vel;
00378 if (fk_solver.JntToCart(jnt_pos, vel) < 0) {
00379 ROS_FATAL("Failed to compute velocity");
00380 }
00381 KDL::Twist twist = vel.GetTwist();
00382 tf::twistKDLToMsg(twist, output);
00383 }
00384
00385 void Footcoords::estimateVelocity(const ros::Time& stamp, std::map<std::string, double>& joint_angles)
00386 {
00387 geometry_msgs::TwistStamped twist_stamped;
00388 if (!prev_joints_.empty()) {
00389 double dt = (stamp - last_time_).toSec();
00390 if (odom_status_ == LLEG_SUPPORT || odom_status_ == INITIALIZING) {
00391 computeVelicity(dt, joint_angles, lfoot_chain_, twist_stamped.twist);
00392 }
00393 else if (odom_status_ == RLEG_SUPPORT) {
00394 computeVelicity(dt, joint_angles, rfoot_chain_, twist_stamped.twist);
00395 }
00396 twist_stamped.header.stamp = stamp;
00397 twist_stamped.header.frame_id = root_frame_id_;
00398 pub_twist_.publish(twist_stamped);
00399 }
00400 }
00401
00402 void Footcoords::filter(const jsk_footstep_controller::SynchronizedForces::ConstPtr& msg)
00403 {
00404 boost::mutex::scoped_lock lock(mutex_);
00405 geometry_msgs::WrenchStamped lfoot = msg->lleg_force;
00406 geometry_msgs::WrenchStamped rfoot = msg->rleg_force;
00407 zmp_ = Eigen::Vector3f(msg->zmp.point.x, msg->zmp.point.y, msg->zmp.point.z);
00408 sensor_msgs::JointState joint_angles = msg->joint_angles;
00409 std::map<std::string, double> angles;
00410 for (size_t i = 0; i < joint_angles.name.size(); i++) {
00411 angles[joint_angles.name[i]] = joint_angles.position[i];
00412 }
00413
00414 updateRobotModel(angles);
00415
00416
00417 tf::Vector3 lfoot_force_vector, rfoot_force_vector;
00418 if (!resolveForceTf(lfoot, rfoot, lfoot_force_vector, rfoot_force_vector)) {
00419 ROS_ERROR("[Footcoords::filter] failed to resolve tf of force sensor");
00420 return;
00421 }
00422
00423 double lfoot_force = applyLowPassFilter(lfoot_force_vector[2], prev_lforce_);
00424 double rfoot_force = applyLowPassFilter(rfoot_force_vector[2], prev_rforce_);
00425
00426
00427 FootCoordsLowLevelInfo info;
00428 info.header = lfoot.header;
00429 info.raw_lleg_force = lfoot_force_vector[2];
00430 info.raw_rleg_force = rfoot_force_vector[2];
00431 info.filtered_lleg_force = lfoot_force;
00432 info.filtered_rleg_force = rfoot_force;
00433 info.threshold = force_thr_;
00434 pub_low_level_.publish(info);
00435 prev_lforce_ = lfoot_force;
00436 prev_rforce_ = rfoot_force;
00437
00438 if (lfoot_force >= force_thr_ && rfoot_force >= force_thr_) {
00439 support_status_ = BOTH_GROUND;
00440 }
00441 else if (lfoot_force < force_thr_ && rfoot_force < force_thr_) {
00442 support_status_ = AIR;
00443 }
00444 else if (lfoot_force >= force_thr_) {
00445
00446 support_status_ = LLEG_GROUND;
00447 }
00448 else if (rfoot_force >= force_thr_) {
00449
00450 support_status_ = RLEG_GROUND;
00451 }
00452 estimateOdometry();
00453 estimateVelocity(msg->header.stamp, angles);
00454 geometry_msgs::PoseStamped leg_odometory;
00455 leg_odometory.header.stamp = msg->header.stamp;
00456 leg_odometory.header.frame_id = root_frame_id_;
00457 tf::poseTFToMsg(estimated_odom_pose_, leg_odometory.pose);
00458 pub_leg_odometory_.publish(leg_odometory);
00459
00460 std::vector<geometry_msgs::TransformStamped> tf_transforms;
00461 geometry_msgs::TransformStamped odom_transform;
00462 tf::transformTFToMsg(estimated_odom_pose_, odom_transform.transform);
00463 odom_transform.header = leg_odometory.header;
00464 odom_transform.child_frame_id = "leg_odom";
00465 tf_transforms.push_back(odom_transform);
00466 tf_broadcaster_.sendTransform(tf_transforms);
00467 prev_joints_ = angles;
00468 last_time_ = msg->header.stamp;
00469 }
00470
00471 void Footcoords::estimateOdometry()
00472 {
00473
00474 estimateOdometryZMPSupportLeg();
00475 }
00476
00477 void Footcoords::estimateOdometryNaive()
00478 {
00479 if (odom_status_ == UNINITIALIZED && support_status_ == BOTH_GROUND) {
00480 ROS_INFO("changed to INITIALIZING");
00481 odom_status_ = INITIALIZING;
00482 }
00483 if (odom_status_ == INITIALIZING && support_status_ == BOTH_GROUND) {
00484 ROS_INFO_THROTTLE(1.0, "INITIALIZING");
00485
00486 tf::Quaternion midcoords_rot = lfoot_pose_.getRotation().slerp(rfoot_pose_.getRotation(), 0.5);
00487 tf::Vector3 midcoords_pos = lfoot_pose_.getOrigin().lerp(rfoot_pose_.getOrigin(), 0.5);
00488 tf::Pose midcoords;
00489 midcoords.setOrigin(midcoords_pos);
00490 midcoords.setRotation(midcoords_rot);
00491 lfoot_to_origin_pose_ = lfoot_pose_.inverse() * midcoords;
00492 rfoot_to_origin_pose_ = rfoot_pose_.inverse() * midcoords;
00493 estimated_odom_pose_ = midcoords;
00494 }
00495 if (odom_status_ == INITIALIZING && support_status_ ==RLEG_GROUND) {
00496 ROS_INFO_THROTTLE(1.0, "detect RLEG support phase");
00497 odom_status_ = RLEG_SUPPORT;
00498 estimated_odom_pose_ = rfoot_pose_ * rfoot_to_origin_pose_;
00499 }
00500 else if (odom_status_ == INITIALIZING && support_status_ == LLEG_GROUND) {
00501 ROS_INFO_THROTTLE(1.0, "detect LLEG support phase");
00502 odom_status_ = LLEG_SUPPORT;
00503 estimated_odom_pose_ = lfoot_pose_ * lfoot_to_origin_pose_;
00504 }
00505 else if (odom_status_ == RLEG_SUPPORT && support_status_ == RLEG_GROUND) {
00506 ROS_INFO_THROTTLE(1.0, "keep RLEG support phase");
00507 estimated_odom_pose_ = rfoot_pose_ * rfoot_to_origin_pose_;
00508 }
00509 else if (odom_status_ == RLEG_SUPPORT && support_status_ == BOTH_GROUND) {
00510 ROS_INFO_THROTTLE(1.0, "dual leg support phase but use RLEG");
00511 estimated_odom_pose_ = rfoot_pose_ * rfoot_to_origin_pose_;
00512 lfoot_to_origin_pose_ = lfoot_pose_.inverse() * rfoot_pose_ * rfoot_to_origin_pose_;
00513 }
00514 else if (odom_status_ == RLEG_SUPPORT && support_status_ == LLEG_GROUND) {
00515 ROS_INFO_THROTTLE(1.0, "detect LLEG support phase");
00516 odom_status_ = LLEG_SUPPORT;
00517 estimated_odom_pose_ = lfoot_pose_ * lfoot_to_origin_pose_;
00518 }
00519 else if (odom_status_ == LLEG_SUPPORT && support_status_ == LLEG_GROUND) {
00520 ROS_INFO_THROTTLE(1.0, "keep LLEG support phase");
00521 estimated_odom_pose_ = lfoot_pose_ * lfoot_to_origin_pose_;;
00522 }
00523 else if (odom_status_ == LLEG_SUPPORT && support_status_ == BOTH_GROUND) {
00524 ROS_INFO_THROTTLE(1.0, "dual leg support phase but use LLEG");
00525 estimated_odom_pose_ = lfoot_pose_ * lfoot_to_origin_pose_;;
00526 rfoot_to_origin_pose_ = rfoot_pose_.inverse() * lfoot_pose_ * lfoot_to_origin_pose_;
00527 }
00528 else if (odom_status_ == LLEG_SUPPORT && support_status_ == RLEG_GROUND) {
00529 ROS_INFO_THROTTLE(1.0, "detect RLEG support phase");
00530 odom_status_ = RLEG_SUPPORT;
00531 estimated_odom_pose_ = rfoot_pose_ * rfoot_to_origin_pose_;
00532 }
00533 if (support_status_ == AIR) {
00534 ROS_INFO_THROTTLE(1.0, "resetting");
00535 odom_status_ = UNINITIALIZED;
00536 }
00537 }
00538
00539 void Footcoords::estimateOdometryMainSupportLeg()
00540 {
00541 if (odom_status_ == UNINITIALIZED && support_status_ == BOTH_GROUND) {
00542 ROS_INFO("changed to INITIALIZING");
00543 odom_status_ = INITIALIZING;
00544 }
00545 if (odom_status_ == INITIALIZING && support_status_ == BOTH_GROUND) {
00546 ROS_INFO_THROTTLE(1.0, "INITIALIZING");
00547
00548 tf::Quaternion midcoords_rot = lfoot_pose_.getRotation().slerp(rfoot_pose_.getRotation(), 0.5);
00549 tf::Vector3 midcoords_pos = lfoot_pose_.getOrigin().lerp(rfoot_pose_.getOrigin(), 0.5);
00550 tf::Pose midcoords;
00551 midcoords.setOrigin(midcoords_pos);
00552 midcoords.setRotation(midcoords_rot);
00553 lfoot_to_origin_pose_ = lfoot_pose_.inverse() * midcoords;
00554 rfoot_to_origin_pose_ = rfoot_pose_.inverse() * midcoords;
00555 estimated_odom_pose_ = midcoords;
00556 }
00557 if (odom_status_ == INITIALIZING && support_status_ == RLEG_GROUND) {
00558 ROS_INFO_THROTTLE(1.0, "detect RLEG support phase");
00559 odom_status_ = RLEG_SUPPORT;
00560 estimated_odom_pose_ = rfoot_pose_ * rfoot_to_origin_pose_;
00561 }
00562 else if (odom_status_ == INITIALIZING && support_status_ == LLEG_GROUND) {
00563 ROS_INFO_THROTTLE(1.0, "detect LLEG support phase");
00564 odom_status_ = LLEG_SUPPORT;
00565 estimated_odom_pose_ = lfoot_pose_ * lfoot_to_origin_pose_;
00566 }
00567 else if (odom_status_ == RLEG_SUPPORT && support_status_ ==RLEG_GROUND) {
00568 ROS_INFO_THROTTLE(1.0, "keep RLEG support phase");
00569 estimated_odom_pose_ = rfoot_pose_ * rfoot_to_origin_pose_;
00570 }
00571 else if (odom_status_ == RLEG_SUPPORT && support_status_ == BOTH_GROUND) {
00572 if (prev_lforce_ > prev_rforce_) {
00573
00574 odom_status_ = LLEG_SUPPORT;
00575 ROS_INFO_THROTTLE(1.0, "dual leg support phase, switch to lleg");
00576 estimated_odom_pose_ = lfoot_pose_ * lfoot_to_origin_pose_;
00577 rfoot_to_origin_pose_ = rfoot_pose_.inverse() * lfoot_pose_ * lfoot_to_origin_pose_;
00578 }
00579 else {
00580 ROS_INFO_THROTTLE(1.0, "dual leg support phase but use RLEG");
00581 estimated_odom_pose_ = rfoot_pose_ * rfoot_to_origin_pose_;
00582 lfoot_to_origin_pose_ = lfoot_pose_.inverse() * rfoot_pose_ * rfoot_to_origin_pose_;
00583 }
00584 }
00585 else if (odom_status_ == RLEG_SUPPORT && support_status_ == LLEG_GROUND) {
00586 ROS_INFO_THROTTLE(1.0, "detect LLEG support phase");
00587 odom_status_ = LLEG_SUPPORT;
00588 estimated_odom_pose_ = lfoot_pose_ * lfoot_to_origin_pose_;
00589 }
00590 else if (odom_status_ == LLEG_SUPPORT && support_status_ == LLEG_GROUND) {
00591 ROS_INFO_THROTTLE(1.0, "keep LLEG support phase");
00592 estimated_odom_pose_ = lfoot_pose_ * lfoot_to_origin_pose_;;
00593 }
00594 else if (odom_status_ == LLEG_SUPPORT && support_status_ == BOTH_GROUND) {
00595 if (prev_rforce_ > prev_lforce_) {
00596 odom_status_ = RLEG_SUPPORT;
00597 ROS_INFO_THROTTLE(1.0, "dual leg support phase, switch to rleg");
00598 estimated_odom_pose_ = rfoot_pose_ * rfoot_to_origin_pose_;
00599 lfoot_to_origin_pose_ = lfoot_pose_.inverse() * rfoot_pose_ * rfoot_to_origin_pose_;
00600 }
00601 else {
00602 ROS_INFO_THROTTLE(1.0, "dual leg support phase but use LLEG");
00603 estimated_odom_pose_ = lfoot_pose_ * lfoot_to_origin_pose_;;
00604 rfoot_to_origin_pose_ = rfoot_pose_.inverse() * lfoot_pose_ * lfoot_to_origin_pose_;
00605 }
00606 }
00607 else if (odom_status_ == LLEG_SUPPORT && support_status_ == RLEG_GROUND) {
00608 ROS_INFO_THROTTLE(1.0, "detect RLEG support phase");
00609 odom_status_ = RLEG_SUPPORT;
00610 estimated_odom_pose_ = rfoot_pose_ * rfoot_to_origin_pose_;
00611 }
00612 if (support_status_ == AIR) {
00613 ROS_INFO_THROTTLE(1.0, "resetting");
00614 odom_status_ = UNINITIALIZED;
00615 }
00616 }
00617
00618 void Footcoords::estimateOdometryZMPSupportLeg()
00619 {
00620 if (odom_status_ == UNINITIALIZED && support_status_ == BOTH_GROUND) {
00621 ROS_INFO("changed to INITIALIZING");
00622 odom_status_ = INITIALIZING;
00623 }
00624 if (odom_status_ == INITIALIZING && support_status_ == BOTH_GROUND) {
00625 ROS_INFO_THROTTLE(1.0, "INITIALIZING");
00626
00627 tf::Quaternion midcoords_rot = lfoot_pose_.getRotation().slerp(rfoot_pose_.getRotation(), 0.5);
00628 tf::Vector3 midcoords_pos = lfoot_pose_.getOrigin().lerp(rfoot_pose_.getOrigin(), 0.5);
00629 tf::Pose midcoords;
00630 midcoords.setOrigin(midcoords_pos);
00631 midcoords.setRotation(midcoords_rot);
00632 lfoot_to_origin_pose_ = lfoot_pose_.inverse() * midcoords;
00633 rfoot_to_origin_pose_ = rfoot_pose_.inverse() * midcoords;
00634 estimated_odom_pose_ = midcoords;
00635 }
00636 if (odom_status_ == INITIALIZING && support_status_ == RLEG_GROUND) {
00637 ROS_INFO_THROTTLE(1.0, "detect RLEG support phase");
00638 odom_status_ = RLEG_SUPPORT;
00639 estimated_odom_pose_ = rfoot_pose_ * rfoot_to_origin_pose_;
00640 }
00641 else if (odom_status_ == INITIALIZING && support_status_ == LLEG_GROUND) {
00642 ROS_INFO_THROTTLE(1.0, "detect LLEG support phase");
00643 odom_status_ = LLEG_SUPPORT;
00644 estimated_odom_pose_ = lfoot_pose_ * lfoot_to_origin_pose_;
00645 }
00646 else if (odom_status_ == RLEG_SUPPORT && support_status_ ==RLEG_GROUND) {
00647 ROS_INFO_THROTTLE(1.0, "keep RLEG support phase");
00648 estimated_odom_pose_ = rfoot_pose_ * rfoot_to_origin_pose_;
00649 }
00650 else if (odom_status_ == RLEG_SUPPORT && support_status_ == BOTH_GROUND) {
00651 if (zmp_[1] > 0) {
00652
00653 odom_status_ = LLEG_SUPPORT;
00654 ROS_INFO_THROTTLE(1.0, "dual leg support phase, switch to lleg");
00655 estimated_odom_pose_ = lfoot_pose_ * lfoot_to_origin_pose_;
00656 rfoot_to_origin_pose_ = rfoot_pose_.inverse() * lfoot_pose_ * lfoot_to_origin_pose_;
00657 }
00658 else {
00659 ROS_INFO_THROTTLE(1.0, "dual leg support phase but use RLEG");
00660 estimated_odom_pose_ = rfoot_pose_ * rfoot_to_origin_pose_;
00661 lfoot_to_origin_pose_ = lfoot_pose_.inverse() * rfoot_pose_ * rfoot_to_origin_pose_;
00662 }
00663 }
00664 else if (odom_status_ == RLEG_SUPPORT && support_status_ == LLEG_GROUND) {
00665 ROS_INFO_THROTTLE(1.0, "detect LLEG support phase");
00666 odom_status_ = LLEG_SUPPORT;
00667 estimated_odom_pose_ = lfoot_pose_ * lfoot_to_origin_pose_;
00668 }
00669 else if (odom_status_ == LLEG_SUPPORT && support_status_ == LLEG_GROUND) {
00670 ROS_INFO_THROTTLE(1.0, "keep LLEG support phase");
00671 estimated_odom_pose_ = lfoot_pose_ * lfoot_to_origin_pose_;;
00672 }
00673 else if (odom_status_ == LLEG_SUPPORT && support_status_ == BOTH_GROUND) {
00674 if (zmp_[1] < 0) {
00675 odom_status_ = RLEG_SUPPORT;
00676 ROS_INFO_THROTTLE(1.0, "dual leg support phase, switch to rleg");
00677 estimated_odom_pose_ = rfoot_pose_ * rfoot_to_origin_pose_;
00678 lfoot_to_origin_pose_ = lfoot_pose_.inverse() * rfoot_pose_ * rfoot_to_origin_pose_;
00679 }
00680 else {
00681 ROS_INFO_THROTTLE(1.0, "dual leg support phase but use LLEG");
00682 estimated_odom_pose_ = lfoot_pose_ * lfoot_to_origin_pose_;;
00683 rfoot_to_origin_pose_ = rfoot_pose_.inverse() * lfoot_pose_ * lfoot_to_origin_pose_;
00684 }
00685 }
00686 else if (odom_status_ == LLEG_SUPPORT && support_status_ == RLEG_GROUND) {
00687 ROS_INFO_THROTTLE(1.0, "detect RLEG support phase");
00688 odom_status_ = RLEG_SUPPORT;
00689 estimated_odom_pose_ = rfoot_pose_ * rfoot_to_origin_pose_;
00690 }
00691 if (support_status_ == AIR) {
00692 ROS_INFO_THROTTLE(1.0, "resetting");
00693 odom_status_ = UNINITIALIZED;
00694 }
00695 }
00696
00697
00698
00699 void Footcoords::publishState(const std::string& state)
00700 {
00701 std_msgs::String state_msg;
00702 state_msg.data = state;
00703 pub_state_.publish(state_msg);
00704 }
00705
00706 void Footcoords::publishContactState(const ros::Time& stamp)
00707 {
00708 GroundContactState contact_state;
00709 contact_state.header.stamp = stamp;
00710 if (support_status_ == AIR) {
00711 contact_state.contact_state
00712 = GroundContactState::CONTACT_AIR;
00713 }
00714 else if (support_status_ == LLEG_GROUND) {
00715 contact_state.contact_state
00716 = GroundContactState::CONTACT_LLEG_GROUND;
00717 }
00718 else if (support_status_ == RLEG_GROUND) {
00719 contact_state.contact_state
00720 = GroundContactState::CONTACT_RLEG_GROUND;
00721 }
00722 else if (support_status_ == BOTH_GROUND) {
00723 contact_state.contact_state
00724 = GroundContactState::CONTACT_BOTH_GROUND;
00725 }
00726 try
00727 {
00728 tf::StampedTransform foot_transform;
00729 tf_listener_->lookupTransform(
00730 lfoot_frame_id_, rfoot_frame_id_, stamp, foot_transform);
00731 double roll, pitch, yaw;
00732 foot_transform.getBasis().getRPY(roll, pitch, yaw);
00733 contact_state.error_pitch_angle = std::abs(pitch);
00734 contact_state.error_roll_angle = std::abs(roll);
00735 contact_state.error_yaw_angle = std::abs(yaw);
00736 contact_state.error_z = std::abs(foot_transform.getOrigin().z());
00737 pub_contact_state_.publish(contact_state);
00738 }
00739 catch (tf2::ConnectivityException &e)
00740 {
00741 ROS_ERROR("[Footcoords::publishContactState] transform error: %s", e.what());
00742 }
00743 catch (tf2::InvalidArgumentException &e)
00744 {
00745 ROS_ERROR("[Footcoords::publishContactState] transform error: %s", e.what());
00746 }
00747 catch (tf2::ExtrapolationException &e)
00748 {
00749 ROS_ERROR("[Footcoords::publishContactState] transform error: %s", e.what());
00750 }
00751 catch (tf2::LookupException &e)
00752 {
00753 ROS_ERROR("[Footcoords::publishContactState] transform error: %s", e.what());
00754 }
00755
00756 }
00757
00758 bool Footcoords::computeMidCoordsFromSingleLeg(const ros::Time& stamp,
00759 bool use_left_leg)
00760 {
00761 if (!waitForEndEffectorTransformation(stamp)) {
00762 ROS_ERROR("[Footcoords::computeMidCoordsFromSingleLeg] Failed to lookup endeffector transformation");
00763 return false;
00764 }
00765 else {
00766 try
00767 {
00768 tf::StampedTransform foot_transform;
00769 if (use_left_leg) {
00770 tf_listener_->lookupTransform(
00771 root_frame_id_, lfoot_frame_id_, stamp, foot_transform);
00772 }
00773 else {
00774 tf_listener_->lookupTransform(
00775 root_frame_id_, rfoot_frame_id_, stamp, foot_transform);
00776 }
00777 midcoords_ = foot_transform.inverse();
00778 return true;
00779 }
00780 catch (tf2::ConnectivityException &e)
00781 {
00782 ROS_ERROR("[Footcoords::computeMidCoordsFromSingleLeg] transform error: %s", e.what());
00783 return false;
00784 }
00785 catch (tf2::InvalidArgumentException &e)
00786 {
00787 ROS_ERROR("[Footcoords::computeMidCoordsFromSingleLeg] transform error: %s", e.what());
00788 return false;
00789 }
00790 catch (tf2::ExtrapolationException &e)
00791 {
00792 ROS_ERROR("[Footcoords::computeMidCoordsFromSingleLeg] transform error: %s", e.what());
00793 }
00794 catch (tf2::LookupException &e)
00795 {
00796 ROS_ERROR("[Footcoords::computeMidCoordsFromSingleLeg] transform error: %s", e.what());
00797 }
00798
00799
00800 }
00801 }
00802
00803 bool Footcoords::computeMidCoords(const ros::Time& stamp)
00804 {
00805 if (!waitForEndEffectorTransformation(stamp)) {
00806 ROS_ERROR("[Footcoords::computeMidCoords] Failed to lookup endeffector transformation");
00807 return false;
00808 }
00809 else {
00810 try
00811 {
00812 tf::StampedTransform lfoot_transform;
00813 tf_listener_->lookupTransform(
00814 root_frame_id_, lfoot_frame_id_, stamp, lfoot_transform);
00815 tf::StampedTransform rfoot_transform;
00816 tf_listener_->lookupTransform(
00817 root_frame_id_, rfoot_frame_id_, stamp, rfoot_transform);
00818 tf::Quaternion lfoot_rot = lfoot_transform.getRotation();
00819 tf::Quaternion rfoot_rot = rfoot_transform.getRotation();
00820 tf::Quaternion mid_rot = lfoot_rot.slerp(rfoot_rot, 0.5);
00821 tf::Vector3 lfoot_pos = lfoot_transform.getOrigin();
00822 tf::Vector3 rfoot_pos = rfoot_transform.getOrigin();
00823 tf::Vector3 mid_pos = lfoot_pos.lerp(rfoot_pos, 0.5);
00824 midcoords_.setOrigin(mid_pos);
00825 midcoords_.setRotation(mid_rot);
00826 midcoords_ = midcoords_;
00827 return true;
00828 }
00829 catch (tf2::ConnectivityException &e)
00830 {
00831 ROS_ERROR("[Footcoords::computeMidCoords] transform error: %s", e.what());
00832 return false;
00833 }
00834 catch (tf2::InvalidArgumentException &e)
00835 {
00836 ROS_ERROR("[Footcoords::computeMidCoords] transform error: %s", e.what());
00837 return false;
00838 }
00839 catch (tf2::ExtrapolationException &e)
00840 {
00841 ROS_ERROR("[Footcoords::computeMidCoords] transform error: %s", e.what());
00842 }
00843 catch (tf2::LookupException &e)
00844 {
00845 ROS_ERROR("[Footcoords::computeMidCoords] transform error: %s", e.what());
00846 }
00847
00848 }
00849 }
00850
00851 bool Footcoords::waitForSensorFrameTransformation(const ros::Time& lstamp,
00852 const ros::Time& rstamp,
00853 const std::string& lsensor_frame,
00854 const std::string& rsensor_frame)
00855 {
00856
00857 if (!tf_listener_->waitForTransform(
00858 lsensor_frame, lfoot_sensor_frame_, lstamp, ros::Duration(1.0))) {
00859 ROS_ERROR("[Footcoords::waitForSensorFrameTransformation] failed to lookup transform between %s and %s",
00860 lsensor_frame.c_str(),
00861 lfoot_sensor_frame_.c_str());
00862 return false;
00863 }
00864 if (!tf_listener_->waitForTransform(
00865 rsensor_frame, rfoot_sensor_frame_, rstamp, ros::Duration(1.0))) {
00866 ROS_ERROR("[Footcoords::waitForSensorFrameTransformation] failed to lookup transform between %s and %s",
00867 rsensor_frame.c_str(),
00868 rfoot_sensor_frame_.c_str());
00869 return false;
00870 }
00871 return true;
00872 }
00873
00874 bool Footcoords::waitForEndEffectorTransformation(const ros::Time& stamp)
00875 {
00876
00877 if (!tf_listener_->waitForTransform(
00878 root_frame_id_, lfoot_frame_id_, stamp, ros::Duration(1.0))) {
00879 ROS_ERROR("[Footcoords::waitForEndEffectorTrasnformation] failed to lookup transform between %s and %s",
00880 root_frame_id_.c_str(),
00881 lfoot_frame_id_.c_str());
00882 return false;
00883 }
00884
00885 else if (!tf_listener_->waitForTransform(
00886 root_frame_id_, rfoot_frame_id_, stamp, ros::Duration(1.0))) {
00887 ROS_ERROR("[Footcoords::waitForEndEffectorTrasnformation]failed to lookup transform between %s and %s",
00888 root_frame_id_.c_str(),
00889 rfoot_frame_id_.c_str());
00890 return false;
00891 }
00892
00893 else if (!tf_listener_->waitForTransform(
00894 lfoot_frame_id_, rfoot_frame_id_, stamp, ros::Duration(1.0))) {
00895 ROS_ERROR("[Footcoords::waitForEndEffectorTrasnformation]failed to lookup transform between %s and %s",
00896 lfoot_frame_id_.c_str(),
00897 rfoot_frame_id_.c_str());
00898 return false;
00899 }
00900 return true;
00901 }
00902
00903 bool Footcoords::updateGroundTF()
00904 {
00905
00906
00907
00908
00909
00910 if (false && support_status_ == BOTH_GROUND) {
00911
00912 ground_transform_ = midcoords_ * locked_midcoords_to_odom_on_ground_;
00913 }
00914 else {
00915 Eigen::Affine3d odom_to_midcoords;
00916 tf::transformTFToEigen(midcoords_, odom_to_midcoords);
00917 Eigen::Affine3d midcoords_to_odom = odom_to_midcoords.inverse();
00918 Eigen::Affine3d midcoords_to_odom_on_ground = midcoords_to_odom;
00919 midcoords_to_odom_on_ground.translation().z() = 0.0;
00920 Eigen::Vector3d zaxis;
00921 zaxis[0] = midcoords_to_odom_on_ground(0, 2);
00922 zaxis[1] = midcoords_to_odom_on_ground(1, 2);
00923 zaxis[2] = midcoords_to_odom_on_ground(2, 2);
00924 Eigen::Quaterniond rot;
00925 rot.setFromTwoVectors(zaxis, Eigen::Vector3d(0, 0, 1));
00926 midcoords_to_odom_on_ground.rotate(rot);
00927 Eigen::Affine3d odom_to_odom_on_ground
00928 = odom_to_midcoords * midcoords_to_odom_on_ground;
00929 tf::transformEigenToTF(odom_to_odom_on_ground,
00930 ground_transform_);
00931 }
00932 }
00933
00934 void Footcoords::getRollPitch(const Eigen::Affine3d& pose, float& roll, float& pitch)
00935 {
00936 Eigen::Affine3f posef;
00937 jsk_pcl_ros::convertEigenAffine3(pose, posef);
00938 float yaw;
00939 pcl::getEulerAngles(posef, roll, pitch, yaw);
00940 }
00941
00942 float Footcoords::getYaw(const Eigen::Affine3d& pose)
00943 {
00944 Eigen::Affine3f posef;
00945 jsk_pcl_ros::convertEigenAffine3(pose, posef);
00946 float roll, pitch, yaw;
00947 pcl::getEulerAngles(posef, roll, pitch, yaw);
00948 return yaw;
00949 }
00950
00951 void Footcoords::publishTF(const ros::Time& stamp)
00952 {
00953
00954 geometry_msgs::TransformStamped ros_midcoords,
00955 ros_ground_coords, ros_odom_to_body_coords,
00956 ros_body_on_odom_coords, ros_odom_init_coords;
00957
00958
00959
00960
00961 std_msgs::Header header;
00962 header.stamp = stamp;
00963 header.frame_id = parent_frame_id_;
00964 ros_midcoords.header.stamp = stamp;
00965 ros_midcoords.header.frame_id = root_frame_id_;
00966 ros_midcoords.child_frame_id = midcoords_frame_id_;
00967 ros_ground_coords.header.stamp = stamp;
00968 ros_ground_coords.header.frame_id = parent_frame_id_;
00969 ros_ground_coords.child_frame_id = output_frame_id_;
00970 ros_odom_to_body_coords.header.stamp = stamp;
00971 ros_odom_to_body_coords.header.frame_id = parent_frame_id_;
00972 ros_odom_to_body_coords.child_frame_id = root_frame_id_;
00973 ros_body_on_odom_coords.header.stamp = stamp;
00974 ros_body_on_odom_coords.header.frame_id = root_frame_id_;
00975 ros_body_on_odom_coords.child_frame_id = body_on_odom_frame_;
00976 ros_odom_init_coords.header.stamp = stamp;
00977 if (invert_odom_init_) {
00978 ros_odom_init_coords.header.frame_id = odom_init_frame_id_;
00979 ros_odom_init_coords.child_frame_id = parent_frame_id_;
00980 } else {
00981 ros_odom_init_coords.header.frame_id = parent_frame_id_;
00982 ros_odom_init_coords.child_frame_id = odom_init_frame_id_;
00983 }
00984 Eigen::Affine3d identity = Eigen::Affine3d::Identity();
00985 float roll, pitch;
00986 getRollPitch(odom_pose_, roll, pitch);
00987 Eigen::Affine3d body_on_odom_pose = (Eigen::Translation3d(0,
00988 0,
00989 odom_pose_.translation()[2]) *
00990 Eigen::AngleAxisd(roll, Eigen::Vector3d::UnitX()) *
00991 Eigen::AngleAxisd(pitch, Eigen::Vector3d::UnitY()));
00992 midcoords_.getRotation().normalize();
00993 Eigen::Affine3d odom_init_pose = (Eigen::Translation3d(odom_init_pose_.translation()[0],
00994 odom_init_pose_.translation()[1],
00995 odom_init_pose_.translation()[2]) *
00996 Eigen::AngleAxisd(getYaw(odom_init_pose_), Eigen::Vector3d::UnitZ()));
00997
00998 tf::transformTFToMsg(midcoords_, ros_midcoords.transform);
00999 tf::transformEigenToMsg(identity, ros_ground_coords.transform);
01000 tf::transformEigenToMsg(body_on_odom_pose.inverse(), ros_body_on_odom_coords.transform);
01001 tf::transformEigenToMsg(odom_pose_, ros_odom_to_body_coords.transform);
01002 if (invert_odom_init_) {
01003 tf::transformEigenToMsg(odom_init_pose.inverse(), ros_odom_init_coords.transform);
01004 } else {
01005 tf::transformEigenToMsg(odom_init_pose, ros_odom_init_coords.transform);
01006 }
01007 std::vector<geometry_msgs::TransformStamped> tf_transforms;
01008 tf_transforms.push_back(ros_midcoords);
01009 tf_transforms.push_back(ros_ground_coords);
01010 if (publish_odom_tf_) {
01011 tf_transforms.push_back(ros_odom_to_body_coords);
01012 }
01013 tf_transforms.push_back(ros_body_on_odom_coords);
01014 tf_transforms.push_back(ros_odom_init_coords);
01015 tf_broadcaster_.sendTransform(tf_transforms);
01016 }
01017
01018 void Footcoords::odomInitTriggerCallback(const std_msgs::Empty& trigger)
01019 {
01020 boost::mutex::scoped_lock lock(mutex_);
01021
01022 jsk_recognition_utils::Plane floor_plane(floor_coeffs_);
01023 floor_plane.project(odom_pose_, odom_init_pose_);
01024 odom_init_pose_ = (Eigen::Translation3d(odom_init_pose_.translation()) *
01025 Eigen::AngleAxisd(getYaw(odom_pose_), Eigen::Vector3d::UnitZ()));
01026
01027
01028
01029 geometry_msgs::TransformStamped ros_odom_init_coords;
01030 geometry_msgs::PoseStamped ros_odom_init_pose_stamped;
01031 Eigen::Affine3d odom_init_pose = (Eigen::Translation3d(odom_init_pose_.translation()[0],
01032 odom_init_pose_.translation()[1],
01033 odom_init_pose_.translation()[2]) *
01034 Eigen::AngleAxisd(getYaw(odom_init_pose_), Eigen::Vector3d::UnitZ()));
01035 ros_odom_init_coords.header.stamp = ros::Time::now();
01036 ros_odom_init_coords.header.frame_id = parent_frame_id_;
01037 ros_odom_init_coords.child_frame_id = odom_init_frame_id_;
01038 tf::transformEigenToMsg(odom_init_pose, ros_odom_init_coords.transform);
01039 pub_odom_init_transform_.publish(ros_odom_init_coords);
01040 ros_odom_init_pose_stamped.header = ros_odom_init_coords.header;
01041 ros_odom_init_pose_stamped.pose.position.x = ros_odom_init_coords.transform.translation.x;
01042 ros_odom_init_pose_stamped.pose.position.y = ros_odom_init_coords.transform.translation.y;
01043 ros_odom_init_pose_stamped.pose.position.z = ros_odom_init_coords.transform.translation.z;
01044 ros_odom_init_pose_stamped.pose.orientation = ros_odom_init_coords.transform.rotation;
01045 pub_odom_init_pose_stamped_.publish(ros_odom_init_pose_stamped);
01046 }
01047
01048 void Footcoords::floorCoeffsCallback(const pcl_msgs::ModelCoefficients& coeffs)
01049 {
01050 boost::mutex::scoped_lock lock(mutex_);
01051 tf::StampedTransform floor_transform;
01052
01053
01054 if (coeffs.header.frame_id != parent_frame_id_) {
01055 try {
01056 tf_listener_->lookupTransform(odom_init_frame_id_, coeffs.header.frame_id, coeffs.header.stamp, floor_transform);
01057 } catch (tf2::ConnectivityException &e) {
01058 ROS_ERROR("[Footcoords::floorCoeffsCallback] transform error: %s", e.what());
01059 return;
01060 } catch (tf2::InvalidArgumentException &e) {
01061 ROS_ERROR("[Footcoords::floorCoeffsCallback] transform error: %s", e.what());
01062 return;
01063 } catch (tf2::ExtrapolationException &e) {
01064 ROS_ERROR("[Footcoords::floorCoeffsCallback] transform error: %s", e.what());
01065 return;
01066 } catch (tf2::LookupException &e) {
01067 ROS_ERROR("[Footcoords::floorCoeffsCallback] transform error: %s", e.what());
01068 return;
01069 }
01070 Eigen::Affine3d floor_transform_eigen;
01071 jsk_recognition_utils::Plane tmp_plane(coeffs.values);
01072 tf::transformTFToEigen(floor_transform, floor_transform_eigen);
01073 tmp_plane.transform(floor_transform_eigen);
01074 floor_coeffs_ = tmp_plane.toCoefficients();
01075 } else {
01076 floor_coeffs_ = coeffs.values;
01077 }
01078 }
01079
01080 void Footcoords::odomImuCallback(const nav_msgs::Odometry::ConstPtr& odom_msg,
01081 const sensor_msgs::Imu::ConstPtr& imu_msg)
01082 {
01083 boost::mutex::scoped_lock lock(mutex_);
01084 if (use_imu_) {
01085 Eigen::Affine3d odom_pose;
01086 tf::poseMsgToEigen(odom_msg->pose.pose, odom_pose);
01087 Eigen::Quaterniond imu_orientation;
01088 tf::quaternionMsgToEigen(imu_msg->orientation, imu_orientation);
01089 if (use_imu_yaw_) {
01090 odom_pose_ = Eigen::Translation3d(odom_pose.translation()) * imu_orientation;
01091 }
01092 else {
01093 float roll, pitch;
01094 getRollPitch(Eigen::Affine3d::Identity() * imu_orientation, roll, pitch);
01095 odom_pose_ = (Eigen::Translation3d(odom_pose.translation()) *
01096 Eigen::AngleAxisd(roll, Eigen::Vector3d::UnitX()) *
01097 Eigen::AngleAxisd(pitch, Eigen::Vector3d::UnitY()));
01098 }
01099 }
01100 else {
01101 tf::poseMsgToEigen(odom_msg->pose.pose, odom_pose_);
01102 }
01103 }
01104 }
01105
01106 int main(int argc, char** argv)
01107 {
01108 ros::init(argc, argv, "footcoords");
01109 jsk_footstep_controller::Footcoords c;
01110 ros::spin();
01111 }