footstep_marker.cpp
Go to the documentation of this file.
00001 // -*- mode: c++ -*-
00002 /*********************************************************************
00003  * Software License Agreement (BSD License)
00004  *
00005  *  Copyright (c) 2015, JSK Lab
00006  *  All rights reserved.
00007  *
00008  *  Redistribution and use in source and binary forms, with or without
00009  *  modification, are permitted provided that the following conditions
00010  *  are met:
00011  *
00012  *   * Redistributions of source code must retain the above copyright
00013  *     notice, this list of conditions and the following disclaimer.
00014  *   * Redistributions in binary form must reproduce the above
00015  *     copyright notice, this list of conditions and the following
00016  *     disclaimer in the documentation and/o2r other materials provided
00017  *     with the distribution.
00018  *   * Neither the name of the JSK Lab nor the names of its
00019  *     contributors may be used to endorse or promote products derived
00020  *     from this software without specific prior written permission.
00021  *
00022  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00023  *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00024  *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
00025  *  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
00026  *  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
00027  *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
00028  *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00029  *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
00030  *  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00031  *  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
00032  *  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00033  *  POSSIBILITY OF SUCH DAMAGE.
00034  *********************************************************************/
00035 
00036 #define BOOST_PARAMETER_MAX_ARITY 7
00037 #include <iostream>
00038 #include <interactive_markers/tools.h>
00039 #include <jsk_interactive_marker/footstep_marker.h>
00040 #include <jsk_interactive_marker/interactive_marker_utils.h>
00041 #include <jsk_interactive_marker/interactive_marker_helpers.h>
00042 #include <jsk_footstep_msgs/PlanFootstepsGoal.h>
00043 #include <jsk_footstep_msgs/PlanFootstepsResult.h>
00044 #include <std_srvs/Empty.h>
00045 #include <jsk_pcl_ros/CallSnapIt.h>
00046 #include <Eigen/StdVector>
00047 #include <eigen_conversions/eigen_msg.h>
00048 #include <tf_conversions/tf_eigen.h>
00049 #include <jsk_pcl_ros/geo_util.h>
00050 #include <jsk_pcl_ros/pcl_conversion_util.h>
00051 #include <jsk_pcl_ros/tf_listener_singleton.h>
00052 #include <jsk_interactive_marker/SnapFootPrint.h>
00053 #include <jsk_interactive_marker/SnapFootPrintInput.h>
00054 #include <jsk_interactive_marker/SetHeuristic.h>
00055 #include <jsk_topic_tools/log_utils.h>
00056 
00057 FootstepMarker::FootstepMarker():
00058 ac_("footstep_planner", true), ac_exec_("footstep_controller", true),
00059 plan_run_(false), lleg_first_(true) {
00060   // read parameters
00061   tf_listener_.reset(new tf::TransformListener);
00062   ros::NodeHandle pnh("~");
00063   ros::NodeHandle nh;
00064   srv_ = boost::make_shared <dynamic_reconfigure::Server<Config> > (pnh);
00065   typename dynamic_reconfigure::Server<Config>::CallbackType f =
00066     boost::bind (&FootstepMarker::configCallback, this, _1, _2);
00067   srv_->setCallback (f);
00068   pnh.param("foot_size_x", foot_size_x_, 0.247);
00069   pnh.param("foot_size_y", foot_size_y_, 0.135);
00070   pnh.param("foot_size_z", foot_size_z_, 0.01);
00071   pnh.param("lfoot_frame_id", lfoot_frame_id_, std::string("lfsensor"));
00072   pnh.param("rfoot_frame_id", rfoot_frame_id_, std::string("rfsensor"));
00073   pnh.param("show_6dof_control", show_6dof_control_, true);
00074   // pnh.param("use_projection_service", use_projection_service_, false);
00075   // pnh.param("use_projection_topic", use_projection_topic_, false);
00076   pnh.param("always_planning", always_planning_, true);
00077   // if (use_projection_topic_) {
00078     project_footprint_pub_ = pnh.advertise<jsk_interactive_marker::SnapFootPrintInput>("project_footprint", 1);
00079   // }
00080   // read lfoot_offset
00081   readPoseParam(pnh, "lfoot_offset", lleg_offset_);
00082   readPoseParam(pnh, "rfoot_offset", rleg_offset_);
00083   
00084   pnh.param("footstep_margin", footstep_margin_, 0.2);
00085   pnh.param("use_footstep_planner", use_footstep_planner_, true);
00086 
00087   pnh.param("use_footstep_controller", use_footstep_controller_, true);
00088   pnh.param("use_initial_footstep_tf", use_initial_footstep_tf_, true);
00089   pnh.param("wait_snapit_server", wait_snapit_server_, false);
00090   bool nowait = true;
00091   pnh.param("no_wait", nowait, true);
00092   pnh.param("frame_id", marker_frame_id_, std::string("/map"));
00093   footstep_pub_ = nh.advertise<jsk_footstep_msgs::FootstepArray>("footstep_from_marker", 1);
00094   snapit_client_ = nh.serviceClient<jsk_pcl_ros::CallSnapIt>("snapit");
00095   snapped_pose_pub_ = pnh.advertise<geometry_msgs::PoseStamped>("snapped_pose", 1);
00096   current_pose_pub_ = pnh.advertise<geometry_msgs::PoseStamped>("current_pose", 1);
00097   estimate_occlusion_client_ = nh.serviceClient<std_srvs::Empty>("require_estimation");
00098   if (!nowait && wait_snapit_server_) {
00099     snapit_client_.waitForExistence();
00100   }
00101   
00102   if (pnh.getParam("initial_reference_frame", initial_reference_frame_)) {
00103     use_initial_reference_ = true;
00104     JSK_ROS_INFO_STREAM("initial_reference_frame: " << initial_reference_frame_);
00105   }
00106   else {
00107     use_initial_reference_ = false;
00108     JSK_ROS_INFO("initial_reference_frame is not specified ");
00109   }
00110 
00111   server_.reset( new interactive_markers::InteractiveMarkerServer(ros::this_node::getName()));
00112   // menu_handler_.insert( "Snap Legs",
00113   //                       boost::bind(&FootstepMarker::menuFeedbackCB, this, _1));
00114   // menu_handler_.insert( "Reset Legs",
00115   //                       boost::bind(&FootstepMarker::menuFeedbackCB, this, _1));
00116   menu_handler_.insert( "Look Ground",
00117                         boost::bind(&FootstepMarker::menuFeedbackCB, this, _1));
00118   menu_handler_.insert( "Execute the Plan",
00119                         boost::bind(&FootstepMarker::menuFeedbackCB, this, _1));
00120   menu_handler_.insert( "Force to replan",
00121                         boost::bind(&FootstepMarker::menuFeedbackCB, this, _1));
00122   // menu_handler_.insert( "Estimate occlusion",
00123   //                       boost::bind(&FootstepMarker::menuFeedbackCB, this, _1));
00124   menu_handler_.insert( "Cancel Walk",
00125                         boost::bind(&FootstepMarker::menuFeedbackCB, this, _1));
00126   menu_handler_.insert( "Toggle 6dof marker",
00127                         boost::bind(&FootstepMarker::menuFeedbackCB, this, _1));
00128   // menu_handler_.insert( "Resume Footstep",
00129   //                     boost::bind(&FootstepMarker::menuFeedbackCB, this, _1));
00130   menu_handler_.insert("Straight Heuristic",
00131                        boost::bind(&FootstepMarker::menuFeedbackCB, this, _1));
00132   menu_handler_.insert("Stepcost Heuristic**",
00133                        boost::bind(&FootstepMarker::menuFeedbackCB, this, _1));
00134   menu_handler_.insert("LLeg First",
00135                        boost::bind(&FootstepMarker::menuFeedbackCB, this, _1));
00136   menu_handler_.insert("RLeg First",
00137                        boost::bind(&FootstepMarker::menuFeedbackCB, this, _1));
00138   marker_pose_.header.frame_id = marker_frame_id_;
00139   marker_pose_.header.stamp = ros::Time::now();
00140   marker_pose_.pose.orientation.w = 1.0;
00141 
00142   resetLegPoses();
00143 
00144   // initialize lleg_initial_pose, rleg_initial_pose
00145   lleg_initial_pose_.position.y = footstep_margin_ / 2.0;
00146   lleg_initial_pose_.orientation.w = 1.0;
00147   rleg_initial_pose_.position.y = - footstep_margin_ / 2.0;
00148   rleg_initial_pose_.orientation.w = 1.0;
00149   
00150   if (use_initial_reference_) {
00151     while (ros::ok()) {
00152       try {
00153         if (!tf_listener_->waitForTransform(marker_frame_id_, initial_reference_frame_,
00154                                             ros::Time(0.0), ros::Duration(10.0))) {
00155           ROS_INFO_THROTTLE(1.0,
00156                             "waiting for transform %s => %s", marker_frame_id_.c_str(),
00157                             initial_reference_frame_.c_str());
00158           continue;
00159         }
00160         ROS_INFO("resolved transform %s => %s", marker_frame_id_.c_str(),
00161                  initial_reference_frame_.c_str());
00162         tf::StampedTransform transform;
00163         tf_listener_->lookupTransform(marker_frame_id_, initial_reference_frame_,
00164                                       ros::Time(0), transform);
00165         marker_pose_.pose.position.x = transform.getOrigin().x();
00166         marker_pose_.pose.position.y = transform.getOrigin().y();
00167         marker_pose_.pose.position.z = transform.getOrigin().z();
00168         marker_pose_.pose.orientation.x = transform.getRotation().x();
00169         marker_pose_.pose.orientation.y = transform.getRotation().y();
00170         marker_pose_.pose.orientation.z = transform.getRotation().z();
00171         marker_pose_.pose.orientation.w = transform.getRotation().w();
00172         break;
00173       }
00174       catch (tf2::TransformException& e) {
00175         ROS_ERROR("Failed to lookup transformation: %s", e.what());
00176       }
00177     }
00178   }
00179 
00180   initializeInteractiveMarker();
00181 
00182   if (use_footstep_planner_) {
00183     ROS_INFO("waiting planner server...");
00184     ac_.waitForServer();
00185     ROS_INFO("found planner server...");
00186   }
00187   if (use_footstep_controller_) {
00188     ROS_INFO("waiting controller server...");
00189     ac_exec_.waitForServer();
00190     ROS_INFO("found controller server...");
00191   }
00192   
00193   move_marker_sub_ = nh.subscribe("move_marker", 1, &FootstepMarker::moveMarkerCB, this);
00194   menu_command_sub_ = nh.subscribe("menu_command", 1, &FootstepMarker::menuCommandCB, this);
00195   exec_sub_ = pnh.subscribe("execute", 1, &FootstepMarker::executeCB, this);
00196   resume_sub_ = pnh.subscribe("resume", 1, &FootstepMarker::resumeCB, this);
00197   if (use_initial_footstep_tf_) {
00198     // waiting TF
00199     while (ros::ok()) {
00200       try {
00201       if (tf_listener_->waitForTransform(lfoot_frame_id_, marker_frame_id_,
00202                                          ros::Time(0.0), ros::Duration(10.0))
00203           && tf_listener_->waitForTransform(rfoot_frame_id_, marker_frame_id_,
00204                                             ros::Time(0.0), ros::Duration(10.0))) {
00205         break;
00206       }
00207       ROS_INFO("waiting for transform {%s, %s} => %s", lfoot_frame_id_.c_str(),
00208                rfoot_frame_id_.c_str(), marker_frame_id_.c_str());
00209       }
00210       catch (tf2::TransformException& e) {
00211         ROS_ERROR("Failed to lookup transformation: %s", e.what());
00212       }
00213     }
00214     ROS_INFO("resolved transform {%s, %s} => %s", lfoot_frame_id_.c_str(),
00215              rfoot_frame_id_.c_str(), marker_frame_id_.c_str());
00216   }
00217   // if (use_projection_topic_) {
00218     projection_sub_ = pnh.subscribe("projected_pose", 1,
00219                                     &FootstepMarker::projectionCallback, this);
00220   // }
00221 }
00222 
00223 void FootstepMarker::configCallback(Config& config, uint32_t level)
00224 {
00225   boost::mutex::scoped_lock lock(plane_mutex_);
00226   use_projection_topic_ = config.use_projection_topic;
00227   use_projection_service_ = config.use_projection_service;
00228   use_plane_snap_ = config.use_plane_snap;
00229 }
00230 
00231 // a function to read double value from XmlRpcValue.
00232 // if the value is integer like 0 and 1, we need to
00233 // cast it to int first, and after that, casting to double.
00234 double getXMLDoubleValue(XmlRpc::XmlRpcValue val) {
00235   switch(val.getType()) {
00236   case XmlRpc::XmlRpcValue::TypeInt:
00237     return (double)((int)val);
00238   case XmlRpc::XmlRpcValue::TypeDouble:
00239     return (double)val;
00240   default:
00241     return 0;
00242   }
00243 }
00244 
00245 void FootstepMarker::readPoseParam(ros::NodeHandle& pnh, const std::string param,
00246                                    tf::Transform& offset) {
00247   XmlRpc::XmlRpcValue v;
00248   geometry_msgs::Pose pose;
00249   if (pnh.hasParam(param)) {
00250     pnh.param(param, v, v);
00251     // check if v is 7 length Array
00252     if (v.getType() == XmlRpc::XmlRpcValue::TypeArray &&
00253         v.size() == 7) {
00254       // safe parameter access by getXMLDoubleValue
00255       pose.position.x = getXMLDoubleValue(v[0]);
00256       pose.position.y = getXMLDoubleValue(v[1]);
00257       pose.position.z = getXMLDoubleValue(v[2]);
00258       pose.orientation.x = getXMLDoubleValue(v[3]);
00259       pose.orientation.y = getXMLDoubleValue(v[4]);
00260       pose.orientation.z = getXMLDoubleValue(v[5]);
00261       pose.orientation.w = getXMLDoubleValue(v[6]);
00262       // converst the message as following: msg -> eigen -> tf
00263       //void poseMsgToEigen(const geometry_msgs::Pose &m, Eigen::Affine3d &e);
00264       Eigen::Affine3d e;
00265       tf::poseMsgToEigen(pose, e); // msg -> eigen
00266       tf::transformEigenToTF(e, offset); // eigen -> tf
00267     }
00268     else {
00269       ROS_ERROR_STREAM(param << " is malformed, which should be 7 length array");
00270     }
00271   }
00272   else {
00273     ROS_WARN_STREAM("there is no parameter on " << param);
00274   }
00275 }
00276 
00277 void FootstepMarker::resetLegPoses() {
00278   lleg_pose_.orientation.x = 0.0;
00279   lleg_pose_.orientation.y = 0.0;
00280   lleg_pose_.orientation.z = 0.0;
00281   lleg_pose_.orientation.w = 1.0;
00282   lleg_pose_.position.x = 0.0;
00283   lleg_pose_.position.y = footstep_margin_ / 2.0;
00284   lleg_pose_.position.z = 0.0;
00285   
00286   rleg_pose_.orientation.x = 0.0;
00287   rleg_pose_.orientation.y = 0.0;
00288   rleg_pose_.orientation.z = 0.0;
00289   rleg_pose_.orientation.w = 1.0;
00290   rleg_pose_.position.x = 0.0;
00291   rleg_pose_.position.y = - footstep_margin_ / 2.0;
00292   rleg_pose_.position.z = 0.0;
00293 }
00294 
00295 geometry_msgs::Pose FootstepMarker::computeLegTransformation(uint8_t leg) {
00296   geometry_msgs::Pose new_pose;
00297   jsk_pcl_ros::CallSnapIt srv;
00298   srv.request.request.header.stamp = ros::Time::now();
00299   srv.request.request.header.frame_id = marker_frame_id_;
00300   srv.request.request.target_plane.header.stamp = ros::Time::now();
00301   srv.request.request.target_plane.header.frame_id = marker_frame_id_;
00302   srv.request.request.target_plane.polygon = computePolygon(leg);
00303   if (snapit_client_.call(srv)) {
00304     Eigen::Affine3d A, T, B, B_prime;
00305     tf::poseMsgToEigen(srv.response.transformation, T);
00306     tf::poseMsgToEigen(marker_pose_.pose, A);
00307     if (leg == jsk_footstep_msgs::Footstep::LEFT) {
00308       tf::poseMsgToEigen(lleg_pose_, B);
00309     }
00310     else if (leg == jsk_footstep_msgs::Footstep::RIGHT) {
00311       tf::poseMsgToEigen(rleg_pose_, B);
00312     }
00313     B_prime = A.inverse() * T * A * B;
00314     tf::poseEigenToMsg(B_prime, new_pose);
00315   }
00316   else {
00317     // throw exception
00318     ROS_ERROR("failed to call snapit");
00319   }
00320   return new_pose;
00321 }
00322 
00323 void FootstepMarker::snapLegs() {
00324   geometry_msgs::Pose l_pose = computeLegTransformation(jsk_footstep_msgs::Footstep::LEFT);
00325   geometry_msgs::Pose r_pose = computeLegTransformation(jsk_footstep_msgs::Footstep::RIGHT);
00326 
00327   lleg_pose_ = l_pose;
00328   rleg_pose_ = r_pose;
00329   
00330 }
00331 
00332 geometry_msgs::Polygon FootstepMarker::computePolygon(uint8_t leg) {
00333   geometry_msgs::Polygon polygon;
00334   // tree
00335   // marker_frame_id_ ---[marker_pose_]---> [leg_pose_] --> points
00336   std::vector<Eigen::Vector3d, Eigen::aligned_allocator<Eigen::Vector3d> > points;
00337   points.push_back(Eigen::Vector3d(foot_size_x_ / 2.0, foot_size_y_ / 2.0, 0.0));
00338   points.push_back(Eigen::Vector3d(-foot_size_x_ / 2.0, foot_size_y_ / 2.0, 0.0));
00339   points.push_back(Eigen::Vector3d(-foot_size_x_ / 2.0, -foot_size_y_ / 2.0, 0.0));
00340   points.push_back(Eigen::Vector3d(foot_size_x_ / 2.0, -foot_size_y_ / 2.0, 0.0));
00341 
00342   Eigen::Affine3d marker_pose_eigen;
00343   Eigen::Affine3d leg_pose_eigen;
00344   tf::poseMsgToEigen(marker_pose_.pose, marker_pose_eigen);
00345   if (leg == jsk_footstep_msgs::Footstep::LEFT) {
00346     tf::poseMsgToEigen(lleg_pose_, leg_pose_eigen);
00347   }
00348   else if (leg == jsk_footstep_msgs::Footstep::RIGHT) {
00349     tf::poseMsgToEigen(rleg_pose_, leg_pose_eigen);
00350   }
00351   
00352   for (size_t i = 0; i < points.size(); i++) {
00353     Eigen::Vector3d point = points[i];
00354     Eigen::Vector3d new_point = marker_pose_eigen * leg_pose_eigen * point;
00355     geometry_msgs::Point32 point_msg;
00356     point_msg.x = new_point[0];
00357     point_msg.y = new_point[1];
00358     point_msg.z = new_point[2];
00359     polygon.points.push_back(point_msg);
00360   }
00361   
00362   return polygon;
00363 }
00364 
00365 void FootstepMarker::executeCB(const std_msgs::Empty::ConstPtr& msg) {
00366   executeFootstep();
00367 }
00368 
00369 void FootstepMarker::resumeCB(const std_msgs::Empty::ConstPtr& msg) {
00370   resumeFootstep();
00371 }
00372 
00373 void FootstepMarker::menuCommandCB(const std_msgs::UInt8::ConstPtr& msg) {
00374   processMenuFeedback(msg->data);
00375 }
00376 
00377 void FootstepMarker::updateInitialFootstep() {
00378   //ROS_INFO("updateInitialFootstep");
00379   try {
00380     if (!use_initial_footstep_tf_) {
00381       return;
00382     } 
00383     tf::StampedTransform lfoot_transform, rfoot_transform;
00384     tf_listener_->lookupTransform(marker_frame_id_, lfoot_frame_id_, ros::Time(0.0), lfoot_transform);
00385     tf_listener_->lookupTransform(marker_frame_id_, rfoot_frame_id_, ros::Time(0.0), rfoot_transform);
00386 
00387     // apply offset
00388     // convert like tf -> eigen -> msg
00389     Eigen::Affine3d le, re;
00390     tf::transformTFToEigen(lfoot_transform * lleg_offset_, le); // tf -> eigen
00391     tf::poseEigenToMsg(le, lleg_initial_pose_);  // eigen -> msg
00392     tf::transformTFToEigen(rfoot_transform * rleg_offset_, re); // tf -> eigen
00393     tf::poseEigenToMsg(re, rleg_initial_pose_);  // eigen -> msg
00394   
00395     // we need to move the marker
00396     initializeInteractiveMarker();
00397   }
00398   catch (tf2::TransformException& e) {
00399     ROS_ERROR("Failed to lookup transformation: %s", e.what());
00400   }
00401 }
00402 
00403 void FootstepMarker::lookGround()
00404 {
00405   std_srvs::Empty empty;
00406   if (ros::service::call("/lookaround_ground", empty)) {
00407     ROS_INFO("Finished to look ground");
00408   }
00409   else {
00410     ROS_ERROR("Failed to look ground");
00411   }
00412 }
00413 
00414 void FootstepMarker::processMenuFeedback(uint8_t menu_entry_id) {
00415   switch (menu_entry_id) {
00416   case 1: {                     // look ground
00417     lookGround();
00418     break;
00419   }
00420   case 2: {                     // execute
00421     executeCB(std_msgs::Empty::ConstPtr());
00422     break;
00423   }
00424   case 3: {                     // replan
00425     planIfPossible();
00426     break;
00427   }
00428   case 4: {                     // cancel walk
00429     cancelWalk();
00430     break;
00431   }
00432   case 5: {                     // toggle 6dof marker
00433     show_6dof_control_ = !show_6dof_control_;
00434     break;
00435   }
00436   case 6: {                     // toggle 6dof marker
00437     changePlannerHeuristic(":straight-heuristic");
00438     break;
00439   }
00440   case 7: {                     // toggle 6dof marker
00441     changePlannerHeuristic(":stepcost-heuristic**");
00442     break;
00443   }
00444   case 8: {                     // toggle 6dof marker
00445     lleg_first_ = true;
00446     break;
00447   }
00448   case 9: {                     // toggle 6dof marker
00449     lleg_first_ = false;
00450     break;
00451   }
00452     
00453   default: {
00454     break;
00455   }
00456   }
00457 }
00458 
00459 void FootstepMarker::changePlannerHeuristic(const std::string& heuristic)
00460 {
00461   jsk_interactive_marker::SetHeuristic heuristic_req;
00462   heuristic_req.request.heuristic = heuristic;
00463   if (!ros::service::call("/footstep_planner/set_heuristic", heuristic_req)) {
00464     JSK_ROS_ERROR("failed to set heuristic");
00465   }
00466   else {
00467     JSK_ROS_INFO("Success to set heuristic: %s", heuristic.c_str());
00468   }
00469 }
00470 
00471 void FootstepMarker::cancelWalk()
00472 {
00473   ROS_WARN("canceling walking");
00474   ac_exec_.cancelAllGoals();
00475   ROS_WARN("canceled walking");
00476 }
00477 
00478 void FootstepMarker::callEstimateOcclusion()
00479 {
00480   std_srvs::Empty srv;
00481   estimate_occlusion_client_.call(srv);
00482 }
00483 
00484 bool FootstepMarker::projectMarkerToPlane()
00485 {
00486   if (use_projection_service_) {
00487     jsk_interactive_marker::SnapFootPrint snap;
00488     snap.request.input_pose = marker_pose_;
00489     snap.request.lleg_pose.orientation.w = 1.0;
00490     snap.request.rleg_pose.orientation.w = 1.0;
00491     snap.request.lleg_pose.position.y = footstep_margin_ / 2.0;
00492     snap.request.rleg_pose.position.y = - footstep_margin_ / 2.0;
00493     if (ros::service::call("project_footprint", snap) && snap.response.success) {
00494       // Resolve tf
00495       geometry_msgs::PoseStamped resolved_pose;
00496       tf_listener_->transformPose(marker_pose_.header.frame_id,
00497                                   snap.response.snapped_pose,
00498                                   resolved_pose);
00499       // Check distance to project
00500       Eigen::Vector3d projected_point, marker_point;
00501       tf::pointMsgToEigen(marker_pose_.pose.position, marker_point);
00502       tf::pointMsgToEigen(resolved_pose.pose.position, projected_point);
00503       if ((projected_point - marker_point).norm() < 0.3) {
00504         server_->setPose("footstep_marker", resolved_pose.pose);
00505         snapped_pose_pub_.publish(resolved_pose);
00506         current_pose_pub_.publish(resolved_pose);
00507         server_->applyChanges();
00508         marker_pose_.pose = resolved_pose.pose;
00509         return true;
00510       }
00511       else {
00512         return false;
00513       }
00514     }
00515     else {
00516       ROS_WARN("Failed to snap footprint");
00517       return false;
00518     }
00519   }
00520   else if (use_projection_topic_) {
00521     jsk_interactive_marker::SnapFootPrintInput msg;
00522     msg.input_pose = marker_pose_;
00523     msg.lleg_pose.orientation.w = 1.0;
00524     msg.rleg_pose.orientation.w = 1.0;
00525     msg.lleg_pose.position.y = footstep_margin_ / 2.0;
00526     msg.rleg_pose.position.y = - footstep_margin_ / 2.0;
00527     project_footprint_pub_.publish(msg);
00528     return true;                // true...?
00529   }
00530 }
00531 
00532 void FootstepMarker::menuFeedbackCB(const visualization_msgs::InteractiveMarkerFeedbackConstPtr &feedback) {
00533   processMenuFeedback(feedback->menu_entry_id);
00534 }
00535 
00536 void FootstepMarker::processFeedbackCB(const visualization_msgs::InteractiveMarkerFeedbackConstPtr &feedback) {
00537   boost::mutex::scoped_lock lock(plane_mutex_);
00538 
00539   marker_pose_.header = feedback->header;
00540   marker_pose_.pose = feedback->pose;
00541   marker_frame_id_ = feedback->header.frame_id;
00542   bool skip_plan = false;
00543   geometry_msgs::PoseStamped input_pose;
00544   current_pose_pub_.publish(marker_pose_);
00545   try {
00546     if (feedback->event_type == visualization_msgs::InteractiveMarkerFeedback::MOUSE_UP) {
00547       if (use_plane_snap_) {
00548         skip_plan = !projectMarkerToPlane();
00549       }
00550     }
00551     if (feedback->event_type == visualization_msgs::InteractiveMarkerFeedback::MOUSE_UP && !skip_plan) {
00552       if (always_planning_) planIfPossible();
00553     }
00554   }
00555   catch (tf2::TransformException& e) {
00556     ROS_ERROR("Failed to lookup transformation: %s", e.what());
00557   }
00558 }
00559 
00560 void FootstepMarker::resumeFootstep() {
00561   if (!use_footstep_controller_) {
00562     return;
00563   }
00564   actionlib::SimpleClientGoalState state = ac_exec_.getState();
00565   if (!state.isDone()) {
00566     ROS_ERROR("still executing footstep");
00567     return;
00568   }
00569   jsk_footstep_msgs::ExecFootstepsGoal goal;
00570   goal.strategy = jsk_footstep_msgs::ExecFootstepsGoal::RESUME;
00571   ac_exec_.sendGoal(goal);
00572 }
00573 
00574 void FootstepMarker::projectionCallback(const geometry_msgs::PoseStamped& pose)
00575 {
00576   geometry_msgs::PoseStamped resolved_pose;
00577   tf_listener_->transformPose(marker_pose_.header.frame_id,
00578                               pose,
00579                               resolved_pose);
00580   // Check distance to project
00581   Eigen::Vector3d projected_point, marker_point;
00582   tf::pointMsgToEigen(marker_pose_.pose.position, marker_point);
00583   tf::pointMsgToEigen(resolved_pose.pose.position, projected_point);
00584   if ((projected_point - marker_point).norm() < 0.3) {
00585     marker_pose_.pose = resolved_pose.pose;
00586     snapped_pose_pub_.publish(resolved_pose);
00587     current_pose_pub_.publish(resolved_pose);
00588   }
00589 }
00590 
00591 void FootstepMarker::executeFootstep() {
00592   if (!use_footstep_controller_) {
00593     return;
00594   }
00595   actionlib::SimpleClientGoalState state = ac_exec_.getState();
00596   if (!state.isDone()) {
00597     ROS_ERROR("still executing footstep");
00598     return;
00599   }
00600   if (!plan_result_) {
00601     ROS_ERROR("no planner result is available");
00602     return;
00603   }
00604   
00605   
00606   jsk_footstep_msgs::ExecFootstepsGoal goal;
00607   goal.footstep = plan_result_->result;
00608   //goal.strategy = jsk_footstep_msgs::ExecFootstepsGoal::DEFAULT_STRATEGY;
00609   ROS_INFO("sending goal...");
00610   ac_exec_.sendGoal(goal);
00611   // ac_exec_.waitForResult();
00612   // ROS_INFO("done executing...");
00613 }
00614 
00615 void FootstepMarker::planIfPossible() {
00616   boost::mutex::scoped_lock lock(plan_run_mutex_);
00617   // check the status of the ac_
00618   if (!use_footstep_planner_) {
00619     return;                     // do nothing
00620   }
00621   bool call_planner = !plan_run_;
00622   if (call_planner) {
00623     plan_run_ = true;
00624     jsk_footstep_msgs::PlanFootstepsGoal goal;
00625     jsk_footstep_msgs::FootstepArray goal_footstep;
00626     goal_footstep.header.frame_id = marker_frame_id_;
00627     goal_footstep.header.stamp = ros::Time(0.0);
00628     jsk_footstep_msgs::Footstep goal_left;
00629     goal_left.leg = jsk_footstep_msgs::Footstep::LEFT;
00630     goal_left.pose = getFootstepPose(true);
00631     goal_left.dimensions.x = foot_size_x_;
00632     goal_left.dimensions.y = foot_size_y_;
00633     goal_left.dimensions.z = foot_size_z_;
00634     jsk_footstep_msgs::Footstep goal_right;
00635     goal_right.pose = getFootstepPose(false);
00636     goal_right.leg = jsk_footstep_msgs::Footstep::RIGHT;
00637     goal_right.dimensions.x = foot_size_x_;
00638     goal_right.dimensions.y = foot_size_y_;
00639     goal_right.dimensions.z = foot_size_z_;
00640     goal_footstep.footsteps.push_back(goal_left);
00641     goal_footstep.footsteps.push_back(goal_right);
00642     goal.goal_footstep = goal_footstep;
00643     jsk_footstep_msgs::FootstepArray initial_footstep;
00644     initial_footstep.header.frame_id = marker_frame_id_;
00645     initial_footstep.header.stamp = ros::Time(0.0);
00646     // TODO: decide initial footstep by tf
00647     jsk_footstep_msgs::Footstep initial_left;
00648     initial_left.leg = jsk_footstep_msgs::Footstep::LEFT;
00649     initial_left.pose = lleg_initial_pose_;
00650     initial_left.dimensions.x = foot_size_x_;
00651     initial_left.dimensions.y = foot_size_y_;
00652     initial_left.dimensions.z = foot_size_z_;
00653     
00654     jsk_footstep_msgs::Footstep initial_right;
00655     initial_right.leg = jsk_footstep_msgs::Footstep::RIGHT;
00656     initial_right.pose = rleg_initial_pose_;
00657     initial_right.dimensions.x = foot_size_x_;
00658     initial_right.dimensions.y = foot_size_y_;
00659     initial_right.dimensions.z = foot_size_z_;
00660     if (lleg_first_) {
00661       initial_footstep.footsteps.push_back(initial_left);
00662       initial_footstep.footsteps.push_back(initial_right);
00663     }
00664     else {
00665       initial_footstep.footsteps.push_back(initial_right);
00666       initial_footstep.footsteps.push_back(initial_left);
00667     }
00668     goal.initial_footstep = initial_footstep;
00669     ac_.sendGoal(goal, boost::bind(&FootstepMarker::planDoneCB, this, _1, _2));
00670   }
00671 }
00672 
00673 void FootstepMarker::planDoneCB(const actionlib::SimpleClientGoalState &state, 
00674                                  const PlanResult::ConstPtr &result)
00675 {
00676   boost::mutex::scoped_lock lock(plan_run_mutex_);
00677   ROS_INFO("planDoneCB");
00678   plan_result_ = ac_.getResult();
00679   footstep_pub_.publish(plan_result_->result);
00680   ROS_INFO("planning is finished");
00681   plan_run_ = false;
00682 }
00683 
00684 geometry_msgs::Pose FootstepMarker::getFootstepPose(bool leftp) {
00685   tf::Vector3 offset(0, 0, 0);
00686   if (leftp) {
00687     offset[1] = footstep_margin_ / 2.0;
00688   }
00689   else {
00690     offset[1] = - footstep_margin_ / 2.0;
00691   }
00692   tf::Transform marker_origin;
00693   marker_origin.setOrigin(tf::Vector3(marker_pose_.pose.position.x,
00694                                       marker_pose_.pose.position.y,
00695                                       marker_pose_.pose.position.z));
00696   marker_origin.setRotation(tf::Quaternion(marker_pose_.pose.orientation.x,
00697                                            marker_pose_.pose.orientation.y,
00698                                            marker_pose_.pose.orientation.z,
00699                                            marker_pose_.pose.orientation.w));
00700   tf::Transform offset_trans;
00701   offset_trans.setRotation(tf::Quaternion(0, 0, 0, 1.0));
00702   offset_trans.setOrigin(offset);
00703   
00704   tf::Transform footstep_transform = marker_origin * offset_trans;
00705   geometry_msgs::Pose ret;
00706   ret.position.x = footstep_transform.getOrigin()[0];
00707   ret.position.y = footstep_transform.getOrigin()[1];
00708   ret.position.z = footstep_transform.getOrigin()[2];
00709   ret.orientation.x = footstep_transform.getRotation()[0];
00710   ret.orientation.y = footstep_transform.getRotation()[1];
00711   ret.orientation.z = footstep_transform.getRotation()[2];
00712   ret.orientation.w = footstep_transform.getRotation()[3];
00713   return ret;
00714 }
00715 
00716 void FootstepMarker::moveMarkerCB(const geometry_msgs::PoseStamped::ConstPtr& msg) {
00717   // move the marker
00718   geometry_msgs::PoseStamped transformed_pose;
00719   tf_listener_->transformPose(marker_frame_id_, *msg, transformed_pose);
00720   geometry_msgs::PoseStamped prev_pose = marker_pose_;
00721   marker_pose_ = transformed_pose;
00722   bool skip_plan = false;
00723   if (use_plane_snap_) {
00724     // do something magicalc
00725     skip_plan = !projectMarkerToPlane();
00726     if (skip_plan) {
00727       marker_pose_ = prev_pose;
00728     }
00729   }
00730   
00731   // need to solve TF
00732   server_->setPose("footstep_marker", transformed_pose.pose);
00733   server_->applyChanges();
00734   current_pose_pub_.publish(marker_pose_);
00735   if (!skip_plan) {
00736     planIfPossible();
00737   }
00738 }
00739 
00740 visualization_msgs::Marker FootstepMarker::makeFootstepMarker(geometry_msgs::Pose pose) {
00741   visualization_msgs::Marker marker;
00742   marker.type = visualization_msgs::Marker::CUBE;
00743   marker.scale.x = foot_size_x_;
00744   marker.scale.y = foot_size_y_;
00745   marker.scale.z = foot_size_z_;
00746   marker.color.a = 1.0;
00747   marker.pose = pose;
00748   return marker;
00749 }
00750 
00751 void FootstepMarker::initializeInteractiveMarker() {
00752   visualization_msgs::InteractiveMarker int_marker;
00753   int_marker.header.frame_id = marker_frame_id_;
00754   //int_marker.header.stamp = ros::Time(0);
00755   int_marker.name = "footstep_marker";
00756   int_marker.pose = marker_pose_.pose;
00757   visualization_msgs::Marker left_box_marker = makeFootstepMarker(lleg_pose_);
00758   left_box_marker.color.g = 1.0;
00759 
00760   visualization_msgs::InteractiveMarkerControl left_box_control;
00761   left_box_control.interaction_mode = visualization_msgs::InteractiveMarkerControl::BUTTON;
00762   left_box_control.always_visible = true;
00763   left_box_control.markers.push_back( left_box_marker );
00764 
00765   int_marker.controls.push_back( left_box_control );
00766 
00767   visualization_msgs::Marker right_box_marker = makeFootstepMarker(rleg_pose_);
00768   right_box_marker.color.r = 1.0;
00769 
00770   visualization_msgs::InteractiveMarkerControl right_box_control;
00771   right_box_control.interaction_mode = visualization_msgs::InteractiveMarkerControl::BUTTON;
00772   right_box_control.always_visible = true;
00773   right_box_control.markers.push_back( right_box_marker );
00774 
00775   int_marker.controls.push_back( right_box_control );
00776   if (show_6dof_control_) {
00777     im_helpers::add6DofControl(int_marker, false);
00778   }
00779   
00780   server_->insert(int_marker,
00781                   boost::bind(&FootstepMarker::processFeedbackCB, this, _1));
00782 
00783   // initial footsteps
00784   visualization_msgs::InteractiveMarker initial_lleg_int_marker;
00785   initial_lleg_int_marker.header.frame_id = marker_frame_id_;
00786   initial_lleg_int_marker.name = "left_initial_footstep_marker";
00787   initial_lleg_int_marker.pose.orientation.w = 1.0;
00788   visualization_msgs::Marker initial_left_marker = makeFootstepMarker(lleg_initial_pose_);
00789   initial_left_marker.color.g = 1.0;
00790 
00791   visualization_msgs::InteractiveMarkerControl initial_left_box_control;
00792   initial_left_box_control.interaction_mode = visualization_msgs::InteractiveMarkerControl::BUTTON;
00793   initial_left_box_control.always_visible = true;
00794   initial_left_box_control.markers.push_back(initial_left_marker);
00795 
00796   initial_lleg_int_marker.controls.push_back( initial_left_box_control );
00797   server_->insert(initial_lleg_int_marker,
00798                   boost::bind(&FootstepMarker::processFeedbackCB, this, _1));
00799 
00800   visualization_msgs::InteractiveMarker initial_rleg_int_marker;
00801   initial_rleg_int_marker.header.frame_id = marker_frame_id_;
00802   initial_rleg_int_marker.name = "right_initial_footstep_marker";
00803   initial_rleg_int_marker.pose.orientation.w = 1.0;
00804   visualization_msgs::Marker initial_right_marker = makeFootstepMarker(rleg_initial_pose_);
00805   initial_right_marker.color.r = 1.0;
00806 
00807   visualization_msgs::InteractiveMarkerControl initial_right_box_control;
00808   initial_right_box_control.interaction_mode = visualization_msgs::InteractiveMarkerControl::BUTTON;
00809   initial_right_box_control.always_visible = true;
00810   initial_right_box_control.markers.push_back(initial_right_marker);
00811 
00812   initial_rleg_int_marker.controls.push_back( initial_right_box_control );
00813   server_->insert(initial_rleg_int_marker,
00814                   boost::bind(&FootstepMarker::processFeedbackCB, this, _1));
00815   
00816   menu_handler_.apply( *server_, "footstep_marker");
00817   
00818   server_->applyChanges();
00819 }
00820 
00821 FootstepMarker::~FootstepMarker() {
00822 }
00823 
00824 int main(int argc, char** argv) {
00825   ros::init(argc, argv, "footstep_marker");
00826   FootstepMarker marker;
00827   ros::Rate r(10.0);
00828   while (ros::ok()) {
00829     ros::spinOnce();
00830     marker.updateInitialFootstep();
00831     r.sleep();
00832   }
00833   return 0;
00834 }


jsk_interactive_marker
Author(s): furuta
autogenerated on Sun Sep 13 2015 22:29:27