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 <planning_environment/models/collision_models_interface.h>
00041 #include <planning_environment/monitors/kinematic_model_state_monitor.h>
00042 #include <planning_environment/models/model_utils.h>
00043 #include <planning_environment/monitors/monitor_utils.h>
00044 #include <arm_navigation_msgs/convert_messages.h>
00045 #include "planning_environment/util/construct_object.h"
00046
00047 #include <sensor_msgs/PointCloud2.h>
00048 #include <pcl/point_types.h>
00049 #include <pcl/point_cloud.h>
00050 #include <pcl/ros/conversions.h>
00051 #include <pcl_ros/transforms.h>
00052
00053 #include <actionlib/server/simple_action_server.h>
00054 #include <actionlib/client/simple_action_client.h>
00055 #include <actionlib/client/simple_client_goal_state.h>
00056
00057 #include <pr2_controllers_msgs/PointHeadAction.h>
00058 #include <control_msgs/FollowJointTrajectoryAction.h>
00059
00060 #include <head_monitor_msgs/HeadMonitorStatus.h>
00061 #include <head_monitor_msgs/HeadMonitorAction.h>
00062 #include <head_monitor_msgs/PreplanHeadScanAction.h>
00063
00064 #include <visualization_msgs/MarkerArray.h>
00065 #include <visualization_msgs/Marker.h>
00066
00067 #include <tf/transform_listener.h>
00068
00069 static const std::string RIGHT_ARM_GROUP = "right_arm";
00070 static const std::string LEFT_ARM_GROUP = "left_arm";
00071
00072 static const double JOINT_BOUNDS_MARGIN = .02;
00073
00074 std::string convertFromGroupNameToArmName(const std::string& arm_name) {
00075 if(arm_name.find(RIGHT_ARM_GROUP) != std::string::npos) {
00076 return(RIGHT_ARM_GROUP);
00077 } else if(arm_name.find(LEFT_ARM_GROUP) != std::string::npos) {
00078 return(LEFT_ARM_GROUP);
00079 } else {
00080 ROS_WARN_STREAM("Neither left arm group or right arm group in group: " << arm_name);
00081 }
00082 return std::string("");
00083 }
00084
00085 class HeadMonitor
00086 {
00087 protected:
00088
00089 ros::NodeHandle private_handle_;
00090 ros::NodeHandle root_handle_;
00091 actionlib::SimpleActionServer<head_monitor_msgs::HeadMonitorAction> head_monitor_action_server_;
00092 actionlib::SimpleActionServer<head_monitor_msgs::PreplanHeadScanAction> head_preplan_scan_action_server_;
00093
00094 ros::Publisher marker_pub_;
00095
00096 actionlib::SimpleActionClient<control_msgs::FollowJointTrajectoryAction> head_controller_action_client_;
00097 actionlib::SimpleActionClient<control_msgs::FollowJointTrajectoryAction>* right_arm_controller_action_client_;
00098 actionlib::SimpleActionClient<control_msgs::FollowJointTrajectoryAction>* left_arm_controller_action_client_;
00099 actionlib::SimpleActionClient<pr2_controllers_msgs::PointHeadAction> point_head_action_client_;
00100
00101 std::string current_group_name_;
00102 actionlib::SimpleActionClient<control_msgs::FollowJointTrajectoryAction>* current_arm_controller_action_client_;
00103
00104 bool use_left_arm_;
00105 bool use_right_arm_;
00106
00107 planning_environment::CollisionModelsInterface* collision_models_interface_;
00108 planning_environment::KinematicModelStateMonitor* kmsm_;
00109
00110 head_monitor_msgs::HeadMonitorGoal monitor_goal_;
00111 head_monitor_msgs::HeadMonitorFeedback monitor_feedback_;
00112 head_monitor_msgs::HeadMonitorResult monitor_result_;
00113
00114 sensor_msgs::JointState last_joint_state_;
00115
00116 trajectory_msgs::JointTrajectory logged_trajectory_;
00117 ros::Time logged_trajectory_start_time_;
00118
00119 tf::TransformListener tf_;
00120
00121 ros::Timer paused_callback_timer_;
00122 ros::Timer start_trajectory_timer_;
00123
00124 visualization_msgs::Marker marker_;
00125
00126 tf::MessageFilter<sensor_msgs::PointCloud2> *mn_;
00127 message_filters::Subscriber<sensor_msgs::PointCloud2> *sub_;
00128
00129
00130 double start_head_pan_, start_head_tilt_, goal_head_pan_, goal_head_tilt_;
00131
00132 double point_sphere_size_;
00133 double pause_time_;
00134 double max_point_distance_;
00135
00136 bool do_monitoring_;
00137 bool do_preplan_scan_;
00138
00139 head_monitor_msgs::HeadMonitorStatus current_execution_status_;
00140
00141 public:
00142
00143 HeadMonitor() :
00144 private_handle_("~"),
00145 head_monitor_action_server_(root_handle_, "head_monitor_action", false),
00146 head_preplan_scan_action_server_(root_handle_, "preplan_head_scan", boost::bind(&HeadMonitor::preplanHeadScanCallback, this, _1), false),
00147 head_controller_action_client_("/head_traj_controller/follow_joint_trajectory", true),
00148 point_head_action_client_("/head_traj_controller/point_head_action", true)
00149 {
00150 current_execution_status_.status = current_execution_status_.IDLE;
00151
00152 private_handle_.param<double>("point_sphere_size", point_sphere_size_, .01);
00153 private_handle_.param<double>("pause_time", pause_time_, 5.0);
00154 private_handle_.param<double>("max_point_distance", max_point_distance_, 1.0);
00155 private_handle_.param<bool>("do_preplan_scan", do_preplan_scan_, true);
00156 private_handle_.param<bool>("do_monitoring", do_monitoring_, true);
00157 private_handle_.param<bool>("use_left_arm", use_left_arm_, true);
00158 private_handle_.param<bool>("use_right_arm", use_right_arm_, true);
00159
00160 std::string robot_description_name = root_handle_.resolveName("robot_description", true);
00161
00162 collision_models_interface_ = new planning_environment::CollisionModelsInterface(robot_description_name);
00163 kmsm_ = new planning_environment::KinematicModelStateMonitor(collision_models_interface_, &tf_);
00164
00165 kmsm_->addOnStateUpdateCallback(boost::bind(&HeadMonitor::jointStateCallback, this, _1));
00166
00167 if(do_preplan_scan_ && do_monitoring_) {
00168 sub_ = new message_filters::Subscriber<sensor_msgs::PointCloud2> (root_handle_, "cloud_in", 1);
00169 mn_ = new tf::MessageFilter<sensor_msgs::PointCloud2> (*sub_, tf_, "", 1);
00170 mn_->setTargetFrame(collision_models_interface_->getWorldFrameId());
00171 mn_->registerCallback(boost::bind(&HeadMonitor::cloudCallback, this, _1));
00172 }
00173
00174 head_monitor_action_server_.registerGoalCallback(boost::bind(&HeadMonitor::monitorGoalCallback, this));
00175 head_monitor_action_server_.registerPreemptCallback(boost::bind(&HeadMonitor::monitorPreemptCallback, this));
00176
00177 if(use_right_arm_) {
00178 right_arm_controller_action_client_ = new actionlib::SimpleActionClient<control_msgs::FollowJointTrajectoryAction>("/r_arm_controller/follow_joint_trajectory", true);
00179 while(ros::ok() && !right_arm_controller_action_client_->waitForServer(ros::Duration(1.0))){
00180 ROS_INFO("Waiting for the right joint_trajectory_action server to come up.");
00181 }
00182 }
00183 if(use_left_arm_) {
00184 left_arm_controller_action_client_ = new actionlib::SimpleActionClient<control_msgs::FollowJointTrajectoryAction>("/l_arm_controller/follow_joint_trajectory", true);
00185 while(ros::ok() && !left_arm_controller_action_client_->waitForServer(ros::Duration(1.0))){
00186 ROS_INFO("Waiting for the left joint_trajectory_action server to come up.");
00187 }
00188 }
00189
00190 if(!use_left_arm_ && !use_right_arm_) {
00191 ROS_ERROR_STREAM("No arms specified. Exiting");
00192 exit(0);
00193 }
00194
00195 ROS_INFO("Connected to the controllers");
00196
00197 head_monitor_action_server_.start();
00198 head_preplan_scan_action_server_.start();
00199
00200 ROS_INFO_STREAM("Starting head monitor action server for "<<ros::this_node::getName());
00201 }
00202
00203 ~HeadMonitor(void)
00204 {
00205 delete kmsm_;
00206 delete collision_models_interface_;
00207 delete right_arm_controller_action_client_;
00208 delete left_arm_controller_action_client_;
00209 }
00210
00214
00215 void cloudCallback (const sensor_msgs::PointCloud2ConstPtr &cloud2)
00216 {
00217 if(current_execution_status_.status == current_execution_status_.IDLE ||
00218 current_execution_status_.status == current_execution_status_.PREPLAN_SCAN) {
00219 return;
00220 }
00221
00222 ros::Time callback_delay = ros::Time::now();
00223
00224 pcl::PointCloud<pcl::PointXYZ> pcl_cloud, trans_cloud, near_cloud;
00225 pcl::fromROSMsg(*cloud2, pcl_cloud);
00226
00227 if(pcl_cloud.points.size() == 0) {
00228 ROS_WARN_STREAM("No points in cloud");
00229 return;
00230 }
00231
00232 collision_models_interface_->bodiesLock();
00233
00234 sensor_msgs::JointState js = last_joint_state_;
00235 trajectory_msgs::JointTrajectory joint_trajectory_subset;
00236 if(current_execution_status_.status == current_execution_status_.EXECUTING) {
00237 planning_environment::removeCompletedTrajectory(collision_models_interface_->getParsedDescription(),
00238 monitor_goal_.joint_trajectory,
00239 js,
00240 joint_trajectory_subset,
00241 false);
00242 } else {
00243 joint_trajectory_subset = monitor_goal_.joint_trajectory;
00244 }
00245
00246 if(joint_trajectory_subset.points.size() == 0) {
00247
00248 if(current_execution_status_.status == current_execution_status_.PAUSED) {
00249 ROS_ERROR_STREAM("Paused, but closest trajectory point is goal");
00250 }
00251 collision_models_interface_->bodiesUnlock();
00252 return;
00253 }
00254 ros::Time n1 = ros::Time::now();
00255
00256 planning_models::KinematicState state(collision_models_interface_->getKinematicModel());
00257 kmsm_->setStateValuesFromCurrentValues(state);
00258
00259 planning_environment::updateAttachedObjectBodyPoses(collision_models_interface_,
00260 state,
00261 tf_);
00262
00263
00264
00265 if (collision_models_interface_->getWorldFrameId() != pcl_cloud.header.frame_id) {
00266 pcl_ros::transformPointCloud(collision_models_interface_->getWorldFrameId(), pcl_cloud, trans_cloud, tf_);
00267 } else {
00268 trans_cloud = pcl_cloud;
00269 }
00270
00271 tf::Transform cur_link_pose = state.getLinkState(monitor_goal_.target_link)->getGlobalCollisionBodyTransform();
00272 near_cloud.header = trans_cloud.header;
00273 for(unsigned int i = 0; i < trans_cloud.points.size(); i++) {
00274 tf::Vector3 pt = tf::Vector3(trans_cloud.points[i].x, trans_cloud.points[i].y, trans_cloud.points[i].z);
00275 double dist = pt.distance(cur_link_pose.getOrigin());
00276 if(dist <= max_point_distance_) {
00277 near_cloud.push_back(trans_cloud.points[i]);
00278 }
00279 }
00280
00281 std::vector<shapes::Shape*> spheres(near_cloud.points.size());;
00282 std::vector<tf::Transform> positions(near_cloud.points.size());
00283
00284 ros::Time n3 = ros::Time::now();
00285
00286 if(near_cloud.points.size() != 0) {
00287
00288 tf::Quaternion ident(0.0, 0.0, 0.0, 1.0);
00289
00290 for (unsigned int i = 0 ; i < near_cloud.points.size(); ++i) {
00291 positions[i] = tf::Transform(ident,
00292 tf::Vector3(near_cloud.points[i].x, near_cloud.points[i].y, near_cloud.points[i].z));
00293 spheres[i] = new shapes::Sphere(point_sphere_size_);
00294 }
00295
00296
00297 collision_models_interface_->addStaticObject("point_spheres",
00298 spheres,
00299 positions,
00300 0.0);
00301
00302
00303 collision_space::EnvironmentModel::AllowedCollisionMatrix acm = collision_models_interface_->getCollisionSpace()->getCurrentAllowedCollisionMatrix();
00304 const planning_models::KinematicModel::JointModelGroup* joint_model_group = collision_models_interface_->getKinematicModel()->getModelGroup(current_group_name_);
00305
00306 acm.addEntry("point_spheres", true);
00307 acm.changeEntry(true);
00308 acm.changeEntry("point_spheres", joint_model_group->getUpdatedLinkModelNames(), false);
00309
00310 collision_models_interface_->setAlteredAllowedCollisionMatrix(acm);
00311
00312 } else {
00313
00314 collision_space::EnvironmentModel::AllowedCollisionMatrix acm = collision_models_interface_->getCollisionSpace()->getCurrentAllowedCollisionMatrix();
00315 acm.changeEntry(true);
00316
00317 collision_models_interface_->setAlteredAllowedCollisionMatrix(acm);
00318 }
00319 arm_navigation_msgs::Constraints empty_constraints;
00320 arm_navigation_msgs::ArmNavigationErrorCodes error_code;
00321 std::vector<arm_navigation_msgs::ArmNavigationErrorCodes> trajectory_error_codes;
00322
00323 ros::Time n2 = ros::Time::now();
00324 if(!collision_models_interface_->isJointTrajectoryValid(state,
00325 joint_trajectory_subset,
00326 empty_constraints,
00327 empty_constraints,
00328 error_code,
00329 trajectory_error_codes,
00330 false)) {
00331 ROS_INFO_STREAM("Validity check took " << (ros::Time::now()-n2).toSec());
00332 ROS_INFO_STREAM("Trajectory check took " << (ros::Time::now() - n1).toSec()
00333 << " shape " << (n2-n3).toSec()
00334 << " traj part " << (ros::Time::now() - n2).toSec());
00335 if(current_execution_status_.status == current_execution_status_.MONITOR_BEFORE_EXECUTION ||
00336 current_execution_status_.status == current_execution_status_.EXECUTING) {
00337 ROS_WARN_STREAM("Trajectory judged invalid " << error_code.val << ". Pausing");
00338
00339 if(current_execution_status_.status == current_execution_status_.MONITOR_BEFORE_EXECUTION) {
00340 start_trajectory_timer_.stop();
00341 } else {
00342 current_arm_controller_action_client_->cancelGoal();
00343 ROS_INFO_STREAM("Delay from data timestamp to cancel is " << (ros::Time::now() - cloud2->header.stamp).toSec()
00344 << " delay to receipt is " << (callback_delay - cloud2->header.stamp).toSec());
00345
00346 }
00347 stopHead();
00348 current_execution_status_.status = current_execution_status_.PAUSED;
00349 kmsm_->setStateValuesFromCurrentValues(state);
00350 planning_environment::convertKinematicStateToRobotState(state,
00351 ros::Time::now(),
00352 collision_models_interface_->getWorldFrameId(),
00353 monitor_feedback_.current_state);
00354 unsigned int trajectory_point = trajectory_error_codes.size();
00355 if(trajectory_error_codes.size() > 0) {
00356 trajectory_point--;
00357 }
00358 ROS_INFO_STREAM("Setting trajectory state to point " << trajectory_point << " of " << joint_trajectory_subset.points.size());
00359
00360 std::map<std::string, double> vals;
00361 for(unsigned int i = 0; i < joint_trajectory_subset.joint_names.size(); i++) {
00362 vals[joint_trajectory_subset.joint_names[i]] = joint_trajectory_subset.points[trajectory_point].positions[i];
00363 }
00364 state.setKinematicState(vals);
00365 planning_environment::convertKinematicStateToRobotState(state,
00366 ros::Time::now(),
00367 collision_models_interface_->getWorldFrameId(),
00368 monitor_feedback_.paused_trajectory_state);
00369 monitor_feedback_.paused_collision_map.header.frame_id = collision_models_interface_->getWorldFrameId();
00370 monitor_feedback_.paused_collision_map.header.stamp = cloud2->header.stamp;
00371 monitor_feedback_.paused_collision_map.id = "point_spheres";
00372 monitor_feedback_.paused_collision_map.operation.operation = arm_navigation_msgs::CollisionObjectOperation::ADD;
00373 for (unsigned int j = 0 ; j < spheres.size(); ++j) {
00374 arm_navigation_msgs::Shape obj;
00375 if (planning_environment::constructObjectMsg(spheres[j], obj)) {
00376 geometry_msgs::Pose pose;
00377 tf::poseTFToMsg(positions[j], pose);
00378 monitor_feedback_.paused_collision_map.shapes.push_back(obj);
00379 monitor_feedback_.paused_collision_map.poses.push_back(pose);
00380 }
00381 }
00382 std::vector<arm_navigation_msgs::ContactInformation> contacts;
00383 collision_models_interface_->getAllCollisionsForState(state, contacts, 1);
00384 if(contacts.size() == 0) {
00385 ROS_INFO_STREAM("No contacts for last trajectory state");
00386 } else {
00387 for(unsigned int i = 0; i < contacts.size(); i++) {
00388 ROS_INFO_STREAM("Contact between " << contacts[i].contact_body_1 << " and " << contacts[i].contact_body_2
00389 << " at point " << contacts[i].position.x << " " << contacts[i].position.y << " " << contacts[i].position.z);
00390 }
00391
00392 }
00393 head_monitor_action_server_.publishFeedback(monitor_feedback_);
00394 paused_callback_timer_ = root_handle_.createTimer(ros::Duration(pause_time_), boost::bind(&HeadMonitor::pauseTimeoutCallback, this), true);
00395 }
00396
00397 } else {
00398 if(current_execution_status_.status == current_execution_status_.PAUSED) {
00399 paused_callback_timer_.stop();
00400
00401 ROS_WARN_STREAM("Unpausing");
00402
00403 current_execution_status_.status = current_execution_status_.MONITOR_BEFORE_EXECUTION;
00404
00405 sensor_msgs::JointState js = last_joint_state_;
00406 trajectory_msgs::JointTrajectory joint_trajectory_subset;
00407
00408 planning_environment::removeCompletedTrajectory(collision_models_interface_->getParsedDescription(),
00409 monitor_goal_.joint_trajectory,
00410 js,
00411 joint_trajectory_subset,
00412 false);
00413
00414 control_msgs::FollowJointTrajectoryGoal goal;
00415 goal.trajectory = generateHeadTrajectory(monitor_goal_.target_link, joint_trajectory_subset);
00416 head_controller_action_client_.sendGoal(goal);
00417
00418
00419 start_trajectory_timer_ = root_handle_.createTimer(ros::Duration(monitor_goal_.time_offset), boost::bind(&HeadMonitor::trajectoryTimerCallback, this), true);
00420 }
00421 }
00422 if(near_cloud.points.size() != 0) {
00423 collision_models_interface_->deleteStaticObject("point_spheres");
00424 monitor_feedback_.paused_collision_map.shapes.clear();
00425 monitor_feedback_.paused_collision_map.poses.clear();
00426 }
00427 ROS_DEBUG_STREAM("Trajectory check took " << (ros::Time::now() - n1).toSec()
00428 << " shape " << (n2-n3).toSec()
00429 << " traj part " << (ros::Time::now() - n2).toSec());
00430 collision_models_interface_->bodiesUnlock();
00431 }
00432
00433 void moveInsideSafetyLimits(const head_monitor_msgs::PreplanHeadScanGoalConstPtr &goal,
00434 const planning_models::KinematicState& state) {
00435 const planning_models::KinematicModel::JointModelGroup* joint_model_group = collision_models_interface_->getKinematicModel()->getModelGroup(goal->group_name);
00436 const std::vector<std::string>& joint_names = joint_model_group->getJointModelNames();
00437 ROS_DEBUG_STREAM("Group name " << goal->group_name);
00438
00439 if(goal->group_name == RIGHT_ARM_GROUP && !use_right_arm_) {
00440 ROS_WARN_STREAM("Not configured for use with group name " << RIGHT_ARM_GROUP);
00441 return;
00442 }
00443 if(goal->group_name == LEFT_ARM_GROUP && !use_left_arm_) {
00444 ROS_WARN_STREAM("Not configured for use with group name " << LEFT_ARM_GROUP);
00445 return;
00446 }
00447
00448 if(state.areJointsWithinBounds(joint_names)) {
00449 return;
00450 }
00451 trajectory_msgs::JointTrajectory traj;
00452 traj.joint_names = joint_names;
00453 traj.header.stamp = ros::Time::now();
00454 traj.header.frame_id = collision_models_interface_->getWorldFrameId();
00455 traj.points.resize(1);
00456 traj.points[0].positions.resize(joint_names.size());
00457 traj.points[0].velocities.resize(joint_names.size());
00458 traj.points[0].time_from_start = ros::Duration(.4);
00459
00460 std::map<std::string, double> joint_values;
00461 state.getKinematicStateValues(joint_values);
00462
00463 for(unsigned int j = 0; j < joint_names.size(); j++) {
00464 if(!state.isJointWithinBounds(joint_names[j])) {
00465 std::pair<double, double> bounds;
00466 state.getJointState(joint_names[j])->getJointModel()->getVariableBounds(joint_names[j], bounds);
00467 ROS_INFO_STREAM("Joint " << joint_names[j] << " out of bounds. " <<
00468 " value: " << state.getJointState(joint_names[j])->getJointStateValues()[0] <<
00469 " low: " << bounds.first << " high: " << bounds.second);
00470 if(joint_values[joint_names[j]] < bounds.first) {
00471 traj.points[0].positions[j] = bounds.first+JOINT_BOUNDS_MARGIN;
00472 ROS_INFO_STREAM("Setting joint " << joint_names[j] << " inside lower bound " << traj.points[0].positions[j]);
00473 } else {
00474 traj.points[0].positions[j] = bounds.second-JOINT_BOUNDS_MARGIN;
00475 ROS_INFO_STREAM("Setting joint " << joint_names[j] << " inside upper bound " << traj.points[0].positions[j]);
00476 }
00477 } else {
00478 traj.points[0].positions[j] = joint_values[joint_names[j]];
00479 }
00480 }
00481
00482 control_msgs::FollowJointTrajectoryGoal traj_goal;
00483 traj_goal.trajectory = traj;
00484
00485 current_arm_controller_action_client_ = ((goal->group_name == RIGHT_ARM_GROUP) ? right_arm_controller_action_client_ : left_arm_controller_action_client_);
00486
00487 if(current_arm_controller_action_client_->sendGoalAndWait(traj_goal, ros::Duration(1.0), ros::Duration(.5)) != actionlib::SimpleClientGoalState::SUCCEEDED) {
00488 ROS_WARN_STREAM("Joint bounds correction trajectory failed");
00489 }
00490 }
00491
00492 void preplanHeadScanCallback(const head_monitor_msgs::PreplanHeadScanGoalConstPtr &goal)
00493 {
00494 head_monitor_msgs::PreplanHeadScanResult res;
00495
00496 collision_models_interface_->bodiesLock();
00497
00498 if(current_execution_status_.status != current_execution_status_.IDLE) {
00499 ROS_WARN_STREAM("Got preplan in something other than IDLE mode");
00500 }
00501
00502
00503 planning_models::KinematicState state(collision_models_interface_->getKinematicModel());
00504
00505 kmsm_->setStateValuesFromCurrentValues(state);
00506
00507 moveInsideSafetyLimits(goal, state);
00508
00509 if(!do_preplan_scan_) {
00510 collision_models_interface_->bodiesUnlock();
00511 head_preplan_scan_action_server_.setSucceeded(res);
00512 return;
00513 }
00514
00515 current_execution_status_.status = current_execution_status_.PREPLAN_SCAN;
00516
00517 kmsm_->setStateValuesFromCurrentValues(state);
00518
00519
00520 planning_environment::setRobotStateAndComputeTransforms(goal->motion_plan_request.start_state,
00521 state);
00522 double x_start, y_start, z_start;
00523
00524 if(!state.hasLinkState(goal->head_monitor_link)) {
00525 ROS_WARN_STREAM("No monitor link " << goal->head_monitor_link);
00526 head_preplan_scan_action_server_.setAborted(res);
00527 current_execution_status_.status = current_execution_status_.IDLE;
00528 collision_models_interface_->bodiesUnlock();
00529 return;
00530 }
00531
00532 tf::Transform link_state = state.getLinkState(goal->head_monitor_link)->getGlobalCollisionBodyTransform();
00533 x_start = link_state.getOrigin().x();
00534 y_start = link_state.getOrigin().y();
00535 z_start = link_state.getOrigin().z();
00536
00537 double x_goal, y_goal, z_goal;
00538 if(goal->motion_plan_request.goal_constraints.position_constraints.size() >= 1
00539 && goal->motion_plan_request.goal_constraints.orientation_constraints.size() >= 1) {
00540 geometry_msgs::PoseStamped goal_pose
00541 = arm_navigation_msgs::poseConstraintsToPoseStamped(goal->motion_plan_request.goal_constraints.position_constraints[0],
00542 goal->motion_plan_request.goal_constraints.orientation_constraints[0]);
00543
00544 std::string es;
00545 if (tf_.getLatestCommonTime(collision_models_interface_->getWorldFrameId(), goal_pose.header.frame_id, goal_pose.header.stamp, &es) != tf::NO_ERROR) {
00546 }
00547 geometry_msgs::PoseStamped psout;
00548 tf_.transformPose(collision_models_interface_->getWorldFrameId(), goal_pose, psout);
00549
00550 x_goal = psout.pose.position.x;
00551 y_goal = psout.pose.position.y;
00552 z_goal = psout.pose.position.z;
00553 } else {
00554 if(goal->motion_plan_request.goal_constraints.joint_constraints.size() <= 1) {
00555 ROS_WARN("Not a pose goal and not enough joint constraints");
00556 head_preplan_scan_action_server_.setAborted(res);
00557 current_execution_status_.status = current_execution_status_.IDLE;
00558 collision_models_interface_->bodiesUnlock();
00559 return;
00560 }
00561 std::map<std::string, double> joint_values;
00562 for(unsigned int i = 0; i < goal->motion_plan_request.goal_constraints.joint_constraints.size(); i++) {
00563 joint_values[goal->motion_plan_request.goal_constraints.joint_constraints[i].joint_name] = goal->motion_plan_request.goal_constraints.joint_constraints[i].position;
00564 }
00565 state.setKinematicState(joint_values);
00566 tf::Transform link_state = state.getLinkState(goal->head_monitor_link)->getGlobalCollisionBodyTransform();
00567 x_goal = link_state.getOrigin().x();
00568 y_goal = link_state.getOrigin().y();
00569 z_goal = link_state.getOrigin().z();
00570 }
00571 std::map<std::string, double> state_values;
00572 ROS_INFO_STREAM("Looking at goal " << x_goal << " " << y_goal << " " << z_goal);
00573 lookAt(collision_models_interface_->getWorldFrameId(), x_goal, y_goal, z_goal, true);
00574 kmsm_->setStateValuesFromCurrentValues(state);
00575 state.getKinematicStateValues(state_values);
00576 goal_head_pan_ = state_values["head_pan_joint"];
00577 goal_head_tilt_ = state_values["head_tilt_joint"];
00578 ROS_INFO_STREAM("Looking at start " << x_start << " " << y_start << " " << z_start);
00579 lookAt(collision_models_interface_->getWorldFrameId(), x_start, y_start, z_start, true);
00580 kmsm_->setStateValuesFromCurrentValues(state);
00581 state.getKinematicStateValues(state_values);
00582 start_head_pan_ = state_values["head_pan_joint"];
00583 start_head_tilt_ = state_values["head_tilt_joint"];
00584 head_preplan_scan_action_server_.setSucceeded(res);
00585 current_execution_status_.status = current_execution_status_.IDLE;
00586 collision_models_interface_->bodiesUnlock();
00587 }
00588
00589
00590 void monitorGoalCallback()
00591 {
00592 if(current_execution_status_.status == current_execution_status_.MONITOR_BEFORE_EXECUTION &&
00593 current_execution_status_.status == current_execution_status_.EXECUTING &&
00594 current_execution_status_.status == current_execution_status_.PAUSED) {
00595 ROS_WARN_STREAM("Got new goal while executing");
00596 stopEverything();
00597 }
00598
00599 if(!head_monitor_action_server_.isNewGoalAvailable())
00600 {
00601 ROS_INFO_STREAM("Preempted, no new goal");
00602 return;
00603 }
00604 monitor_goal_ = head_monitor_msgs::HeadMonitorGoal(*head_monitor_action_server_.acceptNewGoal());
00605 current_group_name_ = convertFromGroupNameToArmName(monitor_goal_.group_name);
00606
00607 if(current_group_name_ == RIGHT_ARM_GROUP && !use_right_arm_) {
00608 ROS_WARN_STREAM("Not configured for use with group name " << RIGHT_ARM_GROUP);
00609 monitor_result_.error_code.val = monitor_result_.error_code.INVALID_GROUP_NAME;
00610 head_monitor_action_server_.setAborted(monitor_result_);
00611 return;
00612 }
00613 if(current_group_name_ == LEFT_ARM_GROUP && !use_left_arm_) {
00614 ROS_WARN_STREAM("Not configured for use with group name " << LEFT_ARM_GROUP);
00615 monitor_result_.error_code.val = monitor_result_.error_code.INVALID_GROUP_NAME;
00616 head_monitor_action_server_.setAborted(monitor_result_);
00617 return;
00618 }
00619
00620 if(current_group_name_.empty()) {
00621 ROS_WARN_STREAM("Group name doesn't have left or right arm in it, gonna be bad");
00622 }
00623
00624 current_arm_controller_action_client_ = ((current_group_name_ == RIGHT_ARM_GROUP) ? right_arm_controller_action_client_ : left_arm_controller_action_client_);
00625
00626 logged_trajectory_ = monitor_goal_.joint_trajectory;
00627 logged_trajectory_.points.clear();
00628
00629 logged_trajectory_start_time_ = ros::Time::now();
00630
00631 if(do_preplan_scan_ && do_monitoring_) {
00632 current_execution_status_.status = current_execution_status_.MONITOR_BEFORE_EXECUTION;
00633
00634
00635
00636 control_msgs::FollowJointTrajectoryGoal goal;
00637 goal.trajectory = generateHeadTrajectory(monitor_goal_.target_link, monitor_goal_.joint_trajectory);
00638 head_controller_action_client_.sendGoal(goal);
00639
00640 start_trajectory_timer_ = root_handle_.createTimer(ros::Duration(monitor_goal_.time_offset), boost::bind(&HeadMonitor::trajectoryTimerCallback, this), true);
00641 } else {
00642
00643 trajectoryTimerCallback();
00644 }
00645 }
00646
00647 void stopHead()
00648 {
00649 head_controller_action_client_.cancelAllGoals();
00650 }
00651
00652 void stopArm()
00653 {
00654 if(current_execution_status_.status == current_execution_status_.EXECUTING) {
00655 current_arm_controller_action_client_->cancelGoal();
00656 }
00657 }
00658
00659 void stopEverything() {
00660 start_trajectory_timer_.stop();
00661 paused_callback_timer_.stop();
00662 stopHead();
00663 stopArm();
00664 }
00665
00666 void monitorPreemptCallback()
00667 {
00668 if(current_execution_status_.status != current_execution_status_.MONITOR_BEFORE_EXECUTION &&
00669 current_execution_status_.status != current_execution_status_.EXECUTING &&
00670 current_execution_status_.status != current_execution_status_.PAUSED) {
00671 ROS_WARN_STREAM("Got preempt not in a relevant mode");
00672 return;
00673 }
00674
00675 stopEverything();
00676
00677 current_execution_status_.status = current_execution_status_.IDLE;
00678
00679 ROS_INFO_STREAM(ros::this_node::getName() << ": Preempted");
00680 head_monitor_action_server_.setPreempted(monitor_result_);
00681 }
00682
00683 void jointStateCallback(const sensor_msgs::JointStateConstPtr& joint_state) {
00684 last_joint_state_ = *joint_state;
00685 if(current_execution_status_.status == current_execution_status_.IDLE
00686 || current_execution_status_.status == current_execution_status_.PREPLAN_SCAN) {
00687 return;
00688 }
00689 std::map<std::string, double> joint_state_map;
00690 std::map<std::string, double> joint_velocity_map;
00691
00692 for (unsigned int i = 0 ; i < joint_state->position.size(); ++i)
00693 {
00694 joint_state_map[joint_state->name[i]] = joint_state->position[i];
00695 joint_velocity_map[joint_state->name[i]] = joint_state->velocity[i];
00696 }
00697 trajectory_msgs::JointTrajectoryPoint point;
00698 point.positions.resize(logged_trajectory_.joint_names.size());
00699 point.velocities.resize(logged_trajectory_.joint_names.size());
00700 for(unsigned int i = 0; i < logged_trajectory_.joint_names.size(); i++) {
00701 point.positions[i] = joint_state_map[logged_trajectory_.joint_names[i]];
00702 point.velocities[i] = joint_velocity_map[logged_trajectory_.joint_names[i]];
00703 }
00704 point.time_from_start = ros::Time::now()-logged_trajectory_start_time_;
00705 logged_trajectory_.points.push_back(point);
00706 }
00707
00708 void controllerDoneCallback(const actionlib::SimpleClientGoalState& state,
00709 const control_msgs::FollowJointTrajectoryResultConstPtr& result)
00710 {
00711 if(current_execution_status_.status != current_execution_status_.EXECUTING) {
00712
00713 return;
00714 }
00715 ROS_INFO_STREAM("Trajectory reported done with state " << state.toString());
00716 current_execution_status_.status = current_execution_status_.IDLE;
00717 monitor_result_.actual_trajectory = logged_trajectory_;
00718 monitor_result_.error_code.val = monitor_result_.error_code.SUCCESS;
00719 head_monitor_action_server_.setSucceeded(monitor_result_);
00720 }
00721
00722 void pauseTimeoutCallback() {
00723 ROS_INFO_STREAM("Paused trajectory timed out");
00724 stopEverything();
00725 current_execution_status_.status = current_execution_status_.IDLE;
00726 monitor_result_.actual_trajectory = logged_trajectory_;
00727 monitor_result_.error_code.val = monitor_result_.error_code.TIMED_OUT;
00728 head_monitor_action_server_.setAborted(monitor_result_);
00729 }
00730
00734
00735
00736 void trajectoryTimerCallback() {
00737 current_execution_status_.status = current_execution_status_.EXECUTING;
00738
00739 control_msgs::FollowJointTrajectoryGoal goal;
00740
00741 sensor_msgs::JointState js = last_joint_state_;
00742 planning_environment::removeCompletedTrajectory(collision_models_interface_->getParsedDescription(),
00743 monitor_goal_.joint_trajectory,
00744 js,
00745 goal.trajectory,
00746 false);
00747 goal.trajectory.header.stamp = ros::Time::now()+ros::Duration(0.2);
00748
00749 ROS_INFO("Sending trajectory with %d points (excerpted from %d points) and timestamp: %f",(int)goal.trajectory.points.size(),(int) monitor_goal_.joint_trajectory.points.size(), goal.trajectory.header.stamp.toSec());
00750 current_arm_controller_action_client_->sendGoal(goal,boost::bind(&HeadMonitor::controllerDoneCallback, this, _1, _2));
00751 }
00752
00756
00757 trajectory_msgs::JointTrajectory generateHeadTrajectory(const std::string& link, const trajectory_msgs::JointTrajectory& joint_trajectory) {
00758 trajectory_msgs::JointTrajectory ret_traj;
00759 ret_traj.header = joint_trajectory.header;
00760 ret_traj.header.stamp = ros::Time::now();
00761 ret_traj.joint_names.resize(2);
00762 ret_traj.joint_names[0] = "head_pan_joint";
00763 ret_traj.joint_names[1] = "head_tilt_joint";
00764
00765
00766
00767 ret_traj.points.resize(2);
00768
00769 ret_traj.points[0].positions.resize(2);
00770 ret_traj.points[1].positions.resize(2);
00771
00772 ret_traj.points[0].positions[0] = start_head_pan_;
00773 ret_traj.points[0].positions[1] = start_head_tilt_;
00774 ret_traj.points[0].time_from_start = ros::Duration(.2);
00775
00776 ret_traj.points[1].positions[0] = goal_head_pan_;
00777 ret_traj.points[1].positions[1] = goal_head_tilt_;
00778 ret_traj.points[1].time_from_start = joint_trajectory.points.back().time_from_start;
00779
00780 return ret_traj;
00781 }
00782
00783
00784 void lookAt(std::string frame_id, double x, double y, double z, bool wait)
00785 {
00786
00787 pr2_controllers_msgs::PointHeadGoal goal;
00788
00789
00790 geometry_msgs::PointStamped point;
00791 point.header.frame_id = frame_id;
00792 point.point.x = x;
00793 point.point.y = y;
00794 point.point.z = z;
00795
00796 goal.target = point;
00797
00798
00799 goal.min_duration = ros::Duration(.4);
00800 goal.max_velocity = 0.4;
00801
00802 if(wait)
00803 {
00804 if(point_head_action_client_.sendGoalAndWait(goal, ros::Duration(15.0), ros::Duration(0.5)) != actionlib::SimpleClientGoalState::SUCCEEDED)
00805 ROS_WARN("Point head timed out, continuing");
00806 }
00807 else
00808 {
00809 point_head_action_client_.sendGoal(goal);
00810 }
00811 }
00812 };
00813
00814
00815 int main(int argc, char** argv)
00816 {
00817 ros::init(argc, argv, "move_arm_head_monitor");
00818
00819 ros::AsyncSpinner spinner(3);
00820 spinner.start();
00821
00822 HeadMonitor head_monitor;
00823
00824 ros::waitForShutdown();
00825 return 0;
00826 }
00827