00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036 #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
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
00075
00076 pnh.param("always_planning", always_planning_, true);
00077
00078 project_footprint_pub_ = pnh.advertise<jsk_interactive_marker::SnapFootPrintInput>("project_footprint", 1);
00079
00080
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
00113
00114
00115
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
00123
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
00129
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
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
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
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
00232
00233
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
00252 if (v.getType() == XmlRpc::XmlRpcValue::TypeArray &&
00253 v.size() == 7) {
00254
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
00263
00264 Eigen::Affine3d e;
00265 tf::poseMsgToEigen(pose, e);
00266 tf::transformEigenToTF(e, offset);
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
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
00335
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
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
00388
00389 Eigen::Affine3d le, re;
00390 tf::transformTFToEigen(lfoot_transform * lleg_offset_, le);
00391 tf::poseEigenToMsg(le, lleg_initial_pose_);
00392 tf::transformTFToEigen(rfoot_transform * rleg_offset_, re);
00393 tf::poseEigenToMsg(re, rleg_initial_pose_);
00394
00395
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: {
00417 lookGround();
00418 break;
00419 }
00420 case 2: {
00421 executeCB(std_msgs::Empty::ConstPtr());
00422 break;
00423 }
00424 case 3: {
00425 planIfPossible();
00426 break;
00427 }
00428 case 4: {
00429 cancelWalk();
00430 break;
00431 }
00432 case 5: {
00433 show_6dof_control_ = !show_6dof_control_;
00434 break;
00435 }
00436 case 6: {
00437 changePlannerHeuristic(":straight-heuristic");
00438 break;
00439 }
00440 case 7: {
00441 changePlannerHeuristic(":stepcost-heuristic**");
00442 break;
00443 }
00444 case 8: {
00445 lleg_first_ = true;
00446 break;
00447 }
00448 case 9: {
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
00495 geometry_msgs::PoseStamped resolved_pose;
00496 tf_listener_->transformPose(marker_pose_.header.frame_id,
00497 snap.response.snapped_pose,
00498 resolved_pose);
00499
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;
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
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
00609 ROS_INFO("sending goal...");
00610 ac_exec_.sendGoal(goal);
00611
00612
00613 }
00614
00615 void FootstepMarker::planIfPossible() {
00616 boost::mutex::scoped_lock lock(plan_run_mutex_);
00617
00618 if (!use_footstep_planner_) {
00619 return;
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
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
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
00725 skip_plan = !projectMarkerToPlane();
00726 if (skip_plan) {
00727 marker_pose_ = prev_pose;
00728 }
00729 }
00730
00731
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
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
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 }