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
00037
00038 #include <ros/ros.h>
00039
00040 #include <tf/tf.h>
00041 #include <tf/transform_listener.h>
00042 #include <urdf/model.h>
00043 #include <angles/angles.h>
00044
00045 #include <actionlib/client/action_client.h>
00046 #include <pr2_controllers_msgs/JointTrajectoryAction.h>
00047
00048 #include <actionlib/server/simple_action_server.h>
00049 #include <move_arm_msgs/MoveArmStatistics.h>
00050 #include <move_arm_msgs/MoveArmAction.h>
00051
00052 #include <trajectory_msgs/JointTrajectory.h>
00053 #include <kinematics_msgs/GetConstraintAwarePositionIK.h>
00054 #include <kinematics_msgs/GetPositionFK.h>
00055
00056 #include <motion_planning_msgs/FilterJointTrajectoryWithConstraints.h>
00057 #include <geometric_shapes_msgs/Shape.h>
00058 #include <motion_planning_msgs/DisplayTrajectory.h>
00059 #include <motion_planning_msgs/GetMotionPlan.h>
00060 #include <motion_planning_msgs/ConvertToJointConstraint.h>
00061 #include <motion_planning_msgs/convert_messages.h>
00062 #include <motion_planning_msgs/ArmNavigationErrorCodes.h>
00063
00064 #include <visualization_msgs/Marker.h>
00065
00066 #include <planning_environment/util/construct_object.h>
00067 #include <planning_environment_msgs/utils.h>
00068
00069 #include <geometric_shapes/bodies.h>
00070
00071 #include <planning_environment_msgs/GetRobotState.h>
00072 #include <planning_environment_msgs/GetJointTrajectoryValidity.h>
00073 #include <planning_environment_msgs/GetStateValidity.h>
00074 #include <planning_environment_msgs/GetGroupInfo.h>
00075 #include <planning_environment_msgs/GetEnvironmentSafety.h>
00076 #include <planning_environment_msgs/SetConstraints.h>
00077
00078 #include <visualization_msgs/MarkerArray.h>
00079
00080 #include <move_arm_head_monitor/HeadMonitorAction.h>
00081 #include <move_arm_head_monitor/HeadLookAction.h>
00082 #include <actionlib/client/simple_action_client.h>
00083 #include <actionlib/client/simple_client_goal_state.h>
00084
00085 #include <std_msgs/Bool.h>
00086
00087 #include <valarray>
00088 #include <algorithm>
00089 #include <cstdlib>
00090
00091 typedef actionlib::ActionClient<pr2_controllers_msgs::JointTrajectoryAction> JointExecutorActionClient;
00092
00093 namespace move_arm
00094 {
00095
00096 enum MoveArmState {
00097 PLANNING,
00098 START_CONTROL,
00099 VISUALIZE_PLAN,
00100 MONITOR,
00101 PAUSE
00102 };
00103
00104 enum ControllerStatus {
00105 QUEUED,
00106 ACTIVE,
00107 SUCCESS,
00108 FAILED
00109 };
00110
00111 enum EnvironmentServerChecks{
00112 COLLISION_TEST = 1,
00113 PATH_CONSTRAINTS_TEST = 2,
00114 GOAL_CONSTRAINTS_TEST = 4,
00115 JOINT_LIMITS_TEST = 8,
00116 CHECK_FULL_TRAJECTORY = 16
00117 };
00118
00119 typedef struct{
00120 bool accept_partial_plans;
00121 bool accept_invalid_goals;
00122 bool disable_ik;
00123 bool disable_collision_monitoring;
00124 bool is_pose_goal;
00125 double allowed_planning_time;
00126 std::string planner_service_name;
00127 } MoveArmParameters;
00128
00129 static const std::string ARM_IK_NAME = "arm_ik";
00130 static const std::string ARM_FK_NAME = "arm_fk";
00131 static const std::string TRAJECTORY_FILTER = "filter_trajectory";
00132 static const std::string DISPLAY_PATH_PUB_TOPIC = "display_path";
00133 static const std::string DISPLAY_JOINT_GOAL_PUB_TOPIC = "display_joint_goal";
00134 static const double MIN_TRAJECTORY_MONITORING_FREQUENCY = 1.0;
00135 static const double MAX_TRAJECTORY_MONITORING_FREQUENCY = 100.0;
00136
00137 class MoveArm
00138 {
00139 public:
00140
00141 MoveArm(const std::string &group_name) :
00142 group_(group_name),
00143 private_handle_("~")
00144 {
00145 double trajectory_monitoring_frequency;
00146 private_handle_.param<double>("move_arm_frequency",move_arm_frequency_, 50.0);
00147 private_handle_.param<double>("trajectory_discretization",trajectory_discretization_, 0.03);
00148 private_handle_.param<double>("trajectory_monitoring_frequency",trajectory_monitoring_frequency, 20.0);
00149 private_handle_.param<double>("trajectory_filter_allowed_time",trajectory_filter_allowed_time_, 2.0);
00150 private_handle_.param<double>("ik_allowed_time",ik_allowed_time_, 2.0);
00151
00152 private_handle_.param<double>("pause_allowed_time",pause_allowed_time_, 30.0);
00153 private_handle_.param<std::string>("head_monitor_link",head_monitor_link_, std::string());
00154 private_handle_.param<double>("head_monitor_link_x",head_monitor_link_x_, 0.0);
00155 private_handle_.param<double>("head_monitor_link_y",head_monitor_link_y_, 0.0);
00156 private_handle_.param<double>("head_monitor_link_z",head_monitor_link_z_, 0.0);
00157 private_handle_.param<double>("head_monitor_max_frequency",head_monitor_max_frequency_, 2.0);
00158 private_handle_.param<double>("head_monitor_time_offset",head_monitor_time_offset_, 1.0);
00159
00160 private_handle_.param<bool>("publish_stats",publish_stats_, true);
00161
00162 std::string urdf_xml,full_urdf_xml;
00163 root_handle_.param("urdf_xml", urdf_xml, std::string("robot_description"));
00164 if(!root_handle_.getParam(urdf_xml,full_urdf_xml))
00165 {
00166 ROS_ERROR("Could not load the xml from parameter server: %s\n", urdf_xml.c_str());
00167 robot_model_initialized_ = false;
00168 }
00169 else
00170 {
00171 robot_model_.initString(full_urdf_xml);
00172 robot_model_initialized_ = true;
00173 }
00174
00175 using_head_monitor_ = true;
00176 num_planning_attempts_ = 0;
00177 state_ = PLANNING;
00178 last_monitor_time_ = ros::Time::now();
00179 trajectory_monitoring_frequency = std::min<double>(std::max<double>(trajectory_monitoring_frequency,MIN_TRAJECTORY_MONITORING_FREQUENCY),MAX_TRAJECTORY_MONITORING_FREQUENCY);
00180 trajectory_monitoring_duration_ = ros::Duration(1.0/trajectory_monitoring_frequency);
00181
00182 if(head_monitor_link_.empty())
00183 {
00184 ROS_WARN("No 'head_monitor_link' parameter specified, head monitoring will not be used.");
00185 using_head_monitor_ = false;
00186 }
00187
00188 ik_client_ = root_handle_.serviceClient<kinematics_msgs::GetConstraintAwarePositionIK>(ARM_IK_NAME);
00189
00190 check_plan_validity_client_ = root_handle_.serviceClient<planning_environment_msgs::GetJointTrajectoryValidity>("get_trajectory_validity");
00191 check_env_safe_client_ = root_handle_.serviceClient<planning_environment_msgs::GetEnvironmentSafety>("get_environment_safety");
00192 check_state_validity_client_ = root_handle_.serviceClient<planning_environment_msgs::GetStateValidity>("get_state_validity");
00193 check_execution_safe_client_ = root_handle_.serviceClient<planning_environment_msgs::GetJointTrajectoryValidity>("get_execution_safety");
00194 get_group_info_client_ = root_handle_.serviceClient<planning_environment_msgs::GetGroupInfo>("get_group_info");
00195 get_state_client_ = root_handle_.serviceClient<planning_environment_msgs::GetRobotState>("get_robot_state");
00196 allowed_contact_regions_publisher_ = root_handle_.advertise<visualization_msgs::MarkerArray>("allowed_contact_regions_array", 128);
00197 filter_trajectory_client_ = root_handle_.serviceClient<motion_planning_msgs::FilterJointTrajectoryWithConstraints>("filter_trajectory");
00198
00199 if(using_head_monitor_) {
00200 head_monitor_client_.reset(new actionlib::SimpleActionClient<move_arm_head_monitor::HeadMonitorAction> ("head_monitor_action", true));
00201 head_look_client_.reset(new actionlib::SimpleActionClient<move_arm_head_monitor::HeadLookAction> ("head_look_action", true));
00202
00203 const unsigned int MAX_TRIES = 5;
00204 unsigned int tries = 0;
00205
00206 while(!head_monitor_client_->waitForServer(ros::Duration(10))) {
00207 ROS_INFO("Waiting for head monitor server");
00208 tries++;
00209 if(tries >= MAX_TRIES) {
00210 ROS_INFO("Can't talk to head monitor, not using");
00211 using_head_monitor_ = false;
00212 break;
00213 }
00214 }
00215
00216 if(using_head_monitor_) {
00217 tries = 0;
00218 while(!head_look_client_->waitForServer(ros::Duration(10))) {
00219 ROS_INFO("Waiting for head look server");
00220 tries++;
00221 if(tries >= MAX_TRIES) {
00222 ROS_INFO("Can't talk to head look client, not using");
00223 using_head_monitor_ = false;
00224 break;
00225 }
00226 }
00227 }
00228 }
00229
00230
00231 arm_ik_initialized_ = false;
00232 ros::service::waitForService("get_trajectory_validity");
00233 ros::service::waitForService("get_environment_safety");
00234 ros::service::waitForService("get_state_validity");
00235 ros::service::waitForService("get_execution_safety");
00236 ros::service::waitForService("get_group_info");
00237 ros::service::waitForService("get_robot_state");
00238 ros::service::waitForService("filter_trajectory");
00239
00240 action_server_.reset(new actionlib::SimpleActionServer<move_arm_msgs::MoveArmAction>(root_handle_, "move_" + group_name, boost::bind(&MoveArm::execute, this, _1)));
00241
00242 display_path_publisher_ = root_handle_.advertise<motion_planning_msgs::DisplayTrajectory>(DISPLAY_PATH_PUB_TOPIC, 1, true);
00243 display_joint_goal_publisher_ = root_handle_.advertise<motion_planning_msgs::DisplayTrajectory>(DISPLAY_JOINT_GOAL_PUB_TOPIC, 1, true);
00244 stats_publisher_ = private_handle_.advertise<move_arm_msgs::MoveArmStatistics>("statistics",1,true);
00245 motion_planning_msgs::RobotState robot_state;
00246 trajectory_msgs::JointTrajectory joint_traj;
00247 getRobotState(robot_state);
00248 joint_traj.points.push_back(motion_planning_msgs::jointStateToJointTrajectoryPoint(robot_state.joint_state));
00249 joint_traj.joint_names = robot_state.joint_state.name;
00250
00251 visualizePlan(joint_traj);
00252 visualizeJointGoal(joint_traj);
00253
00254 }
00255 virtual ~MoveArm()
00256 {
00257 }
00258
00259 bool configure()
00260 {
00261 if(!initializeControllerInterface())
00262 {
00263 ROS_ERROR("Could not initialize controller interface");
00264 return false;
00265 }
00266 if (group_.empty())
00267 {
00268 ROS_ERROR("No 'group' parameter specified. Without the name of the group of joints to plan for, action cannot start");
00269 return false;
00270 }
00271 planning_environment_msgs::GetGroupInfo::Request req;
00272 planning_environment_msgs::GetGroupInfo::Response res;
00273 req.group_name = group_;
00274 if(get_group_info_client_.call(req,res))
00275 {
00276 if(!res.joint_names.empty())
00277 {
00278 group_joint_names_ = res.joint_names;
00279 group_link_names_ = res.link_names;
00280 }
00281 else
00282 {
00283 ROS_ERROR("Could not get the list of joint names in the group: %s",
00284 group_.c_str());
00285 return false;
00286 }
00287 }
00288 else
00289 {
00290 ROS_ERROR("Service call to find group info failed on %s",
00291 get_group_info_client_.getService().c_str());
00292 return false;
00293 }
00294
00295
00296 req.group_name="";
00297 if(get_group_info_client_.call(req,res))
00298 {
00299 all_link_names_ = res.link_names;
00300 } else {
00301 ROS_INFO("Can't get all link names");
00302 return false;
00303 }
00304 return true;
00305 }
00306
00307 private:
00308
00312 bool convertPoseGoalToJointGoal(motion_planning_msgs::GetMotionPlan::Request &req)
00313 {
00314 if(!arm_ik_initialized_)
00315 {
00316 if(!ros::service::waitForService(ARM_IK_NAME,ros::Duration(1.0)))
00317 {
00318 ROS_WARN("Inverse kinematics service is unavailable");
00319 return false;
00320 }
00321 else
00322 {
00323 arm_ik_initialized_ = true;
00324 }
00325 }
00326
00327
00328 ROS_DEBUG("Acting on goal to pose ...");
00329 ROS_DEBUG("Position constraint: %f %f %f",
00330 req.motion_plan_request.goal_constraints.position_constraints[0].position.x,
00331 req.motion_plan_request.goal_constraints.position_constraints[0].position.y,
00332 req.motion_plan_request.goal_constraints.position_constraints[0].position.z);
00333 ROS_DEBUG("Orientation constraint: %f %f %f %f",
00334 req.motion_plan_request.goal_constraints.orientation_constraints[0].orientation.x,
00335 req.motion_plan_request.goal_constraints.orientation_constraints[0].orientation.y,
00336 req.motion_plan_request.goal_constraints.orientation_constraints[0].orientation.z,
00337 req.motion_plan_request.goal_constraints.orientation_constraints[0].orientation.w);
00338
00339 geometry_msgs::PoseStamped tpose = motion_planning_msgs::poseConstraintsToPoseStamped(req.motion_plan_request.goal_constraints.position_constraints[0],
00340 req.motion_plan_request.goal_constraints.orientation_constraints[0]);
00341 std::string link_name = req.motion_plan_request.goal_constraints.position_constraints[0].link_name;
00342 sensor_msgs::JointState solution;
00343
00344 ROS_INFO("IK request");
00345 ROS_INFO("link_name : %s",tpose.header.frame_id.c_str());
00346 ROS_INFO("frame_id : %s",tpose.header.frame_id.c_str());
00347 ROS_INFO("position : (%f,%f,%f)",tpose.pose.position.x,tpose.pose.position.y,tpose.pose.position.z);
00348 ROS_INFO("orientation : (%f,%f,%f,%f)",tpose.pose.orientation.x,tpose.pose.orientation.y,tpose.pose.orientation.z,tpose.pose.orientation.w);
00349 ROS_INFO(" ");
00350 if (computeIK(tpose,
00351 link_name,
00352 solution))
00353 {
00354
00355
00356
00357 motion_planning_msgs::RobotState ik_sanity_check;
00358 ik_sanity_check.joint_state.header = tpose.header;
00359
00360 for (unsigned int i = 0 ; i < solution.name.size() ; ++i)
00361 {
00362 motion_planning_msgs::JointConstraint jc;
00363 jc.joint_name = solution.name[i];
00364 jc.position = solution.position[i];
00365 jc.tolerance_below = 0.01;
00366 jc.tolerance_above = 0.01;
00367 req.motion_plan_request.goal_constraints.joint_constraints.push_back(jc);
00368 ik_sanity_check.joint_state.name.push_back(jc.joint_name);
00369 ik_sanity_check.joint_state.position.push_back(jc.position);
00370 }
00371 motion_planning_msgs::ArmNavigationErrorCodes error_code;
00372 if(!isStateValidAtGoal(ik_sanity_check, error_code))
00373 {
00374 ROS_INFO("IK returned joint state for goal that doesn't seem to be valid");
00375 if(error_code.val == error_code.GOAL_CONSTRAINTS_VIOLATED) {
00376 ROS_WARN("IK solution doesn't obey goal constraints");
00377 } else if(error_code.val == error_code.COLLISION_CONSTRAINTS_VIOLATED) {
00378 ROS_WARN("IK solution in collision");
00379 } else {
00380 ROS_WARN_STREAM("Some other problem with ik solution " << error_code.val);
00381 }
00382 }
00383 req.motion_plan_request.goal_constraints.position_constraints.clear();
00384 req.motion_plan_request.goal_constraints.orientation_constraints.clear();
00385 return true;
00386 }
00387 else
00388 return false;
00389 }
00390
00391 bool computeIK(const geometry_msgs::PoseStamped &pose_stamped_msg,
00392 const std::string &link_name,
00393 sensor_msgs::JointState &solution)
00394 {
00395 kinematics_msgs::GetConstraintAwarePositionIK::Request request;
00396 kinematics_msgs::GetConstraintAwarePositionIK::Response response;
00397
00398 request.ik_request.pose_stamped = pose_stamped_msg;
00399 if(!getRobotState(request.ik_request.robot_state)) {
00400 return false;
00401 }
00402 request.ik_request.ik_seed_state = request.ik_request.robot_state;
00403 request.ik_request.ik_link_name = link_name;
00404 request.timeout = ros::Duration(ik_allowed_time_);
00405 request.ordered_collision_operations = original_request_.motion_plan_request.ordered_collision_operations;
00406 request.allowed_contacts = original_request_.motion_plan_request.allowed_contacts;
00407 request.constraints = original_request_.motion_plan_request.goal_constraints;
00408 request.link_padding = original_request_.motion_plan_request.link_padding;
00409 if (ik_client_.call(request, response))
00410 {
00411 move_arm_action_result_.error_code = response.error_code;
00412 if(response.error_code.val != response.error_code.SUCCESS)
00413 {
00414 ROS_ERROR("IK Solution not found, IK returned with error_code: %d",response.error_code.val);
00415 return false;
00416 }
00417 solution = response.solution.joint_state;
00418 if (solution.position.size() != group_joint_names_.size())
00419 {
00420 ROS_ERROR("Incorrect number of elements in IK output.");
00421 return false;
00422 }
00423 for(unsigned int i = 0; i < solution.position.size() ; ++i)
00424 ROS_DEBUG("IK[%d] = %f", (int)i, solution.position[i]);
00425 }
00426 else
00427 {
00428 ROS_ERROR("IK service failed");
00429 return false;
00430 }
00431 return true;
00432 }
00433
00434 bool checkIK(const geometry_msgs::PoseStamped &pose_stamped_msg,
00435 const std::string &link_name,
00436 sensor_msgs::JointState &solution)
00437 {
00438 kinematics_msgs::GetPositionFK::Request request;
00439 kinematics_msgs::GetPositionFK::Response response;
00440
00441 request.robot_state.joint_state.name = group_joint_names_;
00442 request.fk_link_names.resize(1);
00443 request.fk_link_names[0] = link_name;
00444 request.robot_state.joint_state.position = solution.position;
00445 request.header = pose_stamped_msg.header;
00446 if (fk_client_.call(request, response))
00447 {
00448 if(response.error_code.val != response.error_code.SUCCESS)
00449 return false;
00450 ROS_DEBUG("Obtained FK solution");
00451 ROS_DEBUG("FK Pose:");
00452 ROS_DEBUG("Position : (%f,%f,%f)",
00453 response.pose_stamped[0].pose.position.x,
00454 response.pose_stamped[0].pose.position.y,
00455 response.pose_stamped[0].pose.position.z);
00456 ROS_DEBUG("Rotation : (%f,%f,%f,%f)",
00457 response.pose_stamped[0].pose.orientation.x,
00458 response.pose_stamped[0].pose.orientation.y,
00459 response.pose_stamped[0].pose.orientation.z,
00460 response.pose_stamped[0].pose.orientation.w);
00461 ROS_DEBUG(" ");
00462 }
00463 else
00464 {
00465 ROS_ERROR("FK service failed");
00466 return false;
00467 }
00468 return true;
00469 }
00473
00477 bool filterTrajectory(const trajectory_msgs::JointTrajectory &trajectory_in,
00478 trajectory_msgs::JointTrajectory &trajectory_out)
00479 {
00480 motion_planning_msgs::FilterJointTrajectoryWithConstraints::Request req;
00481 motion_planning_msgs::FilterJointTrajectoryWithConstraints::Response res;
00482 fillTrajectoryMsg(trajectory_in, req.trajectory);
00483
00484 if(trajectory_filter_allowed_time_ == 0.0)
00485 {
00486 trajectory_out = req.trajectory;
00487 return true;
00488 }
00489
00490 req.allowed_contacts = original_request_.motion_plan_request.allowed_contacts;
00491 req.ordered_collision_operations = original_request_.motion_plan_request.ordered_collision_operations;
00492 req.path_constraints = original_request_.motion_plan_request.path_constraints;
00493 req.goal_constraints = original_request_.motion_plan_request.goal_constraints;
00494 req.link_padding = original_request_.motion_plan_request.link_padding;
00495 req.allowed_time = ros::Duration(trajectory_filter_allowed_time_);
00496 ros::Time smoothing_time = ros::Time::now();
00497 if(filter_trajectory_client_.call(req,res))
00498 {
00499 move_arm_stats_.trajectory_duration = (res.trajectory.points.back().time_from_start-res.trajectory.points.front().time_from_start).toSec();
00500 move_arm_stats_.smoothing_time = (ros::Time::now()-smoothing_time).toSec();
00501 trajectory_out = res.trajectory;
00502 return true;
00503 }
00504 else
00505 {
00506 ROS_ERROR("Service call to filter trajectory failed.");
00507 return false;
00508 }
00509 }
00510
00511 int closestStateOnTrajectory(const trajectory_msgs::JointTrajectory &trajectory, const sensor_msgs::JointState &joint_state, unsigned int start, unsigned int end)
00512 {
00513 double dist = 0.0;
00514 int pos = -1;
00515
00516 std::map<std::string, double> current_state_map;
00517 std::map<std::string, bool> continuous;
00518 for(unsigned int i = 0; i < joint_state.name.size(); i++) {
00519 current_state_map[joint_state.name[i]] = joint_state.position[i];
00520 }
00521
00522 for(unsigned int j = 0; j < trajectory.joint_names.size(); j++) {
00523 std::string name = trajectory.joint_names[j];
00524 boost::shared_ptr<const urdf::Joint> joint = robot_model_.getJoint(name);
00525 if (joint.get() == NULL)
00526 {
00527 ROS_ERROR("Joint name %s not found in urdf model", name.c_str());
00528 return false;
00529 }
00530 if (joint->type == urdf::Joint::CONTINUOUS) {
00531 continuous[name] = true;
00532 } else {
00533 continuous[name] = false;
00534 }
00535
00536 }
00537
00538 for (unsigned int i = start ; i <= end ; ++i)
00539 {
00540 double d = 0.0;
00541 for(unsigned int j = 0; j < trajectory.joint_names.size(); j++) {
00542 double diff;
00543 if(!continuous[trajectory.joint_names[j]]) {
00544 diff = fabs(trajectory.points[i].positions[j] - current_state_map[trajectory.joint_names[j]]);
00545 } else {
00546 diff = angles::shortest_angular_distance(trajectory.points[i].positions[j],current_state_map[trajectory.joint_names[j]]);
00547 }
00548 d += diff * diff;
00549 }
00550
00551 if (pos < 0 || d < dist)
00552 {
00553 pos = i;
00554 dist = d;
00555 }
00556 }
00557
00558
00559
00560
00561
00562
00563
00564
00565
00566
00567 return pos;
00568 }
00569
00570 bool removeCompletedTrajectory(const trajectory_msgs::JointTrajectory &trajectory_in,
00571 trajectory_msgs::JointTrajectory &trajectory_out, bool zero_vel_acc)
00572 {
00573
00574 trajectory_out.header = trajectory_in.header;
00575 trajectory_out.header.stamp = ros::Time::now();
00576 trajectory_out.joint_names = trajectory_in.joint_names;
00577 trajectory_out.points.clear();
00578
00579 if(trajectory_in.points.empty())
00580 {
00581 ROS_WARN("No points in input trajectory");
00582 return true;
00583 }
00584
00585 motion_planning_msgs::RobotState state;
00586 if(!getRobotState(state)) {
00587 return false;
00588 }
00589
00590 sensor_msgs::JointState current_state = state.joint_state;
00591
00592 int current_position_index = 0;
00593
00594 current_position_index = closestStateOnTrajectory(trajectory_in, current_state, current_position_index, trajectory_in.points.size() - 1);
00595 if (current_position_index < 0)
00596 {
00597 ROS_ERROR("Unable to identify current state in trajectory");
00598 return false;
00599 } else {
00600 ROS_INFO_STREAM("Closest state is " << current_position_index << " of " << trajectory_in.points.size());
00601 }
00602
00603
00604 for(unsigned int i = current_position_index+1; i < trajectory_in.points.size(); ++i)
00605 {
00606 trajectory_out.points.push_back(trajectory_in.points[i]);
00607 }
00608
00609 if(trajectory_out.points.empty())
00610 {
00611 ROS_WARN("No points in output trajectory");
00612 return false;
00613 }
00614
00615 ros::Duration first_time = trajectory_out.points[0].time_from_start;
00616
00617 if(first_time < ros::Duration(.1)) {
00618 ROS_INFO("First time less than one-tenth of a second");
00619 first_time = ros::Duration(0.0);
00620 } else {
00621 first_time -= ros::Duration(.1);
00622 }
00623
00624 for(unsigned int i=0; i < trajectory_out.points.size(); ++i)
00625 {
00626 if(trajectory_out.points[i].time_from_start > first_time) {
00627 trajectory_out.points[i].time_from_start -= first_time;
00628 } else {
00629 ROS_INFO_STREAM("Not enough time in time from start for trajectory point " << i);
00630 }
00631 }
00632
00633
00634
00635 for(unsigned int i=0; i < trajectory_out.joint_names.size(); ++i) {
00636 for(unsigned int j=0; j < trajectory_out.points.size(); ++j) {
00637 trajectory_out.points[j].velocities[i] = 0;
00638 trajectory_out.points[j].accelerations[i] = 0;
00639 }
00640 }
00641
00642 return true;
00643
00644 }
00645
00646
00650
00654
00655 bool checkJointGoal(motion_planning_msgs::GetMotionPlan::Request &req, motion_planning_msgs::ArmNavigationErrorCodes& error_code)
00656 {
00657 ROS_DEBUG("Checking validity of joint goal");
00658 motion_planning_msgs::RobotState empty_state;
00659 empty_state.joint_state = motion_planning_msgs::jointConstraintsToJointState(req.motion_plan_request.goal_constraints.joint_constraints);
00660 if (isStateValid(empty_state,
00661 error_code,
00662 JOINT_LIMITS_TEST))
00663 {
00664 ROS_DEBUG("Joint goal passed joint limits/collision test");
00665 return true;
00666 }
00667 else
00668 {
00669 if(move_arm_parameters_.accept_invalid_goals)
00670 return true;
00671 else
00672 {
00673 return false;
00674 }
00675 }
00676 }
00677
00678
00680 bool checkTrajectoryReachesGoal(const trajectory_msgs::JointTrajectory& joint_traj, motion_planning_msgs::ArmNavigationErrorCodes& error_code)
00681 {
00682 motion_planning_msgs::RobotState last_state_in_trajectory;
00683 last_state_in_trajectory.joint_state.header = joint_traj.header;
00684 last_state_in_trajectory.joint_state.position = joint_traj.points.back().positions;
00685 last_state_in_trajectory.joint_state.name = joint_traj.joint_names;
00686 if(!isStateValidAtGoal(last_state_in_trajectory, error_code))
00687 {
00688 if(error_code.val == error_code.GOAL_CONSTRAINTS_VIOLATED) {
00689 ROS_WARN("Checked trajectory does not seem to result in satisfying goal constraints");
00690 } else if(error_code.val == error_code.COLLISION_CONSTRAINTS_VIOLATED) {
00691 ROS_WARN("Checked trajectory seems to end in collision");
00692 } else {
00693 ROS_WARN_STREAM("Some other problem with planner path " << error_code.val);
00694 }
00695 return false;
00696 }
00697 return true;
00698 }
00699
00700 bool isEnvironmentSafe()
00701 {
00702 planning_environment_msgs::GetEnvironmentSafety::Request req;
00703 planning_environment_msgs::GetEnvironmentSafety::Response res;
00704 if(check_env_safe_client_.call(req,res))
00705 {
00706 if(res.error_code.val == res.error_code.SUCCESS)
00707 return true;
00708 else
00709 return false;
00710 }
00711 else
00712 {
00713 ROS_ERROR("Service call to environment server failed on %s",check_env_safe_client_.getService().c_str());
00714 return false;
00715 }
00716 }
00717 bool isTrajectoryValid(const trajectory_msgs::JointTrajectory &traj, motion_planning_msgs::ArmNavigationErrorCodes& error_code)
00718 {
00719 planning_environment_msgs::GetJointTrajectoryValidity::Request req;
00720 planning_environment_msgs::GetJointTrajectoryValidity::Response res;
00721
00722 ROS_DEBUG("Received trajectory has %d points with %d joints",
00723 (int) traj.points.size(),
00724 (int)traj.joint_names.size());
00725
00726 req.trajectory = traj;
00727 if(!getRobotState(req.robot_state))
00728 {
00729 ROS_ERROR("Could not get robot state");
00730 error_code.val = error_code.ROBOT_STATE_STALE;
00731 return false;
00732 }
00733
00734 req.check_path_constraints = true;
00735 req.check_collisions = true;
00736 req.allowed_contacts = original_request_.motion_plan_request.allowed_contacts;
00737 req.ordered_collision_operations = original_request_.motion_plan_request.ordered_collision_operations;
00738 req.path_constraints = original_request_.motion_plan_request.path_constraints;
00739 req.goal_constraints = original_request_.motion_plan_request.goal_constraints;
00740 req.link_padding = original_request_.motion_plan_request.link_padding;
00741 if(check_plan_validity_client_.call(req,res))
00742 {
00743 error_code = res.error_code;
00744 if(res.error_code.val == res.error_code.SUCCESS)
00745 return true;
00746 else
00747 {
00748 move_arm_action_result_.error_code = res.error_code;
00749 move_arm_action_result_.contacts = res.contacts;
00750 ROS_ERROR("Trajectory invalid");
00751 return false;
00752 }
00753 }
00754 else
00755 {
00756 ROS_ERROR("Service call to check trajectory validity failed on %s",check_plan_validity_client_.getService().c_str());
00757 error_code.val = error_code.COLLISION_CHECKING_UNAVAILABLE;
00758 return false;
00759 }
00760 }
00761 bool isExecutionSafe()
00762 {
00763 planning_environment_msgs::GetJointTrajectoryValidity::Request req;
00764 planning_environment_msgs::GetJointTrajectoryValidity::Response res;
00765
00766
00767 discretizeTrajectory(current_trajectory_,req.trajectory,trajectory_discretization_);
00768 if(!getRobotState(req.robot_state))
00769 return false;
00770 req.check_path_constraints = true;
00771 req.check_collisions = true;
00772 req.allowed_contacts = original_request_.motion_plan_request.allowed_contacts;
00773 req.ordered_collision_operations = original_request_.motion_plan_request.ordered_collision_operations;
00774 req.path_constraints = original_request_.motion_plan_request.path_constraints;
00775 req.goal_constraints = original_request_.motion_plan_request.goal_constraints;
00776 req.link_padding = original_request_.motion_plan_request.link_padding;
00777 if(check_execution_safe_client_.call(req,res))
00778 {
00779 if(res.error_code.val == res.error_code.SUCCESS)
00780 return true;
00781 else
00782 {
00783 move_arm_action_result_.error_code = res.error_code;
00784 move_arm_action_result_.contacts = res.contacts;
00785 return false;
00786 }
00787 }
00788 else
00789 {
00790 ROS_ERROR("Service call to check execution safety failed on %s",
00791 check_execution_safe_client_.getService().c_str());
00792 return false;
00793 }
00794 }
00795 bool isStateValidAtGoal(const motion_planning_msgs::RobotState& state,
00796 motion_planning_msgs::ArmNavigationErrorCodes& error_code)
00797 {
00798 planning_environment_msgs::GetStateValidity::Request req;
00799 planning_environment_msgs::GetStateValidity::Response res;
00800 req.robot_state = state;
00801 req.check_goal_constraints = true;
00802 req.check_collisions = true;
00803 planning_environment_msgs::generateDisableAllowedCollisionsWithExclusions(all_link_names_,
00804 group_link_names_,
00805 req.ordered_collision_operations.collision_operations);
00806 req.ordered_collision_operations.collision_operations.insert(req.ordered_collision_operations.collision_operations.end(),
00807 original_request_.motion_plan_request.ordered_collision_operations.collision_operations.begin(),
00808 original_request_.motion_plan_request.ordered_collision_operations.collision_operations.end());
00809 req.allowed_contacts = original_request_.motion_plan_request.allowed_contacts;
00810 req.path_constraints = original_request_.motion_plan_request.path_constraints;
00811 req.goal_constraints = original_request_.motion_plan_request.goal_constraints;
00812 req.link_padding = original_request_.motion_plan_request.link_padding;
00813 if(check_state_validity_client_.call(req,res))
00814 {
00815 error_code = res.error_code;
00816 if(res.error_code.val == res.error_code.SUCCESS)
00817 return true;
00818 else
00819 return false;
00820 }
00821 else
00822 {
00823 ROS_ERROR("Service call to check goal validity failed %s",
00824 check_state_validity_client_.getService().c_str());
00825 return false;
00826 }
00827 }
00828 bool isStateValid(const motion_planning_msgs::RobotState& state,
00829 motion_planning_msgs::ArmNavigationErrorCodes& error_code,
00830 int flag=0)
00831 {
00832 planning_environment_msgs::GetStateValidity::Request req;
00833 planning_environment_msgs::GetStateValidity::Response res;
00834 req.robot_state = state;
00835 addCheckFlags(req,COLLISION_TEST | flag);
00836 req.allowed_contacts = original_request_.motion_plan_request.allowed_contacts;
00837 planning_environment_msgs::generateDisableAllowedCollisionsWithExclusions(all_link_names_,
00838 group_link_names_,
00839 req.ordered_collision_operations.collision_operations);
00840 req.ordered_collision_operations.collision_operations.insert(req.ordered_collision_operations.collision_operations.end(),
00841 original_request_.motion_plan_request.ordered_collision_operations.collision_operations.begin(),
00842 original_request_.motion_plan_request.ordered_collision_operations.collision_operations.end());
00843
00844
00845
00846
00847
00848 req.path_constraints = original_request_.motion_plan_request.path_constraints;
00849 req.goal_constraints = original_request_.motion_plan_request.goal_constraints;
00850 req.link_padding = original_request_.motion_plan_request.link_padding;
00851 if(check_state_validity_client_.call(req,res))
00852 {
00853 error_code = res.error_code;
00854 if(res.error_code.val == res.error_code.SUCCESS)
00855 return true;
00856 else
00857 {
00858 move_arm_action_result_.contacts = res.contacts;
00859 return false;
00860 }
00861 }
00862 else
00863 {
00864 ROS_ERROR("Service call to check state validity failed on %s",check_state_validity_client_.getService().c_str());
00865 return false;
00866 }
00867 }
00868 void discretizeTrajectory(const trajectory_msgs::JointTrajectory &trajectory,
00869 trajectory_msgs::JointTrajectory &trajectory_out,
00870 const double &trajectory_discretization)
00871 {
00872 trajectory_out.joint_names = trajectory.joint_names;
00873 for(unsigned int i=1; i < trajectory.points.size(); i++)
00874 {
00875 double diff = 0.0;
00876 for(unsigned int j=0; j < trajectory.points[i].positions.size(); j++)
00877 {
00878 double start = trajectory.points[i-1].positions[j];
00879 double end = trajectory.points[i].positions[j];
00880 if(fabs(end-start) > diff)
00881 diff = fabs(end-start);
00882 }
00883 int num_intervals =(int) (diff/trajectory_discretization+1.0);
00884
00885 for(unsigned int k=0; k < (unsigned int) num_intervals; k++)
00886 {
00887 trajectory_msgs::JointTrajectoryPoint point;
00888 for(unsigned int j=0; j < trajectory.points[i].positions.size(); j++)
00889 {
00890 double start = trajectory.points[i-1].positions[j];
00891 double end = trajectory.points[i].positions[j];
00892 point.positions.push_back(start + (end-start)*k/num_intervals);
00893 }
00894 point.time_from_start = ros::Duration(trajectory.points[i].time_from_start.toSec() + k* (trajectory.points[i].time_from_start - trajectory.points[i-1].time_from_start).toSec()/num_intervals);
00895 trajectory_out.points.push_back(point);
00896 }
00897 }
00898 trajectory_out.points.push_back(trajectory.points.back());
00899 }
00903
00907 bool isPoseGoal(motion_planning_msgs::GetMotionPlan::Request &req)
00908 {
00909 if (req.motion_plan_request.goal_constraints.joint_constraints.empty() &&
00910 req.motion_plan_request.goal_constraints.position_constraints.size() == 1 &&
00911 req.motion_plan_request.goal_constraints.orientation_constraints.size() == 1)
00912 return true;
00913 else
00914 return false;
00915 }
00916 bool isJointGoal(motion_planning_msgs::GetMotionPlan::Request &req)
00917 {
00918 if (req.motion_plan_request.goal_constraints.position_constraints.empty() &&
00919 req.motion_plan_request.goal_constraints.orientation_constraints.empty() &&
00920 !req.motion_plan_request.goal_constraints.joint_constraints.empty())
00921 return true;
00922 else
00923 return false;
00924 }
00925 void addCheckFlags(planning_environment_msgs::GetStateValidity::Request &req,
00926 const int &flag)
00927 {
00928 if(flag & COLLISION_TEST)
00929 req.check_collisions = true;
00930 if(flag & PATH_CONSTRAINTS_TEST)
00931 req.check_path_constraints = true;
00932 if(flag & GOAL_CONSTRAINTS_TEST)
00933 req.check_goal_constraints = true;
00934 if(flag & JOINT_LIMITS_TEST)
00935 req.check_joint_limits = true;
00936 }
00937 bool getRobotState(motion_planning_msgs::RobotState &robot_state)
00938 {
00939 planning_environment_msgs::GetRobotState::Request req;
00940 planning_environment_msgs::GetRobotState::Response res;
00941 if(get_state_client_.call(req,res))
00942 {
00943 robot_state = res.robot_state;
00944 return true;
00945 }
00946 else
00947 {
00948 ROS_ERROR("Service call to get robot state failed on %s",
00949 get_state_client_.getService().c_str());
00950 return false;
00951 }
00952 }
00956
00960 void moveArmGoalToPlannerRequest(const move_arm_msgs::MoveArmGoalConstPtr& goal,
00961 motion_planning_msgs::GetMotionPlan::Request &req)
00962 {
00963 req.motion_plan_request.workspace_parameters.workspace_region_pose.header.stamp = ros::Time::now();
00964 req.motion_plan_request = goal->motion_plan_request;
00965
00966 move_arm_parameters_.accept_partial_plans = goal->accept_partial_plans;
00967 move_arm_parameters_.accept_invalid_goals = goal->accept_invalid_goals;
00968 move_arm_parameters_.disable_ik = goal->disable_ik;
00969 move_arm_parameters_.disable_collision_monitoring = goal->disable_collision_monitoring;
00970 move_arm_parameters_.allowed_planning_time = goal->motion_plan_request.allowed_planning_time.toSec();
00971 move_arm_parameters_.planner_service_name = goal->planner_service_name;
00972 visualizeAllowedContactRegions(req.motion_plan_request.allowed_contacts);
00973 ROS_INFO("Move arm: %d allowed contact regions",(int)req.motion_plan_request.allowed_contacts.size());
00974 for(unsigned int i=0; i < req.motion_plan_request.allowed_contacts.size(); i++)
00975 {
00976 ROS_INFO("Position : (%f,%f,%f)",req.motion_plan_request.allowed_contacts[i].pose_stamped.pose.position.x,req.motion_plan_request.allowed_contacts[i].pose_stamped.pose.position.y,req.motion_plan_request.allowed_contacts[i].pose_stamped.pose.position.z);
00977 ROS_INFO("Frame id : %s",req.motion_plan_request.allowed_contacts[i].pose_stamped.header.frame_id.c_str());
00978 ROS_INFO("Depth : %f",req.motion_plan_request.allowed_contacts[i].penetration_depth);
00979 ROS_INFO("Link : %s",req.motion_plan_request.allowed_contacts[i].link_names[0].c_str());
00980 ROS_INFO(" ");
00981 }
00982 }
00983 bool doPrePlanningChecks(motion_planning_msgs::GetMotionPlan::Request &req,
00984 motion_planning_msgs::GetMotionPlan::Response &res)
00985 {
00986
00987 motion_planning_msgs::RobotState empty_state;
00988 motion_planning_msgs::ArmNavigationErrorCodes error_code;
00989 if(!isStateValid(empty_state, error_code) && !move_arm_parameters_.disable_collision_monitoring){
00990 if(error_code.val == error_code.COLLISION_CONSTRAINTS_VIOLATED) {
00991 move_arm_action_result_.error_code.val = error_code.START_STATE_IN_COLLISION;
00992 ROS_ERROR("Starting state is in collision, can't plan");
00993 } else if (error_code.val == error_code.PATH_CONSTRAINTS_VIOLATED) {
00994 move_arm_action_result_.error_code.val = error_code.START_STATE_VIOLATES_PATH_CONSTRAINTS;
00995 ROS_ERROR("Starting state violated path constraints, can't plan");;
00996 } else if (error_code.val == error_code.JOINT_LIMITS_VIOLATED) {
00997 move_arm_action_result_.error_code.val = move_arm_action_result_.error_code.JOINT_LIMITS_VIOLATED;;
00998 ROS_ERROR("Start state violates joint limits, can't plan.");
00999 }
01000 action_server_->setAborted(move_arm_action_result_);
01001 return false;
01002 }
01003
01004 if (!move_arm_parameters_.disable_ik && isPoseGoal(req))
01005 {
01006 ROS_INFO("Planning to a pose goal");
01007 if(!convertPoseGoalToJointGoal(req))
01008 {
01009 action_server_->setAborted(move_arm_action_result_);
01010 return false;
01011 }
01012 }
01013
01014 if(!checkJointGoal(req, error_code))
01015 {
01016 if(error_code.val == error_code.JOINT_LIMITS_VIOLATED) {
01017 ROS_ERROR("Will not plan to requested joint goal since it violates joint limits constraints");
01018 move_arm_action_result_.error_code.val = move_arm_action_result_.error_code.JOINT_LIMITS_VIOLATED;
01019 } else if(error_code.val == error_code.COLLISION_CONSTRAINTS_VIOLATED) {
01020 ROS_ERROR("Will not plan to requested joint goal since it is in collision");
01021 move_arm_action_result_.error_code.val = move_arm_action_result_.error_code.GOAL_IN_COLLISION;
01022 } else if(error_code.val == error_code.PATH_CONSTRAINTS_VIOLATED) {
01023 ROS_ERROR("Will not plan to requested joint goal since it violates path constraints");
01024 move_arm_action_result_.error_code.val = move_arm_action_result_.error_code.GOAL_VIOLATES_PATH_CONSTRAINTS;
01025 }
01026 action_server_->setAborted(move_arm_action_result_);
01027 return false;
01028 }
01029 return true;
01030 }
01031 bool createPlan(motion_planning_msgs::GetMotionPlan::Request &req,
01032 motion_planning_msgs::GetMotionPlan::Response &res)
01033 {
01034 if (!isEnvironmentSafe())
01035 {
01036 ROS_WARN("Environment is not safe. Will not issue request for planning");
01037 return false;
01038 }
01039 if(!getRobotState(req.motion_plan_request.start_state))
01040 return false;
01041
01042 ros::ServiceClient planning_client = root_handle_.serviceClient<motion_planning_msgs::GetMotionPlan>(move_arm_parameters_.planner_service_name);
01043 move_arm_stats_.planner_service_name = move_arm_parameters_.planner_service_name;
01044 ROS_DEBUG("Issuing request for motion plan");
01045
01046 if (planning_client.call(req, res))
01047 {
01048 if (res.trajectory.joint_trajectory.points.empty())
01049 {
01050 ROS_WARN("Motion planner was unable to plan a path to goal");
01051 return false;
01052 }
01053 ROS_INFO("Motion planning succeeded");
01054 motion_planning_msgs::ArmNavigationErrorCodes error_code;
01055 if(!checkTrajectoryReachesGoal(res.trajectory.joint_trajectory, error_code)) {
01056 if(move_arm_parameters_.accept_partial_plans)
01057 {
01058 ROS_WARN("Returned path from planner does not reach a valid goal");
01059 return true;
01060 }
01061 else
01062 {
01063 ROS_ERROR("Returned path from planner does not satisfy goal");
01064 return false;
01065 }
01066 }
01067 return true;
01068 }
01069 else
01070 {
01071 ROS_ERROR("Motion planning service failed on %s",planning_client.getService().c_str());
01072 return false;
01073 }
01074 }
01078
01082 bool initializeControllerInterface()
01083 {
01084 std::string controller_action_name;
01085 private_handle_.param<std::string>("controller_action_name", controller_action_name, "action");
01086 ROS_INFO("Connecting to controller using action: %s",controller_action_name.c_str());
01087 controller_action_client_ = new JointExecutorActionClient(controller_action_name);
01088 if(!controller_action_client_) {
01089 ROS_ERROR("Controller action client hasn't been initialized yet");
01090 return false;
01091 }
01092 while(!controller_action_client_->waitForActionServerToStart(ros::Duration(1.0))){
01093 ROS_INFO("Waiting for the joint_trajectory_action server to come up.");
01094 if(!root_handle_.ok()) {
01095 return false;
01096 }
01097 }
01098 ROS_INFO("Connected to the controller");
01099 return true;
01100 }
01101
01102 void stopMonitoring()
01103 {
01104 if(using_head_monitor_ && head_monitor_client_->getState().state_ == actionlib::SimpleClientGoalState::ACTIVE)
01105 {
01106 head_monitor_client_->cancelGoal();
01107 head_monitor_client_->waitForResult(ros::Duration(0.1));
01108 }
01109 }
01110
01111 bool stopTrajectory()
01112 {
01113 stopMonitoring();
01114
01115 if (controller_goal_handle_.isExpired())
01116 ROS_ERROR("Expired goal handle. controller_status = %d", controller_status_);
01117 else
01118 controller_goal_handle_.cancel();
01119 return true;
01120 }
01121 bool sendTrajectory(trajectory_msgs::JointTrajectory ¤t_trajectory)
01122 {
01123 current_trajectory.header.stamp = ros::Time::now()+ros::Duration(0.2);
01124
01125 if(using_head_monitor_ && head_monitor_time_offset_ > 0.5)
01126 current_trajectory.header.stamp += ros::Duration(head_monitor_time_offset_ - 0.5);
01127
01128 pr2_controllers_msgs::JointTrajectoryGoal goal;
01129 goal.trajectory = current_trajectory;
01130
01131 ROS_INFO("Sending trajectory with %d points and timestamp: %f",(int)goal.trajectory.points.size(),goal.trajectory.header.stamp.toSec());
01132 for(unsigned int i=0; i < goal.trajectory.joint_names.size(); i++)
01133 ROS_INFO("Joint: %d name: %s",i,goal.trajectory.joint_names[i].c_str());
01134
01135
01136
01137
01138
01139
01140
01141
01142
01143
01144
01145
01146
01147
01148
01149
01150
01151
01152
01153
01154 controller_goal_handle_ = controller_action_client_->sendGoal(goal,boost::bind(&MoveArm::controllerTransitionCallback, this, _1));
01155
01156 controller_status_ = QUEUED;
01157
01158 return true;
01159 }
01160
01161 void controllerTransitionCallback(JointExecutorActionClient::GoalHandle gh)
01162 {
01163 if(gh != controller_goal_handle_)
01164 return;
01165 actionlib::CommState comm_state = gh.getCommState();
01166 switch( comm_state.state_)
01167 {
01168 case actionlib::CommState::WAITING_FOR_GOAL_ACK:
01169 case actionlib::CommState::PENDING:
01170 case actionlib::CommState::RECALLING:
01171 controller_status_ = QUEUED;
01172 return;
01173 case actionlib:: CommState::ACTIVE:
01174 case actionlib::CommState::PREEMPTING:
01175 controller_status_ = ACTIVE;
01176 return;
01177 case actionlib::CommState::DONE:
01178 {
01179 switch(gh.getTerminalState().state_)
01180 {
01181 case actionlib::TerminalState::RECALLED:
01182 case actionlib::TerminalState::REJECTED:
01183 case actionlib::TerminalState::PREEMPTED:
01184 case actionlib::TerminalState::ABORTED:
01185 case actionlib::TerminalState::LOST:
01186 {
01187 ROS_INFO("Trajectory controller status came back as failed");
01188 controller_status_ = FAILED;
01189 controller_goal_handle_.reset();
01190 return;
01191 }
01192 case actionlib::TerminalState::SUCCEEDED:
01193 {
01194 controller_goal_handle_.reset();
01195 controller_status_ = SUCCESS;
01196 return;
01197 }
01198 default:
01199 ROS_ERROR("Unknown terminal state [%u]. This is a bug in ActionClient", gh.getTerminalState().state_);
01200 }
01201 }
01202 default:
01203 break;
01204 }
01205 }
01206 bool isControllerDone(motion_planning_msgs::ArmNavigationErrorCodes& error_code)
01207 {
01208 if (controller_status_ == SUCCESS)
01209 {
01210 error_code.val = error_code.SUCCESS;
01211 return true;
01212 } else if(controller_status_ == FAILED)
01213 {
01214 error_code.val = error_code.TRAJECTORY_CONTROLLER_FAILED;
01215 return true;
01216 } else {
01217 return false;
01218 }
01219 }
01220 void fillTrajectoryMsg(const trajectory_msgs::JointTrajectory &trajectory_in,
01221 trajectory_msgs::JointTrajectory &trajectory_out)
01222 {
01223 trajectory_out = trajectory_in;
01224 if(trajectory_in.points.empty())
01225 {
01226 ROS_WARN("No points in trajectory");
01227 return;
01228 }
01229
01230 double d = 0.0;
01231
01232 motion_planning_msgs::RobotState state;
01233 if(!getRobotState(state)) {
01234 return;
01235 }
01236
01237 std::map<std::string, double> val_map;
01238 for(unsigned int i = 0; i < state.joint_state.name.size(); i++) {
01239 val_map[state.joint_state.name[i]] = state.joint_state.position[i];
01240 }
01241
01242 sensor_msgs::JointState current;
01243 current.name = trajectory_out.joint_names;
01244 current.position.resize(trajectory_out.joint_names.size());
01245 for(unsigned int i = 0; i < trajectory_out.joint_names.size(); i++) {
01246 current.position[i] = val_map[trajectory_out.joint_names[i]];
01247 }
01248 std::map<std::string, bool> continuous;
01249 for(unsigned int j = 0; j < trajectory_in.joint_names.size(); j++) {
01250 std::string name = trajectory_in.joint_names[j];
01251 boost::shared_ptr<const urdf::Joint> joint = robot_model_.getJoint(name);
01252 if (joint.get() == NULL)
01253 {
01254 ROS_ERROR("Joint name %s not found in urdf model", name.c_str());
01255 return;
01256 }
01257 if (joint->type == urdf::Joint::CONTINUOUS) {
01258 continuous[name] = true;
01259 } else {
01260 continuous[name] = false;
01261 }
01262 }
01263 for (unsigned int i = 0 ; i < current.position.size() ; ++i)
01264 {
01265 double diff;
01266 if(!continuous[trajectory_in.joint_names[i]]) {
01267 diff = fabs(trajectory_in.points[0].positions[i] - val_map[trajectory_in.joint_names[i]]);
01268 } else {
01269 diff = angles::shortest_angular_distance(trajectory_in.points[0].positions[i],val_map[trajectory_in.joint_names[i]]);
01270 }
01271 d += diff * diff;
01272 }
01273 d = sqrt(d);
01274
01275 int include_first = (d > 0.1) ? 1 : 0;
01276 double offset = 0.0;
01277 trajectory_out.points.resize(trajectory_in.points.size() + include_first);
01278
01279 if (include_first)
01280 {
01281 ROS_INFO("Adding current state to front of trajectory");
01282 trajectory_out.points[0].positions = motion_planning_msgs::jointStateToJointTrajectoryPoint(current).positions;
01283 trajectory_out.points[0].time_from_start = ros::Duration(0.0);
01284 offset = 0.3 + d;
01285 }
01286 for (unsigned int i = 0 ; i < trajectory_in.points.size() ; ++i)
01287 {
01288 trajectory_out.points[i+include_first].time_from_start = trajectory_in.points[i].time_from_start;
01289 trajectory_out.points[i+include_first].positions = trajectory_in.points[i].positions;
01290 }
01291 trajectory_out.header.stamp = ros::Time::now();
01292 }
01296
01300 void resetStateMachine()
01301 {
01302 num_planning_attempts_ = 0;
01303 current_trajectory_.points.clear();
01304 current_trajectory_.joint_names.clear();
01305 state_ = PLANNING;
01306 }
01307 bool executeCycle(motion_planning_msgs::GetMotionPlan::Request &req)
01308 {
01309 motion_planning_msgs::GetMotionPlan::Response res;
01310
01311 switch(state_)
01312 {
01313 case PLANNING:
01314 {
01315 move_arm_action_feedback_.state = "planning";
01316 move_arm_action_feedback_.time_to_completion = ros::Duration(req.motion_plan_request.allowed_planning_time);
01317 action_server_->publishFeedback(move_arm_action_feedback_);
01318
01319 if(!doPrePlanningChecks(req,res))
01320 return true;
01321
01322 visualizeJointGoal(req);
01323 motion_planning_msgs::RobotState empty_state;
01324 motion_planning_msgs::ArmNavigationErrorCodes error_code;
01325 if(isStateValidAtGoal(empty_state, error_code))
01326 {
01327 resetStateMachine();
01328 move_arm_action_result_.error_code.val = move_arm_action_result_.error_code.SUCCESS;
01329 action_server_->setSucceeded(move_arm_action_result_);
01330 ROS_INFO("Apparently we reached the goal without planning");
01331 return true;
01332 }
01333 ros::Time planning_time = ros::Time::now();
01334 if(createPlan(req,res))
01335 {
01336 move_arm_stats_.planning_time = (ros::Time::now()-planning_time).toSec();
01337 ROS_DEBUG("createPlan succeeded");
01338 if(!isTrajectoryValid(res.trajectory.joint_trajectory, error_code))
01339 {
01340 if(error_code.val == error_code.COLLISION_CONSTRAINTS_VIOLATED) {
01341 ROS_WARN("Planner trajectory collides");
01342 } else if (error_code.val == error_code.PATH_CONSTRAINTS_VIOLATED) {
01343 ROS_WARN("Planner trajectory violates path constraints");
01344 } else if (error_code.val == error_code.JOINT_LIMITS_VIOLATED) {
01345 ROS_WARN("Planner trajectory violates joint limits");
01346 } else if (error_code.val == error_code.GOAL_CONSTRAINTS_VIOLATED) {
01347 ROS_WARN("Planner trajectory doesn't reach goal");
01348 }
01349 num_planning_attempts_++;
01350 if(num_planning_attempts_ > req.motion_plan_request.num_planning_attempts)
01351 {
01352 resetStateMachine();
01353 action_server_->setAborted(move_arm_action_result_);
01354 return true;
01355 }
01356 }
01357 else{
01358 ROS_DEBUG("Trajectory validity check was successful");
01359
01360 current_trajectory_ = res.trajectory.joint_trajectory;
01361 visualizePlan(current_trajectory_);
01362
01363 state_ = START_CONTROL;
01364 ROS_INFO("Done planning. Transitioning to control");
01365 }
01366 }
01367 else if(action_server_->isActive())
01368 {
01369 num_planning_attempts_++;
01370 if(num_planning_attempts_ > req.motion_plan_request.num_planning_attempts)
01371 {
01372 resetStateMachine();
01373 action_server_->setAborted(move_arm_action_result_);
01374 return true;
01375 }
01376 }
01377 else
01378 {
01379 ROS_ERROR("create plan failed");
01380 }
01381 break;
01382 }
01383 case START_CONTROL:
01384 {
01385 move_arm_action_feedback_.state = "start_control";
01386 move_arm_action_feedback_.time_to_completion = ros::Duration(1.0/move_arm_frequency_);
01387 action_server_->publishFeedback(move_arm_action_feedback_);
01388 ROS_DEBUG("Filtering Trajectory");
01389 trajectory_msgs::JointTrajectory filtered_trajectory;
01390 if(filterTrajectory(current_trajectory_, filtered_trajectory))
01391 {
01392 motion_planning_msgs::ArmNavigationErrorCodes error_code;
01393 if(!checkTrajectoryReachesGoal(filtered_trajectory, error_code)) {
01394 ROS_WARN("Filtered trajectory does not satisfy goal. Will replan");
01395 state_ = PLANNING;
01396 break;
01397
01398
01399
01400 }
01401 if(!isTrajectoryValid(filtered_trajectory, error_code))
01402 {
01403 if(error_code.val == error_code.COLLISION_CONSTRAINTS_VIOLATED) {
01404 ROS_WARN("Filtered trajectory collides");
01405 } else if (error_code.val == error_code.PATH_CONSTRAINTS_VIOLATED) {
01406 ROS_WARN("Filtered trajectory violates path constraints");
01407 } else if (error_code.val == error_code.JOINT_LIMITS_VIOLATED) {
01408 ROS_WARN("Filtered trajectory violates joint limits");
01409 } else if (error_code.val == error_code.GOAL_CONSTRAINTS_VIOLATED) {
01410 ROS_WARN("Filtered trajectory doesn't reach goal");
01411 }
01412 ROS_ERROR("Move arm will abort this goal. Will replan");
01413 state_ = PLANNING;
01414
01415
01416 break;
01417
01418 }
01419 else{
01420 ROS_DEBUG("Trajectory validity check was successful");
01421 }
01422 current_trajectory_ = filtered_trajectory;
01423 }
01424
01425 if(using_head_monitor_)
01426 {
01427 move_arm_head_monitor::HeadLookGoal look_goal;
01428
01429 look_goal.target_time = ros::Time::now() + ros::Duration(0.01);
01430 look_goal.target_link = head_monitor_link_;
01431 look_goal.target_x = head_monitor_link_x_;
01432 look_goal.target_y = head_monitor_link_y_;
01433 look_goal.target_z = head_monitor_link_z_;
01434
01435 ROS_DEBUG("Looking at target link before starting trajectory");
01436
01437 if(head_look_client_->sendGoalAndWait(look_goal, ros::Duration(4.0), ros::Duration(1.0)) != actionlib::SimpleClientGoalState::SUCCEEDED)
01438 ROS_WARN("Head look didn't succeed before timeout, starting anyway");
01439 }
01440
01441
01442 ROS_DEBUG("Sending trajectory");
01443 move_arm_stats_.time_to_execution = (ros::Time::now() - ros::Time(move_arm_stats_.time_to_execution)).toSec();
01444 if(sendTrajectory(current_trajectory_))
01445 {
01446 state_ = MONITOR;
01447
01448 if(using_head_monitor_)
01449 {
01450 move_arm_head_monitor::HeadMonitorGoal monitor_goal;
01451
01452 monitor_goal.stop_time = current_trajectory_.header.stamp + (current_trajectory_.points.end()-1)->time_from_start;
01453 monitor_goal.max_frequency = head_monitor_max_frequency_;
01454 monitor_goal.time_offset = ros::Duration(head_monitor_time_offset_);
01455 monitor_goal.target_link = head_monitor_link_;
01456 monitor_goal.target_x = head_monitor_link_x_;
01457 monitor_goal.target_y = head_monitor_link_y_;
01458 monitor_goal.target_z = head_monitor_link_z_;
01459
01460 ROS_DEBUG("Starting head monitoring");
01461 head_monitor_client_->sendGoal(monitor_goal);
01462 }
01463
01464 }
01465 else
01466 {
01467 resetStateMachine();
01468 action_server_->setAborted(move_arm_action_result_);
01469 return true;
01470 }
01471 break;
01472 }
01473 case MONITOR:
01474 {
01475 move_arm_action_feedback_.state = "monitor";
01476 move_arm_action_feedback_.time_to_completion = current_trajectory_.points.back().time_from_start;
01477 action_server_->publishFeedback(move_arm_action_feedback_);
01478 ROS_DEBUG("Start to monitor");
01479 motion_planning_msgs::ArmNavigationErrorCodes controller_error_code;
01480 if(isControllerDone(controller_error_code))
01481 {
01482 stopMonitoring();
01483 move_arm_stats_.time_to_result = (ros::Time::now()-ros::Time(move_arm_stats_.time_to_result)).toSec();
01484
01485 motion_planning_msgs::RobotState empty_state;
01486 motion_planning_msgs::ArmNavigationErrorCodes state_error_code;
01487 if(isStateValidAtGoal(empty_state, state_error_code))
01488 {
01489 resetStateMachine();
01490 move_arm_action_result_.error_code.val = move_arm_action_result_.error_code.SUCCESS;
01491 action_server_->setSucceeded(move_arm_action_result_);
01492 if(controller_error_code.val == controller_error_code.TRAJECTORY_CONTROLLER_FAILED) {
01493 ROS_INFO("Trajectory controller failed but we seem to be at goal");
01494 } else {
01495 ROS_INFO("Reached goal");
01496 }
01497 return true;
01498 }
01499 else
01500 {
01501 if(state_error_code.val == state_error_code.COLLISION_CONSTRAINTS_VIOLATED) {
01502 move_arm_action_result_.error_code.val = state_error_code.START_STATE_IN_COLLISION;
01503 ROS_WARN("Though trajectory is done current state is in collision");
01504 } else if (state_error_code.val == state_error_code.PATH_CONSTRAINTS_VIOLATED) {
01505 ROS_WARN("Though trajectory is done current state violates path constraints");
01506 } else if (state_error_code.val == state_error_code.JOINT_LIMITS_VIOLATED) {
01507 ROS_WARN("Though trajectory is done current state violates joint limits");
01508 } else if(state_error_code.val == state_error_code.GOAL_CONSTRAINTS_VIOLATED) {
01509 ROS_WARN("Though trajectory is done current state does not seem to be at goal");
01510 }
01511 resetStateMachine();
01512 action_server_->setAborted(move_arm_action_result_);
01513 state_ = PLANNING;
01514 break;
01515 }
01516 }
01517 if(!move_arm_parameters_.disable_collision_monitoring && action_server_->isActive())
01518 {
01519 ROS_DEBUG("Monitoring trajectory");
01520 if(ros::Time::now() - last_monitor_time_ <= trajectory_monitoring_duration_)
01521 {
01522 break;
01523 }
01524 last_monitor_time_ = ros::Time::now();
01525 if(!isExecutionSafe())
01526 {
01527 ROS_INFO("Stopping trajectory since it is unsafe");
01528
01529 if(using_head_monitor_)
01530 {
01531 pause_start_time_ = ros::Time::now();
01532 state_ = PAUSE;
01533 }
01534 else
01535 {
01536 state_ = PLANNING;
01537 }
01538
01539 stopTrajectory();
01540
01541 }
01542 }
01543 break;
01544 }
01545 case PAUSE:
01546 {
01547 if(isExecutionSafe())
01548 {
01549 ROS_INFO("Safe to resume, trying to remove completed trajectory section");
01550 trajectory_msgs::JointTrajectory shortened_trajectory;
01551 if(removeCompletedTrajectory(current_trajectory_, shortened_trajectory, true))
01552 {
01553 current_trajectory_ = shortened_trajectory;
01554 ROS_INFO("Shortening trajectory succeeded, starting control");
01555 state_ = START_CONTROL;
01556 }
01557 else
01558 {
01559 ROS_INFO("Shortening trajectory failed, going back to planning");
01560 state_ = PLANNING;
01561 }
01562 }
01563 else if(ros::Time::now() - pause_start_time_ > ros::Duration(pause_allowed_time_))
01564 {
01565 ROS_INFO("Pausing has timed out, trying to replan trajectory");
01566 state_ = PLANNING;
01567 }
01568
01569 break;
01570 }
01571 default:
01572 {
01573 ROS_INFO("Should not be here.");
01574 break;
01575 }
01576 }
01577 if(!action_server_->isActive())
01578 {
01579 ROS_DEBUG("Move arm no longer has an active goal");
01580 return true;
01581 }
01582 return false;
01583 }
01584 void execute(const move_arm_msgs::MoveArmGoalConstPtr& goal)
01585 {
01586 motion_planning_msgs::GetMotionPlan::Request req;
01587 moveArmGoalToPlannerRequest(goal,req);
01588 original_request_ = req;
01589 ROS_INFO("Received new goal");
01590 ros::Rate move_arm_rate(move_arm_frequency_);
01591 move_arm_action_result_.contacts.clear();
01592 move_arm_action_result_.error_code.val = 0;
01593 move_arm_stats_.time_to_execution = ros::Time::now().toSec();
01594 move_arm_stats_.time_to_result = ros::Time::now().toSec();
01595 while(private_handle_.ok())
01596 {
01597 if (action_server_->isPreemptRequested())
01598 {
01599 move_arm_stats_.preempted = true;
01600 if(publish_stats_)
01601 publishStats();
01602 move_arm_stats_.time_to_execution = ros::Time::now().toSec();
01603 move_arm_stats_.time_to_result = ros::Time::now().toSec();
01604 if(action_server_->isNewGoalAvailable())
01605 {
01606 move_arm_action_result_.contacts.clear();
01607 move_arm_action_result_.error_code.val = 0;
01608 moveArmGoalToPlannerRequest((action_server_->acceptNewGoal()),req);
01609 ROS_INFO("Received new goal, will preempt previous goal");
01610 original_request_ = req;
01611 if (controller_status_ == QUEUED || controller_status_ == ACTIVE)
01612 stopTrajectory();
01613 state_ = PLANNING;
01614 }
01615 else
01616 {
01617 ROS_INFO("The move arm action was preempted by the action client. Preempting this goal.");
01618 if (controller_status_ == QUEUED || controller_status_ == ACTIVE)
01619 stopTrajectory();
01620 resetStateMachine();
01621 action_server_->setPreempted();
01622 return;
01623 }
01624 }
01625
01626
01627 ros::WallTime start = ros::WallTime::now();
01628
01629
01630 bool done = executeCycle(req);
01631
01632
01633 if(done)
01634 {
01635 if(publish_stats_)
01636 publishStats();
01637 return;
01638 }
01639
01640 ros::WallDuration t_diff = ros::WallTime::now() - start;
01641 ROS_DEBUG("Full control cycle time: %.9f\n", t_diff.toSec());
01642
01643 move_arm_rate.sleep();
01644 }
01645
01646 ROS_INFO("Node was killed, aborting");
01647 action_server_->setAborted(move_arm_action_result_);
01648 }
01652
01656 void publishStats()
01657 {
01658 move_arm_stats_.error_code.val = move_arm_action_result_.error_code.val;
01659 move_arm_stats_.result = motion_planning_msgs::armNavigationErrorCodeToString(move_arm_action_result_.error_code);
01660 stats_publisher_.publish(move_arm_stats_);
01661
01662 move_arm_stats_.error_code.val = 0;
01663 move_arm_stats_.result = " ";
01664 move_arm_stats_.request_id++;
01665 move_arm_stats_.planning_time = -1.0;
01666 move_arm_stats_.smoothing_time = -1.0;
01667 move_arm_stats_.ik_time = -1.0;
01668 move_arm_stats_.time_to_execution = -1.0;
01669 move_arm_stats_.time_to_result = -1.0;
01670 move_arm_stats_.preempted = false;
01671 move_arm_stats_.num_replans = 0.0;
01672 move_arm_stats_.trajectory_duration = -1.0;
01673 }
01674
01675 void printTrajectory(const trajectory_msgs::JointTrajectory &trajectory)
01676 {
01677 for (unsigned int i = 0 ; i < trajectory.points.size() ; ++i)
01678 {
01679 std::stringstream ss;
01680 for (unsigned int j = 0 ; j < trajectory.points[i].positions.size() ; ++j)
01681 ss << trajectory.points[i].positions[j] << " ";
01682 ss << trajectory.points[i].time_from_start.toSec();
01683 ROS_DEBUG("%s", ss.str().c_str());
01684 }
01685 }
01686 void visualizeJointGoal(motion_planning_msgs::GetMotionPlan::Request &req)
01687 {
01688
01689
01690
01691
01692
01693 ROS_DEBUG("Displaying joint goal");
01694 motion_planning_msgs::DisplayTrajectory d_path;
01695 d_path.model_id = req.motion_plan_request.group_name;
01696 d_path.trajectory.joint_trajectory = motion_planning_msgs::jointConstraintsToJointTrajectory(req.motion_plan_request.goal_constraints.joint_constraints);
01697 if(!getRobotState(d_path.robot_state))
01698 {
01699 ROS_ERROR("Could not get robot state");
01700 }
01701 else
01702 {
01703 display_joint_goal_publisher_.publish(d_path);
01704 ROS_INFO("Displaying move arm joint goal.");
01705 }
01706 }
01707 void visualizeJointGoal(const trajectory_msgs::JointTrajectory &trajectory)
01708 {
01709 ROS_DEBUG("Displaying joint goal");
01710 motion_planning_msgs::DisplayTrajectory d_path;
01711 d_path.trajectory.joint_trajectory = trajectory;
01712 if(!getRobotState(d_path.robot_state))
01713 {
01714 ROS_ERROR("Could not get robot state");
01715 }
01716 else
01717 {
01718 display_joint_goal_publisher_.publish(d_path);
01719 ROS_INFO("Displaying move arm joint goal.");
01720 }
01721 }
01722 void visualizePlan(const trajectory_msgs::JointTrajectory &trajectory)
01723 {
01724 move_arm_action_feedback_.state = "visualizing plan";
01725 if(action_server_->isActive())
01726 action_server_->publishFeedback(move_arm_action_feedback_);
01727 motion_planning_msgs::DisplayTrajectory d_path;
01728 d_path.model_id = original_request_.motion_plan_request.group_name;
01729 d_path.trajectory.joint_trajectory = trajectory;
01730 if(!getRobotState(d_path.robot_state))
01731 ROS_ERROR("Could not get robot state");
01732 else
01733 display_path_publisher_.publish(d_path);
01734 }
01735 void visualizeAllowedContactRegions(const std::vector<motion_planning_msgs::AllowedContactSpecification> &allowed_contacts)
01736 {
01737 static int count = 0;
01738 visualization_msgs::MarkerArray mk;
01739 mk.markers.resize(allowed_contacts.size());
01740 for(unsigned int i=0; i < allowed_contacts.size(); i++)
01741 {
01742 bool valid_shape = true;
01743 mk.markers[i].header.stamp = ros::Time::now();
01744 mk.markers[i].header.frame_id = allowed_contacts[i].pose_stamped.header.frame_id;
01745 mk.markers[i].ns = "move_arm::"+allowed_contacts[i].name;
01746 mk.markers[i].id = count++;
01747 if(allowed_contacts[i].shape.type == geometric_shapes_msgs::Shape::SPHERE)
01748 {
01749 mk.markers[i].type = visualization_msgs::Marker::SPHERE;
01750 if(allowed_contacts[i].shape.dimensions.size() >= 1)
01751 mk.markers[i].scale.x = mk.markers[i].scale.y = mk.markers[i].scale.z = allowed_contacts[i].shape.dimensions[0];
01752 else
01753 valid_shape = false;
01754 }
01755 else if (allowed_contacts[i].shape.type == geometric_shapes_msgs::Shape::BOX)
01756 {
01757 mk.markers[i].type = visualization_msgs::Marker::CUBE;
01758 if(allowed_contacts[i].shape.dimensions.size() >= 3)
01759 {
01760 mk.markers[i].scale.x = allowed_contacts[i].shape.dimensions[0];
01761 mk.markers[i].scale.y = allowed_contacts[i].shape.dimensions[1];
01762 mk.markers[i].scale.z = allowed_contacts[i].shape.dimensions[2];
01763 }
01764 else
01765 valid_shape = false;
01766 }
01767 else if (allowed_contacts[i].shape.type == geometric_shapes_msgs::Shape::CYLINDER)
01768 {
01769 mk.markers[i].type = visualization_msgs::Marker::CYLINDER;
01770 if(allowed_contacts[i].shape.dimensions.size() >= 2)
01771 {
01772 mk.markers[i].scale.x = allowed_contacts[i].shape.dimensions[0];
01773 mk.markers[i].scale.y = allowed_contacts[i].shape.dimensions[0];
01774 mk.markers[i].scale.z = allowed_contacts[i].shape.dimensions[1];
01775 }
01776 else
01777 valid_shape = false;
01778 }
01779 else
01780 {
01781 mk.markers[i].scale.x = mk.markers[i].scale.y = mk.markers[i].scale.z = 0.01;
01782 valid_shape = false;
01783 }
01784
01785 mk.markers[i].action = visualization_msgs::Marker::ADD;
01786 mk.markers[i].pose = allowed_contacts[i].pose_stamped.pose;
01787 if(!valid_shape)
01788 {
01789 mk.markers[i].scale.x = mk.markers[i].scale.y = mk.markers[i].scale.z = 0.01;
01790 mk.markers[i].color.a = 0.3;
01791 mk.markers[i].color.r = 1.0;
01792 mk.markers[i].color.g = 0.04;
01793 mk.markers[i].color.b = 0.04;
01794 }
01795 else
01796 {
01797 mk.markers[i].color.a = 1.0;
01798 mk.markers[i].color.r = 0.04;
01799 mk.markers[i].color.g = 1.0;
01800 mk.markers[i].color.b = 0.04;
01801 }
01802
01803 }
01804 allowed_contact_regions_publisher_.publish(mk);
01805 }
01809
01810 private:
01811
01812 std::string group_;
01813
01814 boost::shared_ptr<actionlib::SimpleActionClient<move_arm_head_monitor::HeadMonitorAction> > head_monitor_client_;
01815 boost::shared_ptr<actionlib::SimpleActionClient<move_arm_head_monitor::HeadLookAction> > head_look_client_;
01816
01817 ros::ServiceClient get_group_info_client_, get_state_client_;
01818 ros::ServiceClient ik_client_, check_state_at_goal_client_, check_plan_validity_client_;
01819 ros::ServiceClient check_env_safe_client_, check_execution_safe_client_, check_state_validity_client_;
01820 ros::ServiceClient trajectory_start_client_,trajectory_cancel_client_,trajectory_query_client_;
01821 ros::NodeHandle private_handle_, root_handle_;
01822 boost::shared_ptr<actionlib::SimpleActionServer<move_arm_msgs::MoveArmAction> > action_server_;
01823
01824 tf::TransformListener *tf_;
01825 MoveArmState state_;
01826 double move_arm_frequency_;
01827 ros::Duration trajectory_monitoring_duration_;
01828 ros::Time last_monitor_time_;
01829 trajectory_msgs::JointTrajectory current_trajectory_;
01830
01831 int num_planning_attempts_;
01832
01833 std::vector<std::string> group_joint_names_;
01834 std::vector<std::string> group_link_names_;
01835 std::vector<std::string> all_link_names_;
01836 move_arm_msgs::MoveArmResult move_arm_action_result_;
01837 move_arm_msgs::MoveArmFeedback move_arm_action_feedback_;
01838
01839 motion_planning_msgs::GetMotionPlan::Request original_request_;
01840
01842 urdf::Model robot_model_;
01844 bool robot_model_initialized_;
01845
01846 ros::Publisher display_path_publisher_;
01847 ros::Publisher display_joint_goal_publisher_;
01848 ros::Publisher allowed_contact_regions_publisher_;
01849 ros::ServiceClient filter_trajectory_client_;
01850 ros::ServiceClient fk_client_;
01851 MoveArmParameters move_arm_parameters_;
01852 ControllerStatus controller_status_;
01853
01854 JointExecutorActionClient* controller_action_client_;
01855 JointExecutorActionClient::GoalHandle controller_goal_handle_;
01856
01857 double trajectory_filter_allowed_time_, ik_allowed_time_;
01858 double trajectory_discretization_;
01859 bool arm_ik_initialized_;
01860
01861 std::string head_monitor_link_;
01862 double head_monitor_link_x_, head_monitor_link_y_, head_monitor_link_z_, head_monitor_max_frequency_, head_monitor_time_offset_;
01863 double pause_allowed_time_;
01864 ros::Time pause_start_time_;
01865 bool using_head_monitor_;
01866
01867 bool publish_stats_;
01868 move_arm_msgs::MoveArmStatistics move_arm_stats_;
01869 ros::Publisher stats_publisher_;
01870 };
01871 }
01872
01873 int main(int argc, char** argv)
01874 {
01875 ros::init(argc, argv, "move_arm");
01876
01877 ros::AsyncSpinner spinner(1);
01878 spinner.start();
01879 ros::NodeHandle nh("~");
01880 std::string group;
01881 nh.param<std::string>("group", group, std::string());
01882 ROS_INFO("Move arm operating on group %s",group.c_str());
01883 move_arm::MoveArm move_arm(group);
01884 if(!move_arm.configure())
01885 {
01886 ROS_ERROR("Could not configure move arm, exiting");
01887 ros::shutdown();
01888 return 1;
01889 }
01890 ROS_INFO("Move arm action started");
01891 ros::waitForShutdown();
01892
01893 return 0;
01894 }