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
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
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
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
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
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
00145
00146
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
00165 if (v.getType() == XmlRpc::XmlRpcValue::TypeArray &&
00166 v.size() == 7) {
00167
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
00176
00177 Eigen::Affine3d e;
00178 tf::poseMsgToEigen(pose, e);
00179 tf::transformEigenToTF(e, offset);
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
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
00248
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
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
00300
00301 Eigen::Affine3d le, re;
00302 tf::transformTFToEigen(lfoot_transform * lleg_offset_, le);
00303 tf::poseEigenToMsg(le, lleg_initial_pose_);
00304 tf::transformTFToEigen(rfoot_transform * rleg_offset_, re);
00305 tf::poseEigenToMsg(re, rleg_initial_pose_);
00306
00307
00308 initializeInteractiveMarker();
00309 }
00310
00311 void FootstepMarker::processMenuFeedback(uint8_t menu_entry_id) {
00312 switch (menu_entry_id) {
00313 case 1: {
00314 snapLegs();
00315 initializeInteractiveMarker();
00316 break;
00317 }
00318 case 2: {
00319 resetLegPoses();
00320 initializeInteractiveMarker();
00321 break;
00322 }
00323 case 3: {
00324 executeCB(std_msgs::Empty::ConstPtr());
00325 break;
00326 }
00327 case 4: {
00328 planIfPossible();
00329 break;
00330 }
00331 case 5: {
00332 callEstimateOcclusion();
00333 break;
00334 }
00335 case 6: {
00336 cancelWalk();
00337 break;
00338 }
00339 case 7: {
00340 show_6dof_control_ = !show_6dof_control_;
00341 break;
00342 }
00343 case 8: {
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
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);
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
00396
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
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
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
00427
00428 Eigen::Vector3f e_z = m.col(2);
00429 Eigen::Quaternionf trans;
00430 trans.setFromTwoVectors(e_z, normal);
00431
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
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) {
00492 marker_pose_.pose = min_pose.pose;
00493 snapped_pose_pub_.publish(min_pose);
00494
00495
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
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
00563 ROS_INFO("sending goal...");
00564 ac_exec_.sendGoal(goal);
00565
00566
00567 }
00568
00569 void FootstepMarker::planIfPossible() {
00570 boost::mutex::scoped_lock(plan_run_mutex_);
00571
00572 if (!use_footstep_planner_) {
00573 return;
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
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
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
00663 skip_plan = !projectMarkerToPlane();
00664 }
00665 }
00666
00667
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
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
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 }