footstep_marker.cpp
Go to the documentation of this file.
00001 #include <iostream>
00002 #include <interactive_markers/tools.h>
00003 #include <jsk_interactive_marker/footstep_marker.h>
00004 #include <jsk_interactive_marker/interactive_marker_utils.h>
00005 #include <jsk_interactive_marker/interactive_marker_helpers.h>
00006 #include <jsk_footstep_msgs/PlanFootstepsGoal.h>
00007 #include <jsk_footstep_msgs/PlanFootstepsResult.h>
00008 #include <std_srvs/Empty.h>
00009 #include <jsk_pcl_ros/CallSnapIt.h>
00010 #include <Eigen/StdVector>
00011 #include <eigen_conversions/eigen_msg.h>
00012 #include <tf_conversions/tf_eigen.h>
00013 #include <jsk_pcl_ros/geo_util.h>
00014 
00015 FootstepMarker::FootstepMarker():
00016 ac_("footstep_planner", true), ac_exec_("footstep_controller", true),
00017   plan_run_(false) {
00018   // read parameters
00019   tf_listener_.reset(new tf::TransformListener);
00020   ros::NodeHandle pnh("~");
00021   ros::NodeHandle nh;
00022   pnh.param("foot_size_x", foot_size_x_, 0.247);
00023   pnh.param("foot_size_y", foot_size_y_, 0.135);
00024   pnh.param("foot_size_z", foot_size_z_, 0.01);
00025   pnh.param("lfoot_frame_id", lfoot_frame_id_, std::string("lfsensor"));
00026   pnh.param("rfoot_frame_id", rfoot_frame_id_, std::string("rfsensor"));
00027   pnh.param("show_6dof_control", show_6dof_control_, true);
00028   // read lfoot_offset
00029   readPoseParam(pnh, "lfoot_offset", lleg_offset_);
00030   readPoseParam(pnh, "rfoot_offset", rleg_offset_);
00031   
00032   pnh.param("footstep_margin", footstep_margin_, 0.2);
00033   pnh.param("use_footstep_planner", use_footstep_planner_, true);
00034   pnh.param("use_plane_snap", use_plane_snap_, true);
00035   pnh.param("use_footstep_controller", use_footstep_controller_, true);
00036   pnh.param("use_initial_footstep_tf", use_initial_footstep_tf_, true);
00037   pnh.param("wait_snapit_server", wait_snapit_server_, false);
00038   pnh.param("frame_id", marker_frame_id_, std::string("/map"));
00039   footstep_pub_ = nh.advertise<jsk_footstep_msgs::FootstepArray>("footstep_from_marker", 1);
00040   snapit_client_ = nh.serviceClient<jsk_pcl_ros::CallSnapIt>("snapit");
00041   snapped_pose_pub_ = pnh.advertise<geometry_msgs::PoseStamped>("snapped_pose", 1);
00042   estimate_occlusion_client_ = nh.serviceClient<std_srvs::Empty>("require_estimation");
00043   if (wait_snapit_server_) {
00044     snapit_client_.waitForExistence();
00045   }
00046   
00047   if (use_plane_snap_) {
00048     //plane_sub_ = pnh.subscribe("planes", 1, &FootstepMarker::planesCB, this);
00049     polygons_sub_.subscribe(pnh, "planes", 1);
00050     coefficients_sub_.subscribe(pnh, "planes_coefficients", 1);
00051     sync_ = boost::make_shared<message_filters::Synchronizer<PlaneSyncPolicy> >(100);
00052     sync_->connectInput(polygons_sub_, coefficients_sub_);
00053     sync_->registerCallback(boost::bind(&FootstepMarker::planeCB,
00054                                         this, _1, _2));
00055   }
00056   
00057   if (pnh.getParam("initial_reference_frame", initial_reference_frame_)) {
00058     use_initial_reference_ = true;
00059   }
00060   else {
00061     use_initial_reference_ = false;
00062   }
00063 
00064   server_.reset( new interactive_markers::InteractiveMarkerServer(ros::this_node::getName()));
00065   menu_handler_.insert( "Snap Legs",
00066                         boost::bind(&FootstepMarker::menuFeedbackCB, this, _1));
00067   menu_handler_.insert( "Reset Legs",
00068                         boost::bind(&FootstepMarker::menuFeedbackCB, this, _1));
00069   menu_handler_.insert( "Execute the Plan",
00070                         boost::bind(&FootstepMarker::menuFeedbackCB, this, _1));
00071   menu_handler_.insert( "Force to replan",
00072                         boost::bind(&FootstepMarker::menuFeedbackCB, this, _1));
00073   menu_handler_.insert( "Estimate occlusion",
00074                         boost::bind(&FootstepMarker::menuFeedbackCB, this, _1));
00075   menu_handler_.insert( "Cancel Walk",
00076                         boost::bind(&FootstepMarker::menuFeedbackCB, this, _1));
00077   menu_handler_.insert( "Toggle 6dof marker",
00078                         boost::bind(&FootstepMarker::menuFeedbackCB, this, _1));
00079   menu_handler_.insert( "Resume Footstep",
00080                       boost::bind(&FootstepMarker::menuFeedbackCB, this, _1));
00081   marker_pose_.header.frame_id = marker_frame_id_;
00082   marker_pose_.header.stamp = ros::Time::now();
00083   marker_pose_.pose.orientation.w = 1.0;
00084 
00085   resetLegPoses();
00086 
00087   // initialize lleg_initial_pose, rleg_initial_pose
00088   lleg_initial_pose_.position.y = footstep_margin_ / 2.0;
00089   lleg_initial_pose_.orientation.w = 1.0;
00090   rleg_initial_pose_.position.y = - footstep_margin_ / 2.0;
00091   rleg_initial_pose_.orientation.w = 1.0;
00092   
00093   if (use_initial_reference_) {
00094     while (ros::ok()) {
00095       if (tf_listener_->waitForTransform(marker_frame_id_, initial_reference_frame_,
00096                                          ros::Time(0.0), ros::Duration(10.0))) {
00097         break;
00098       }
00099       ROS_INFO("waiting for transform %s => %s", marker_frame_id_.c_str(),
00100                initial_reference_frame_.c_str());
00101     }
00102     tf::StampedTransform transform;
00103     tf_listener_->lookupTransform(marker_frame_id_, initial_reference_frame_,
00104                                   ros::Time(0), transform);
00105     marker_pose_.pose.position.x = transform.getOrigin().x();
00106     marker_pose_.pose.position.y = transform.getOrigin().y();
00107     marker_pose_.pose.position.z = transform.getOrigin().z();
00108     marker_pose_.pose.orientation.x = transform.getRotation().x();
00109     marker_pose_.pose.orientation.y = transform.getRotation().y();
00110     marker_pose_.pose.orientation.z = transform.getRotation().z();
00111     marker_pose_.pose.orientation.w = transform.getRotation().w();
00112   }
00113 
00114   initializeInteractiveMarker();
00115   
00116   move_marker_sub_ = nh.subscribe("move_marker", 1, &FootstepMarker::moveMarkerCB, this);
00117   menu_command_sub_ = nh.subscribe("menu_command", 1, &FootstepMarker::menuCommandCB, this);
00118   exec_sub_ = pnh.subscribe("execute", 1, &FootstepMarker::executeCB, this);
00119   resume_sub_ = pnh.subscribe("resume", 1, &FootstepMarker::resumeCB, this);
00120   if (use_initial_footstep_tf_) {
00121     // waiting TF
00122     while (ros::ok()) {
00123       if (tf_listener_->waitForTransform(lfoot_frame_id_, marker_frame_id_,
00124                                          ros::Time(0.0), ros::Duration(10.0))
00125           && tf_listener_->waitForTransform(rfoot_frame_id_, marker_frame_id_,
00126                                             ros::Time(0.0), ros::Duration(10.0))) {
00127         break;
00128       }
00129       ROS_INFO("waiting for transform {%s, %s} => %s", lfoot_frame_id_.c_str(),
00130                rfoot_frame_id_.c_str(), marker_frame_id_.c_str());
00131     }
00132   }
00133 
00134   if (use_footstep_planner_) {
00135     ROS_INFO("waiting planner server...");
00136     ac_.waitForServer();
00137   }
00138   if (use_footstep_controller_) {
00139     ROS_INFO("waiting controller server...");
00140     ac_exec_.waitForServer();
00141   }
00142 }
00143 
00144 // a function to read double value from XmlRpcValue.
00145 // if the value is integer like 0 and 1, we need to
00146 // cast it to int first, and after that, casting to double.
00147 double getXMLDoubleValue(XmlRpc::XmlRpcValue val) {
00148   switch(val.getType()) {
00149   case XmlRpc::XmlRpcValue::TypeInt:
00150     return (double)((int)val);
00151   case XmlRpc::XmlRpcValue::TypeDouble:
00152     return (double)val;
00153   default:
00154     return 0;
00155   }
00156 }
00157 
00158 void FootstepMarker::readPoseParam(ros::NodeHandle& pnh, const std::string param,
00159                                    tf::Transform& offset) {
00160   XmlRpc::XmlRpcValue v;
00161   geometry_msgs::Pose pose;
00162   if (pnh.hasParam(param)) {
00163     pnh.param(param, v, v);
00164     // check if v is 7 length Array
00165     if (v.getType() == XmlRpc::XmlRpcValue::TypeArray &&
00166         v.size() == 7) {
00167       // safe parameter access by getXMLDoubleValue
00168       pose.position.x = getXMLDoubleValue(v[0]);
00169       pose.position.y = getXMLDoubleValue(v[1]);
00170       pose.position.z = getXMLDoubleValue(v[2]);
00171       pose.orientation.x = getXMLDoubleValue(v[3]);
00172       pose.orientation.y = getXMLDoubleValue(v[4]);
00173       pose.orientation.z = getXMLDoubleValue(v[5]);
00174       pose.orientation.w = getXMLDoubleValue(v[6]);
00175       // converst the message as following: msg -> eigen -> tf
00176       //void poseMsgToEigen(const geometry_msgs::Pose &m, Eigen::Affine3d &e);
00177       Eigen::Affine3d e;
00178       tf::poseMsgToEigen(pose, e); // msg -> eigen
00179       tf::transformEigenToTF(e, offset); // eigen -> tf
00180     }
00181     else {
00182       ROS_ERROR_STREAM(param << " is malformed, which should be 7 length array");
00183     }
00184   }
00185   else {
00186     ROS_WARN_STREAM("there is no parameter on " << param);
00187   }
00188 }
00189 
00190 void FootstepMarker::resetLegPoses() {
00191   lleg_pose_.orientation.x = 0.0;
00192   lleg_pose_.orientation.y = 0.0;
00193   lleg_pose_.orientation.z = 0.0;
00194   lleg_pose_.orientation.w = 1.0;
00195   lleg_pose_.position.x = 0.0;
00196   lleg_pose_.position.y = footstep_margin_ / 2.0;
00197   lleg_pose_.position.z = 0.0;
00198   
00199   rleg_pose_.orientation.x = 0.0;
00200   rleg_pose_.orientation.y = 0.0;
00201   rleg_pose_.orientation.z = 0.0;
00202   rleg_pose_.orientation.w = 1.0;
00203   rleg_pose_.position.x = 0.0;
00204   rleg_pose_.position.y = - footstep_margin_ / 2.0;
00205   rleg_pose_.position.z = 0.0;
00206 }
00207 
00208 geometry_msgs::Pose FootstepMarker::computeLegTransformation(uint8_t leg) {
00209   geometry_msgs::Pose new_pose;
00210   jsk_pcl_ros::CallSnapIt srv;
00211   srv.request.request.header.stamp = ros::Time::now();
00212   srv.request.request.header.frame_id = marker_frame_id_;
00213   srv.request.request.target_plane.header.stamp = ros::Time::now();
00214   srv.request.request.target_plane.header.frame_id = marker_frame_id_;
00215   srv.request.request.target_plane.polygon = computePolygon(leg);
00216   if (snapit_client_.call(srv)) {
00217     Eigen::Affine3d A, T, B, B_prime;
00218     tf::poseMsgToEigen(srv.response.transformation, T);
00219     tf::poseMsgToEigen(marker_pose_.pose, A);
00220     if (leg == jsk_footstep_msgs::Footstep::LEFT) {
00221       tf::poseMsgToEigen(lleg_pose_, B);
00222     }
00223     else if (leg == jsk_footstep_msgs::Footstep::RIGHT) {
00224       tf::poseMsgToEigen(rleg_pose_, B);
00225     }
00226     B_prime = A.inverse() * T * A * B;
00227     tf::poseEigenToMsg(B_prime, new_pose);
00228   }
00229   else {
00230     // throw exception
00231     ROS_ERROR("failed to call snapit");
00232   }
00233   return new_pose;
00234 }
00235 
00236 void FootstepMarker::snapLegs() {
00237   geometry_msgs::Pose l_pose = computeLegTransformation(jsk_footstep_msgs::Footstep::LEFT);
00238   geometry_msgs::Pose r_pose = computeLegTransformation(jsk_footstep_msgs::Footstep::RIGHT);
00239 
00240   lleg_pose_ = l_pose;
00241   rleg_pose_ = r_pose;
00242   
00243 }
00244 
00245 geometry_msgs::Polygon FootstepMarker::computePolygon(uint8_t leg) {
00246   geometry_msgs::Polygon polygon;
00247   // tree
00248   // marker_frame_id_ ---[marker_pose_]---> [leg_pose_] --> points
00249   std::vector<Eigen::Vector3d, Eigen::aligned_allocator<Eigen::Vector3d> > points;
00250   points.push_back(Eigen::Vector3d(foot_size_x_ / 2.0, foot_size_y_ / 2.0, 0.0));
00251   points.push_back(Eigen::Vector3d(-foot_size_x_ / 2.0, foot_size_y_ / 2.0, 0.0));
00252   points.push_back(Eigen::Vector3d(-foot_size_x_ / 2.0, -foot_size_y_ / 2.0, 0.0));
00253   points.push_back(Eigen::Vector3d(foot_size_x_ / 2.0, -foot_size_y_ / 2.0, 0.0));
00254 
00255   Eigen::Affine3d marker_pose_eigen;
00256   Eigen::Affine3d leg_pose_eigen;
00257   tf::poseMsgToEigen(marker_pose_.pose, marker_pose_eigen);
00258   if (leg == jsk_footstep_msgs::Footstep::LEFT) {
00259     tf::poseMsgToEigen(lleg_pose_, leg_pose_eigen);
00260   }
00261   else if (leg == jsk_footstep_msgs::Footstep::RIGHT) {
00262     tf::poseMsgToEigen(rleg_pose_, leg_pose_eigen);
00263   }
00264   
00265   for (size_t i = 0; i < points.size(); i++) {
00266     Eigen::Vector3d point = points[i];
00267     Eigen::Vector3d new_point = marker_pose_eigen * leg_pose_eigen * point;
00268     geometry_msgs::Point32 point_msg;
00269     point_msg.x = new_point[0];
00270     point_msg.y = new_point[1];
00271     point_msg.z = new_point[2];
00272     polygon.points.push_back(point_msg);
00273   }
00274   
00275   return polygon;
00276 }
00277 
00278 void FootstepMarker::executeCB(const std_msgs::Empty::ConstPtr& msg) {
00279   executeFootstep();
00280 }
00281 
00282 void FootstepMarker::resumeCB(const std_msgs::Empty::ConstPtr& msg) {
00283   resumeFootstep();
00284 }
00285 
00286 void FootstepMarker::menuCommandCB(const std_msgs::UInt8::ConstPtr& msg) {
00287   processMenuFeedback(msg->data);
00288 }
00289 
00290 void FootstepMarker::updateInitialFootstep() {
00291   //ROS_INFO("updateInitialFootstep");
00292   if (!use_initial_footstep_tf_) {
00293     return;
00294   } 
00295   tf::StampedTransform lfoot_transform, rfoot_transform;
00296   tf_listener_->lookupTransform(marker_frame_id_, lfoot_frame_id_, ros::Time(0.0), lfoot_transform);
00297   tf_listener_->lookupTransform(marker_frame_id_, rfoot_frame_id_, ros::Time(0.0), rfoot_transform);
00298 
00299   // apply offset
00300   // convert like tf -> eigen -> msg
00301   Eigen::Affine3d le, re;
00302   tf::transformTFToEigen(lfoot_transform * lleg_offset_, le); // tf -> eigen
00303   tf::poseEigenToMsg(le, lleg_initial_pose_);  // eigen -> msg
00304   tf::transformTFToEigen(rfoot_transform * rleg_offset_, re); // tf -> eigen
00305   tf::poseEigenToMsg(re, rleg_initial_pose_);  // eigen -> msg
00306   
00307   // we need to move the marker
00308   initializeInteractiveMarker();
00309 }
00310 
00311 void FootstepMarker::processMenuFeedback(uint8_t menu_entry_id) {
00312   switch (menu_entry_id) {
00313   case 1: {                     // snapit
00314     snapLegs();
00315     initializeInteractiveMarker();
00316     break;
00317   }
00318   case 2: {
00319     resetLegPoses();
00320     initializeInteractiveMarker();
00321     break;
00322   }
00323   case 3: {                     // execute
00324     executeCB(std_msgs::Empty::ConstPtr());
00325     break;
00326   }
00327   case 4: {                     // replan
00328     planIfPossible();
00329     break;
00330   }
00331   case 5: {                     // estimate
00332     callEstimateOcclusion();
00333     break;
00334   }
00335   case 6: {                     // cancel walk
00336     cancelWalk();
00337     break;
00338   }
00339   case 7: {                     // toggle 6dof marker
00340     show_6dof_control_ = !show_6dof_control_;
00341     break;
00342   }
00343   case 8: {                     // resume
00344     resumeCB(std_msgs::Empty::ConstPtr());
00345     break;
00346   }
00347   default: {
00348     break;
00349   }
00350   }
00351 }
00352 
00353 void FootstepMarker::cancelWalk()
00354 {
00355   ROS_WARN("canceling walking");
00356   ac_exec_.cancelAllGoals();
00357   ROS_WARN("canceled walking");
00358 }
00359 
00360 void FootstepMarker::callEstimateOcclusion()
00361 {
00362   std_srvs::Empty srv;
00363   estimate_occlusion_client_.call(srv);
00364 }
00365 
00366 double FootstepMarker::projectPoseToPlane(
00367   const std::vector<geometry_msgs::PointStamped>& polygon,
00368   const geometry_msgs::PoseStamped& point,
00369   geometry_msgs::PoseStamped& foot)
00370 {
00371 #ifdef PROJECT_DEBUG
00372   ROS_INFO("---------");
00373 #endif
00374   jsk_pcl_ros::ConvexPolygon::Vertices vertices;
00375   for (size_t i = 0; i < polygon.size(); i++) {
00376     geometry_msgs::Point p = polygon[i].point;
00377     jsk_pcl_ros::ConvexPolygon::Vertex v (p.x, p.y, p.z);
00378     //ROS_INFO("v[%lu] - [%f, %f, %f]", i, v[0], v[1], v[2]);
00379     vertices.push_back(v);
00380   }
00381   jsk_pcl_ros::ConvexPolygon convex(vertices);
00382   Eigen::Vector3f orig(polygon[1].point.x, polygon[1].point.y, polygon[1].point.z);
00383   Eigen::Vector3f A(polygon[0].point.x, polygon[0].point.y, polygon[0].point.z);
00384   Eigen::Vector3f B(polygon[2].point.x, polygon[2].point.y, polygon[2].point.z);
00385   Eigen::Vector3f normal = (B - orig).cross(A - orig).normalized();
00386   Eigen::Vector3f g(0, 0, 1);   // should be parameterize
00387   bool reversed = false;
00388   if (normal.dot(g) < 0) {
00389     normal = - normal;
00390     reversed = true;
00391   }
00392   Eigen::Vector3f p(point.pose.position.x, point.pose.position.y, point.pose.position.z);
00393   double d = convex.distanceToPoint(p);
00394   Eigen::Vector3f projected_point = p - d * normal;
00395   // Eigen::Vector3d projected_point;
00396   // convex.projectOnPlane(p, projected_point);
00397 #ifdef PROJECT_DEBUG
00398   ROS_INFO("normal: [%f, %f, %f]", normal[0], normal[1], normal[2]);
00399   ROS_INFO("plane d: %f", convex.getD());
00400   ROS_INFO("distance: %f", d);
00401 #endif
00402   // check the point is inside of the polygon or not...
00403   bool insidep = convex.isInside(projected_point);
00404   if (insidep) {
00405 #ifdef PROJECT_DEBUG
00406     ROS_INFO("insidep: true");
00407 #endif
00408   }
00409   else {
00410 #ifdef PROJECT_DEBUG
00411      ROS_INFO("insidep: false");
00412 #endif
00413      d = DBL_MAX;
00414   }
00415   foot.header = point.header;
00416   foot.pose.position.x = projected_point[0];
00417   foot.pose.position.y = projected_point[1];
00418   foot.pose.position.z = projected_point[2];
00419   // compute orientation...
00420   Eigen::Quaternionf q(point.pose.orientation.w,
00421                        point.pose.orientation.x,
00422                        point.pose.orientation.y,
00423                        point.pose.orientation.z);
00424   Eigen::Quaternionf q2;
00425   Eigen::Matrix3f m = q.toRotationMatrix();
00426   // Eigen::Vector3d e_x = m.col(0);
00427   // Eigen::Vector3d e_y = m.col(1);
00428   Eigen::Vector3f e_z = m.col(2);
00429   Eigen::Quaternionf trans;
00430   trans.setFromTwoVectors(e_z, normal); // ???
00431   // we need to check if trans is flipped
00432   
00433   q2 = trans * q;
00434   Eigen::Vector3f e_z2 = q2.toRotationMatrix().col(2);
00435 #ifdef PROJECT_DEBUG
00436   ROS_INFO("e_z: [%f, %f, %f]", e_z[0], e_z[1], e_z[2]);
00437   ROS_INFO("e_z2: [%f, %f, %f]", e_z2[0], e_z2[1], e_z2[2]);
00438 #endif
00439   //q2 = q * trans;
00440   foot.pose.orientation.x = q2.x();
00441   foot.pose.orientation.y = q2.y();
00442   foot.pose.orientation.z = q2.z();
00443   foot.pose.orientation.w = q2.w();
00444   return fabs(d);
00445 }
00446 
00447 void FootstepMarker::transformPolygon(
00448   const geometry_msgs::PolygonStamped& polygon,
00449   const std_msgs::Header& target_header,
00450   std::vector<geometry_msgs::PointStamped>& output_points)
00451 {
00452   for (size_t i = 0; i < polygon.polygon.points.size(); i++) {
00453     geometry_msgs::PointStamped point, output;
00454     point.header = polygon.header;
00455     point.point.x = polygon.polygon.points[i].x;
00456     point.point.y = polygon.polygon.points[i].y;
00457     point.point.z = polygon.polygon.points[i].z;
00458     tf_listener_->transformPoint(target_header.frame_id,
00459                                  point,
00460                                  output);
00461     output_points.push_back(output);
00462   }
00463 }
00464 
00465 bool FootstepMarker::projectMarkerToPlane()
00466 {
00467   if (latest_planes_->polygons.size() == 0) {
00468     ROS_WARN("it's not valid polygons");
00469     return false;
00470   }
00471   ROS_ERROR("projecting");
00472   double min_distance = DBL_MAX;
00473   geometry_msgs::PoseStamped min_pose;
00474   for (size_t i = 0; i < latest_planes_->polygons.size(); i++) {
00475     std::vector<geometry_msgs::PointStamped> transformed_points;
00476     transformPolygon(latest_planes_->polygons[i],
00477                      marker_pose_.header,
00478                      transformed_points);
00479     geometry_msgs::PoseStamped foot;
00480     geometry_msgs::PoseStamped from;
00481     from.pose = marker_pose_.pose;
00482     from.header = marker_pose_.header;
00483     double distance = projectPoseToPlane(transformed_points,
00484                                          from, foot);
00485     if (min_distance > distance) {
00486       min_pose = foot;
00487       min_distance = distance;
00488     }
00489   }
00490   ROS_INFO_STREAM("min_distance: " << min_distance);
00491   if (min_distance < 0.3) {     // smaller than 30cm
00492     marker_pose_.pose = min_pose.pose;
00493     snapped_pose_pub_.publish(min_pose);
00494     // server_->setPose("footstep_marker", min_pose.pose);
00495     // server_->applyChanges();
00496     ROS_WARN("projected");
00497     return true;
00498   }
00499   else {
00500     ROS_WARN("not projected");
00501     return false;
00502   }
00503 }
00504 
00505 void FootstepMarker::menuFeedbackCB(const visualization_msgs::InteractiveMarkerFeedbackConstPtr &feedback) {
00506   processMenuFeedback(feedback->menu_entry_id);
00507 }
00508 
00509 void FootstepMarker::processFeedbackCB(const visualization_msgs::InteractiveMarkerFeedbackConstPtr &feedback) {
00510   boost::mutex::scoped_lock(plane_mutex_);
00511   marker_pose_.header = feedback->header;
00512   marker_pose_.pose = feedback->pose;
00513   marker_frame_id_ = feedback->header.frame_id;
00514   bool skip_plan = false;
00515   if (feedback->event_type == visualization_msgs::InteractiveMarkerFeedback::MOUSE_UP) {
00516     if (use_plane_snap_) {
00517       if (!latest_planes_) {
00518         ROS_WARN("no planes are available yet");
00519       }
00520       else {
00521         // do something magicalc
00522         skip_plan = !projectMarkerToPlane();
00523       }
00524     }
00525   }
00526   if (feedback->event_type == visualization_msgs::InteractiveMarkerFeedback::MOUSE_UP && !skip_plan) {
00527     planIfPossible();
00528   }
00529 }
00530 
00531 void FootstepMarker::resumeFootstep() {
00532   if (!use_footstep_controller_) {
00533     return;
00534   }
00535   actionlib::SimpleClientGoalState state = ac_exec_.getState();
00536   if (!state.isDone()) {
00537     ROS_ERROR("still executing footstep");
00538     return;
00539   }
00540   jsk_footstep_msgs::ExecFootstepsGoal goal;
00541   goal.strategy = jsk_footstep_msgs::ExecFootstepsGoal::RESUME;
00542   ac_exec_.sendGoal(goal);
00543 }
00544 
00545 void FootstepMarker::executeFootstep() {
00546   if (!use_footstep_controller_) {
00547     return;
00548   }
00549   actionlib::SimpleClientGoalState state = ac_exec_.getState();
00550   if (!state.isDone()) {
00551     ROS_ERROR("still executing footstep");
00552     return;
00553   }
00554   if (!plan_result_) {
00555     ROS_ERROR("no planner result is available");
00556     return;
00557   }
00558   
00559   
00560   jsk_footstep_msgs::ExecFootstepsGoal goal;
00561   goal.footstep = plan_result_->result;
00562   //goal.strategy = jsk_footstep_msgs::ExecFootstepsGoal::DEFAULT_STRATEGY;
00563   ROS_INFO("sending goal...");
00564   ac_exec_.sendGoal(goal);
00565   // ac_exec_.waitForResult();
00566   // ROS_INFO("done executing...");
00567 }
00568 
00569 void FootstepMarker::planIfPossible() {
00570   boost::mutex::scoped_lock(plan_run_mutex_);
00571   // check the status of the ac_
00572   if (!use_footstep_planner_) {
00573     return;                     // do nothing
00574   }
00575   bool call_planner = !plan_run_;
00576   if (call_planner) {
00577     plan_run_ = true;
00578     jsk_footstep_msgs::PlanFootstepsGoal goal;
00579     jsk_footstep_msgs::FootstepArray goal_footstep;
00580     goal_footstep.header.frame_id = marker_frame_id_;
00581     goal_footstep.header.stamp = ros::Time(0.0);
00582     jsk_footstep_msgs::Footstep goal_left;
00583     goal_left.leg = jsk_footstep_msgs::Footstep::LEFT;
00584     goal_left.pose = getFootstepPose(true);
00585     jsk_footstep_msgs::Footstep goal_right;
00586     goal_right.pose = getFootstepPose(false);
00587     goal_right.leg = jsk_footstep_msgs::Footstep::RIGHT;
00588     goal_footstep.footsteps.push_back(goal_left);
00589     goal_footstep.footsteps.push_back(goal_right);
00590     goal.goal_footstep = goal_footstep;
00591     jsk_footstep_msgs::FootstepArray initial_footstep;
00592     initial_footstep.header.frame_id = marker_frame_id_;
00593     initial_footstep.header.stamp = ros::Time(0.0);
00594     // TODO: decide initial footstep by tf
00595     jsk_footstep_msgs::Footstep initial_left;
00596     initial_left.leg = jsk_footstep_msgs::Footstep::LEFT;
00597     initial_left.pose = lleg_initial_pose_;
00598     initial_footstep.footsteps.push_back(initial_left);
00599     jsk_footstep_msgs::Footstep initial_right;
00600     initial_right.leg = jsk_footstep_msgs::Footstep::RIGHT;
00601     initial_right.pose = rleg_initial_pose_;
00602     initial_footstep.footsteps.push_back(initial_right);
00603     goal.initial_footstep = initial_footstep;
00604     ac_.sendGoal(goal, boost::bind(&FootstepMarker::planDoneCB, this, _1, _2));
00605   }
00606 }
00607 
00608 void FootstepMarker::planDoneCB(const actionlib::SimpleClientGoalState &state, 
00609                                  const PlanResult::ConstPtr &result)
00610 {
00611   boost::mutex::scoped_lock(plan_run_mutex_);
00612   ROS_INFO("planDoneCB");
00613   plan_result_ = ac_.getResult();
00614   footstep_pub_.publish(plan_result_->result);
00615   ROS_INFO("planning is finished");
00616   plan_run_ = false;
00617 }
00618 
00619 geometry_msgs::Pose FootstepMarker::getFootstepPose(bool leftp) {
00620   tf::Vector3 offset(0, 0, 0);
00621   if (leftp) {
00622     offset[1] = footstep_margin_ / 2.0;
00623   }
00624   else {
00625     offset[1] = - footstep_margin_ / 2.0;
00626   }
00627   tf::Transform marker_origin;
00628   marker_origin.setOrigin(tf::Vector3(marker_pose_.pose.position.x,
00629                                       marker_pose_.pose.position.y,
00630                                       marker_pose_.pose.position.z));
00631   marker_origin.setRotation(tf::Quaternion(marker_pose_.pose.orientation.x,
00632                                            marker_pose_.pose.orientation.y,
00633                                            marker_pose_.pose.orientation.z,
00634                                            marker_pose_.pose.orientation.w));
00635   tf::Transform offset_trans;
00636   offset_trans.setRotation(tf::Quaternion(0, 0, 0, 1.0));
00637   offset_trans.setOrigin(offset);
00638   
00639   tf::Transform footstep_transform = marker_origin * offset_trans;
00640   geometry_msgs::Pose ret;
00641   ret.position.x = footstep_transform.getOrigin()[0];
00642   ret.position.y = footstep_transform.getOrigin()[1];
00643   ret.position.z = footstep_transform.getOrigin()[2];
00644   ret.orientation.x = footstep_transform.getRotation()[0];
00645   ret.orientation.y = footstep_transform.getRotation()[1];
00646   ret.orientation.z = footstep_transform.getRotation()[2];
00647   ret.orientation.w = footstep_transform.getRotation()[3];
00648   return ret;
00649 }
00650 
00651 void FootstepMarker::moveMarkerCB(const geometry_msgs::PoseStamped::ConstPtr& msg) {
00652   // move the marker
00653   geometry_msgs::PoseStamped transformed_pose;
00654   tf_listener_->transformPose(marker_frame_id_, *msg, transformed_pose);
00655   marker_pose_ = transformed_pose;
00656   bool skip_plan = false;
00657   if (use_plane_snap_) {
00658     if (!latest_planes_) {
00659       ROS_WARN("no planes are available yet");
00660     }
00661     else {
00662       // do something magicalc
00663       skip_plan = !projectMarkerToPlane();
00664     }
00665   }
00666   
00667   // need to solve TF
00668   server_->setPose("footstep_marker", transformed_pose.pose);
00669   server_->applyChanges();
00670   if (!skip_plan) {
00671     planIfPossible();
00672   }
00673 }
00674 
00675 visualization_msgs::Marker FootstepMarker::makeFootstepMarker(geometry_msgs::Pose pose) {
00676   visualization_msgs::Marker marker;
00677   marker.type = visualization_msgs::Marker::CUBE;
00678   marker.scale.x = foot_size_x_;
00679   marker.scale.y = foot_size_y_;
00680   marker.scale.z = foot_size_z_;
00681   marker.color.a = 1.0;
00682   marker.pose = pose;
00683   return marker;
00684 }
00685 
00686 void FootstepMarker::initializeInteractiveMarker() {
00687   visualization_msgs::InteractiveMarker int_marker;
00688   int_marker.header.frame_id = marker_frame_id_;
00689   //int_marker.header.stamp = ros::Time(0);
00690   int_marker.name = "footstep_marker";
00691   int_marker.pose = marker_pose_.pose;
00692   visualization_msgs::Marker left_box_marker = makeFootstepMarker(lleg_pose_);
00693   left_box_marker.color.g = 1.0;
00694 
00695   visualization_msgs::InteractiveMarkerControl left_box_control;
00696   left_box_control.interaction_mode = visualization_msgs::InteractiveMarkerControl::BUTTON;
00697   left_box_control.always_visible = true;
00698   left_box_control.markers.push_back( left_box_marker );
00699 
00700   int_marker.controls.push_back( left_box_control );
00701 
00702   visualization_msgs::Marker right_box_marker = makeFootstepMarker(rleg_pose_);
00703   right_box_marker.color.r = 1.0;
00704 
00705   visualization_msgs::InteractiveMarkerControl right_box_control;
00706   right_box_control.interaction_mode = visualization_msgs::InteractiveMarkerControl::BUTTON;
00707   right_box_control.always_visible = true;
00708   right_box_control.markers.push_back( right_box_marker );
00709 
00710   int_marker.controls.push_back( right_box_control );
00711   if (show_6dof_control_) {
00712     im_helpers::add6DofControl(int_marker, false);
00713   }
00714   
00715   server_->insert(int_marker,
00716                   boost::bind(&FootstepMarker::processFeedbackCB, this, _1));
00717 
00718   // initial footsteps
00719   visualization_msgs::InteractiveMarker initial_lleg_int_marker;
00720   initial_lleg_int_marker.header.frame_id = marker_frame_id_;
00721   initial_lleg_int_marker.name = "left_initial_footstep_marker";
00722   initial_lleg_int_marker.pose.orientation.w = 1.0;
00723   visualization_msgs::Marker initial_left_marker = makeFootstepMarker(lleg_initial_pose_);
00724   initial_left_marker.color.g = 1.0;
00725 
00726   visualization_msgs::InteractiveMarkerControl initial_left_box_control;
00727   initial_left_box_control.interaction_mode = visualization_msgs::InteractiveMarkerControl::BUTTON;
00728   initial_left_box_control.always_visible = true;
00729   initial_left_box_control.markers.push_back(initial_left_marker);
00730 
00731   initial_lleg_int_marker.controls.push_back( initial_left_box_control );
00732   server_->insert(initial_lleg_int_marker,
00733                   boost::bind(&FootstepMarker::processFeedbackCB, this, _1));
00734 
00735   visualization_msgs::InteractiveMarker initial_rleg_int_marker;
00736   initial_rleg_int_marker.header.frame_id = marker_frame_id_;
00737   initial_rleg_int_marker.name = "right_initial_footstep_marker";
00738   initial_rleg_int_marker.pose.orientation.w = 1.0;
00739   visualization_msgs::Marker initial_right_marker = makeFootstepMarker(rleg_initial_pose_);
00740   initial_right_marker.color.r = 1.0;
00741 
00742   visualization_msgs::InteractiveMarkerControl initial_right_box_control;
00743   initial_right_box_control.interaction_mode = visualization_msgs::InteractiveMarkerControl::BUTTON;
00744   initial_right_box_control.always_visible = true;
00745   initial_right_box_control.markers.push_back(initial_right_marker);
00746 
00747   initial_rleg_int_marker.controls.push_back( initial_right_box_control );
00748   server_->insert(initial_rleg_int_marker,
00749                   boost::bind(&FootstepMarker::processFeedbackCB, this, _1));
00750   
00751   menu_handler_.apply( *server_, "footstep_marker");
00752   
00753   server_->applyChanges();
00754 }
00755 
00756 FootstepMarker::~FootstepMarker() {
00757 }
00758 
00759 void FootstepMarker::planeCB(
00760   const jsk_pcl_ros::PolygonArray::ConstPtr& planes,
00761   const jsk_pcl_ros::ModelCoefficientsArray::ConstPtr& coefficients)
00762 {
00763   boost::mutex::scoped_lock(plane_mutex_);
00764   if (planes->polygons.size() > 0) {
00765     latest_planes_ = planes;
00766     latest_coefficients_ = coefficients;
00767   }
00768   else {
00769     ROS_WARN_STREAM(__FUNCTION__ << "the size of the plane is 0, ignore");
00770   }
00771 }
00772 
00773 int main(int argc, char** argv) {
00774   ros::init(argc, argv, "footstep_marker");
00775   FootstepMarker marker;
00776   ros::Rate r(10.0);
00777   
00778   while (ros::ok()) {
00779     ros::spinOnce();
00780     marker.updateInitialFootstep();
00781     r.sleep();
00782   }
00783   return 0;
00784 }


jsk_interactive_marker
Author(s): furuta
autogenerated on Mon Oct 6 2014 01:19:15