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
00037 #include <chomp_motion_planner/chomp_robot_model.h>
00038 #include <kdl_parser/kdl_parser.hpp>
00039 #include <ros/ros.h>
00040 #include <cstdio>
00041 #include <iostream>
00042 #include <visualization_msgs/MarkerArray.h>
00043
00044 using namespace std;
00045 using namespace mapping_msgs;
00046
00047 namespace chomp
00048 {
00049
00050 ChompRobotModel::ChompRobotModel():
00051 node_handle_("~"),
00052 monitor_(NULL)
00053 {
00054 }
00055
00056 ChompRobotModel::~ChompRobotModel()
00057 {
00058 }
00059
00060 bool ChompRobotModel::init(planning_environment::CollisionSpaceMonitor* monitor, std::string& reference_frame)
00061 {
00062
00063 reference_frame_ = reference_frame;
00064 monitor_ = monitor;
00065
00066
00067
00068 max_radius_clearance_ = 0.0;
00069
00070
00071 string urdf_string;
00072 if (!node_handle_.getParam(monitor_->getCollisionModels()->getDescription(), urdf_string))
00073 {
00074 return false;
00075 }
00076
00077
00078 double joint_update_limit;
00079 node_handle_.param("collision_clearance", collision_clearance_default_, 0.10);
00080 node_handle_.param("joint_update_limit", joint_update_limit, 0.05);
00081
00082
00083 if (!kdl_parser::treeFromString(urdf_string, kdl_tree_))
00084 {
00085 ROS_ERROR("Failed to construct KDL tree from URDF.");
00086 return false;
00087 }
00088 num_kdl_joints_ = kdl_tree_.getNrOfJoints();
00089
00090
00091
00092 KDL::SegmentMap segment_map = kdl_tree_.getSegments();
00093
00094 for (KDL::SegmentMap::const_iterator it = segment_map.begin(); it != segment_map.end(); ++it)
00095 {
00096 if (it->second.segment.getJoint().getType() != KDL::Joint::None)
00097 {
00098 std::string joint_name = it->second.segment.getJoint().getName();
00099 std::string segment_name = it->first;
00100 joint_segment_mapping_.insert(make_pair(joint_name, segment_name));
00101 }
00102 }
00103
00104
00105 fk_solver_ = new KDL::TreeFkSolverJointPosAxis(kdl_tree_, reference_frame_);
00106
00107 kdl_number_to_urdf_name_.resize(num_kdl_joints_);
00108
00109
00110 for (map<string, string>::iterator it = joint_segment_mapping_.begin(); it!= joint_segment_mapping_.end(); ++it)
00111 {
00112 std::string joint_name = it->first;
00113 std::string segment_name = it->second;
00114
00115 segment_joint_mapping_.insert(make_pair(segment_name, joint_name));
00116 int kdl_number = kdl_tree_.getSegment(segment_name)->second.q_nr;
00117 if (kdl_tree_.getSegment(segment_name)->second.segment.getJoint().getType() != KDL::Joint::None)
00118 {
00119
00120 kdl_number_to_urdf_name_[kdl_number] = joint_name;
00121 urdf_name_to_kdl_number_.insert(make_pair(joint_name, kdl_number));
00122 }
00123 }
00124
00125
00126 std::map<std::string, std::vector<std::string> > groups = monitor_->getCollisionModels()->getPlanningGroupJoints();
00127 for (std::map< std::string, std::vector<std::string> >::iterator it = groups.begin(); it != groups.end() ; ++it)
00128 {
00129 ChompPlanningGroup group;
00130 group.name_ = it->first;
00131 int num_links = it->second.size();
00132 group.num_joints_ = 0;
00133 group.link_names_.resize(num_links);
00134 std::vector<bool> active_joints;
00135 active_joints.resize(num_kdl_joints_, false);
00136 for (int i=0; i<num_links; i++)
00137 {
00138 std::string joint_name = it->second[i];
00139 map<string, string>::iterator link_name_it = joint_segment_mapping_.find(joint_name);
00140 if (link_name_it == joint_segment_mapping_.end())
00141 {
00142 ROS_ERROR("Joint name %s did not have containing KDL segment.", joint_name.c_str());
00143 return false;
00144 }
00145 std::string link_name = link_name_it->second;
00146 group.link_names_[i] = link_name;
00147 const KDL::Segment* segment = &(kdl_tree_.getSegment(link_name)->second.segment);
00148 KDL::Joint::JointType joint_type = segment->getJoint().getType();
00149 if (joint_type != KDL::Joint::None)
00150 {
00151 ChompJoint joint;
00152 joint.chomp_joint_index_ = group.num_joints_;
00153 joint.kdl_joint_index_ = kdl_tree_.getSegment(link_name)->second.q_nr;
00154 joint.kdl_joint_ = &(segment->getJoint());
00155 joint.link_name_ = link_name;
00156 joint.joint_name_ = segment_joint_mapping_[link_name];
00157 joint.joint_update_limit_ = joint_update_limit;
00158 const planning_models::KinematicModel::JointModel* kin_model_joint = monitor_->getCollisionModels()->getKinematicModel()->getJointModel(joint.joint_name_);
00159 if (const planning_models::KinematicModel::RevoluteJointModel* revolute_joint = dynamic_cast<const planning_models::KinematicModel::RevoluteJointModel*>(kin_model_joint))
00160 {
00161 joint.wrap_around_ = revolute_joint->continuous_;
00162 joint.has_joint_limits_ = !(joint.wrap_around_);
00163 std::pair<double,double> bounds = revolute_joint->getVariableBounds(revolute_joint->getName());
00164 joint.joint_limit_min_ = bounds.first;
00165 joint.joint_limit_max_ = bounds.second;
00166 ROS_DEBUG_STREAM("Setting bounds for joint " << revolute_joint->getName() << " to " << joint.joint_limit_min_ << " " << joint.joint_limit_max_);
00167 }
00168 else if (const planning_models::KinematicModel::PrismaticJointModel* prismatic_joint = dynamic_cast<const planning_models::KinematicModel::PrismaticJointModel*>(kin_model_joint))
00169 {
00170 joint.wrap_around_ = false;
00171 joint.has_joint_limits_ = true;
00172 std::pair<double,double> bounds = prismatic_joint->getVariableBounds(prismatic_joint->getName());
00173 joint.joint_limit_min_ = bounds.first;
00174 joint.joint_limit_max_ = bounds.second;
00175 ROS_DEBUG_STREAM("Setting bounds for joint " << prismatic_joint->getName() << " to " << joint.joint_limit_min_ << " " << joint.joint_limit_max_);
00176 }
00177 else
00178 {
00179 ROS_WARN("CHOMP cannot handle floating or planar joints yet.");
00180 }
00181
00182 group.num_joints_++;
00183 group.chomp_joints_.push_back(joint);
00184 active_joints[joint.kdl_joint_index_] = true;
00185 }
00186
00187 }
00188 group.fk_solver_.reset(new KDL::TreeFkSolverJointPosAxisPartial(kdl_tree_, reference_frame_, active_joints));
00189 planning_groups_.insert(make_pair(it->first, group));
00190 }
00191
00192 generateLinkCollisionPoints();
00193 populatePlanningGroupCollisionPoints();
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221 ROS_INFO("Initialized chomp robot model in %s reference frame.", reference_frame_.c_str());
00222
00223 return true;
00224 }
00225
00226 void ChompRobotModel::getLinkInformation(const std::string link_name, std::vector<int>& active_joints, int& segment_number)
00227 {
00228
00229 if (link_collision_points_.find(link_name) == link_collision_points_.end())
00230 {
00231 link_collision_points_.insert(make_pair(link_name, std::vector<ChompCollisionPoint>()));
00232 }
00233
00234
00235 if (link_attached_object_collision_points_.find(link_name) == link_attached_object_collision_points_.end())
00236 {
00237 link_attached_object_collision_points_.insert(make_pair(link_name, std::vector<ChompCollisionPoint>()));
00238 }
00239
00240 ROS_DEBUG_STREAM("Link info for " << link_name);
00241
00242
00243 active_joints.clear();
00244 KDL::SegmentMap::const_iterator segment_iter = kdl_tree_.getSegment(link_name);
00245
00246
00247 while (segment_iter != kdl_tree_.getRootSegment())
00248 {
00249 KDL::Joint::JointType joint_type = segment_iter->second.segment.getJoint().getType();
00250 if (joint_type != KDL::Joint::None)
00251 {
00252 active_joints.push_back(segment_iter->second.q_nr);
00253 ROS_DEBUG_STREAM("Adding parent " << segment_iter->second.segment.getJoint().getName());
00254 }
00255 segment_iter = segment_iter->second.parent;
00256 }
00257 ROS_DEBUG(" ");
00258
00259 segment_number = fk_solver_->segmentNameToIndex(link_name);
00260
00261 }
00262
00263 void ChompRobotModel::addCollisionPointsFromLink(const planning_models::KinematicState& state, std::string link_name, double clearance)
00264 {
00265 const planning_models::KinematicState::LinkState* link_state = state.getLinkState(link_name);
00266 if(link_state == NULL) {
00267 ROS_WARN_STREAM("Collision link " << link_name << " not valid");
00268 return;
00269 }
00270
00271 bodies::Body* body = bodies::createBodyFromShape(link_state->getLinkModel()->getLinkShape());
00272 body->setPadding(monitor_->getEnvironmentModel()->getCurrentLinkPadding(link_state->getName()));
00273 body->setPose(link_state->getGlobalLinkTransform());
00274 body->setScale(1.0);
00275 bodies::BoundingCylinder cyl;
00276 body->computeBoundingCylinder(cyl);
00277 delete body;
00278
00279 std::vector<int> active_joints;
00280 KDL::SegmentMap::const_iterator segment_iter = kdl_tree_.getSegment(link_name);
00281 int segment_number;
00282
00283 ROS_DEBUG_STREAM("Link " << link_name << " length " << cyl.length << " radius " << cyl.radius);
00284
00285 getLinkInformation(link_name, active_joints, segment_number);
00286 std::vector<ChompCollisionPoint>& collision_points_vector = link_collision_points_.find(link_name)->second;
00287
00288
00289
00290 int first_child=1;
00291
00292 for (std::vector<KDL::SegmentMap::const_iterator>::const_iterator child_iter = segment_iter->second.children.begin();
00293 child_iter!= segment_iter->second.children.end(); ++child_iter)
00294 {
00295
00296
00297 KDL::Vector joint_origin = (*child_iter)->second.segment.getJoint().JointOrigin();
00298 ROS_DEBUG("joint origin for %s is %f %f %f\n", (*child_iter)->first.c_str(), joint_origin.x(), joint_origin.y(), joint_origin.z());
00299
00300
00301 double spacing = cyl.radius;
00302 double distance = joint_origin.Norm();
00303 distance+=cyl.length;
00304 int num_points = ceil(distance/spacing)+1;
00305 spacing = distance/(num_points-1.0);
00306
00307 KDL::Vector point_pos;
00308 for (int i=0; i<num_points; i++)
00309 {
00310 if (!first_child && i==0)
00311 continue;
00312 point_pos = joint_origin * (double)(i/(num_points-1.0));
00313 collision_points_vector.push_back(ChompCollisionPoint(active_joints, cyl.radius, clearance, segment_number, point_pos));
00314 ROS_DEBUG_STREAM("Point pos is " << point_pos.x() << " " << point_pos.y() << " " << point_pos.z());
00315 if(max_radius_clearance_ < cyl.radius) {
00316 max_radius_clearance_ = cyl.radius+clearance;
00317 }
00318 }
00319
00320 first_child = 0;
00321 }
00322
00323 ROS_DEBUG_STREAM("Link " << link_name << " has " << collision_points_vector.size() << " points");
00324
00325 }
00326
00327 bool ChompRobotModel::ChompPlanningGroup::addCollisionPoint(ChompCollisionPoint& collision_point, ChompRobotModel& robot_model)
00328 {
00329
00330 std::vector<int> parent_joints(num_joints_, 0);
00331
00332
00333
00334
00335 bool add_this_point=false;
00336 for (int i=0; i<num_joints_; i++)
00337 {
00338 if (collision_point.isParentJoint(chomp_joints_[i].kdl_joint_index_))
00339 {
00340 add_this_point = true;
00341 break;
00342 }
00343 }
00344
00345 if (!add_this_point)
00346 return false;
00347
00348 collision_points_.push_back(ChompCollisionPoint(collision_point, collision_point.getParentJoints()));
00349
00350 return true;
00351
00352 }
00353
00354 void ChompRobotModel::getLinkCollisionPoints(std::string link_name, std::vector<ChompCollisionPoint>& points)
00355 {
00356 std::map<std::string, std::vector<ChompCollisionPoint> >::iterator it = link_collision_points_.find(link_name);
00357 if (it==link_collision_points_.end())
00358 return;
00359
00360 points = it->second;
00361 }
00362
00363
00364
00365
00366
00367
00368
00369 void ChompRobotModel::generateLinkCollisionPoints()
00370 {
00371
00372 link_collision_points_.clear();
00373
00374 if(!node_handle_.hasParam("collision_links")) {
00375 ROS_WARN_STREAM("No collision link param specified");
00376 return;
00377 }
00378
00379 std::string all_links_string;
00380
00381 node_handle_.getParam("collision_links", all_links_string);
00382
00383 std::list<std::string> all_links_list;
00384
00385 std::stringstream link_name_stream(all_links_string);
00386 while(link_name_stream.good() && !link_name_stream.eof()){
00387 std::string lname;
00388 link_name_stream >> lname;
00389 if(lname.size() == 0) continue;
00390 all_links_list.push_back(lname);
00391 }
00392
00393 planning_models::KinematicState state(monitor_->getKinematicModel());
00394 monitor_->setStateValuesFromCurrentValues(state);
00395
00396 for(std::list<std::string>::iterator it = all_links_list.begin();
00397 it != all_links_list.end();
00398 it++) {
00399 addCollisionPointsFromLink(state, *it, collision_clearance_default_);
00400 }
00401 }
00402
00403 void ChompRobotModel::generateAttachedObjectCollisionPoints(const motion_planning_msgs::RobotState* robot_state) {
00404
00405 if(robot_state == NULL) {
00406 ROS_ERROR("Must have robot state to generate collision points from attached objects");
00407 return;
00408 }
00409
00410 planning_models::KinematicState state(monitor_->getKinematicModel());
00411
00412 monitor_->setRobotStateAndComputeTransforms(*robot_state, state);
00413
00414
00415 btTransform id;
00416 id.setIdentity();
00417 state.getJointState(monitor_->getKinematicModel()->getRoot()->getName())->setJointStateValues(id);
00418 state.updateKinematicLinks();
00419
00420
00421 for (vector<string>::const_iterator link_it=monitor_->getCollisionModels()->getGroupLinkUnion().begin();
00422 link_it!=monitor_->getCollisionModels()->getGroupLinkUnion().end(); ++link_it)
00423 {
00424 std::string link_name = *link_it;
00425 std::vector<int> active_joints;
00426 int segment_number;
00427
00428 getLinkInformation(link_name, active_joints, segment_number);
00429 std::vector<ChompCollisionPoint>& collision_points_vector = link_attached_object_collision_points_.find(link_name)->second;
00430
00431 collision_points_vector.clear();
00432
00433 const std::vector<const planning_models::KinematicState::AttachedBodyState*>& att_vec = state.getAttachedBodyStateVector();
00434 for(unsigned int i = 0; i < att_vec.size(); i++)
00435 {
00436 if(link_name == att_vec[i]->getAttachedLinkName())
00437 {
00438 if(robot_state != NULL) {
00439 const unsigned int n = att_vec[i]->getAttachedBodyModel()->getShapes().size();
00440 for(unsigned int j = 0; j < n; j++) {
00441 bodies::Body *body = bodies::createBodyFromShape(att_vec[i]->getAttachedBodyModel()->getShapes()[j]);
00442 body->setPadding(monitor_->getEnvironmentModel()->getCurrentLinkPadding("attached"));
00443
00444 geometry_msgs::PoseStamped pose_global;
00445 pose_global.header.stamp = robot_state->joint_state.header.stamp;
00446 pose_global.header.frame_id = reference_frame_;
00447 tf::poseTFToMsg(att_vec[i]->getGlobalCollisionBodyTransforms()[j], pose_global.pose);
00448
00449 geometry_msgs::PoseStamped pose_link;
00450 monitor_->getTransformListener()->transformPose(link_name, pose_global, pose_link);
00451
00452 btTransform pose;
00453 tf::poseMsgToTF(pose_link.pose, pose);
00454
00455 body->setPose(pose);
00456 ROS_INFO_STREAM("Should have a padding of " << monitor_->getEnvironmentModel()->getCurrentLinkPadding("attached"));
00457 bodies::BoundingCylinder bounding_cylinder;
00458 body->computeBoundingCylinder(bounding_cylinder);
00459
00460 KDL::Rotation rotation = KDL::Rotation::Quaternion(pose_link.pose.orientation.x,
00461 pose_link.pose.orientation.y,
00462 pose_link.pose.orientation.z,
00463 pose_link.pose.orientation.w);
00464 KDL::Vector position(pose_link.pose.position.x, pose_link.pose.position.y, pose_link.pose.position.z);
00465 KDL::Frame f(rotation, position);
00466
00467 double radius = bounding_cylinder.radius;
00468 double length = bounding_cylinder.length;
00469 KDL::Vector p(0,0,0);
00470 KDL::Vector p2;
00471 double spacing = radius/2.0;
00472 int num_points = ceil(length/spacing)+1;
00473 spacing = length/(num_points-1.0);
00474 for (int i=0; i<num_points; ++i) {
00475 p(2) = -length/2.0 + i*spacing;
00476 p2 = f*p;
00477 collision_points_vector.push_back(ChompCollisionPoint(active_joints, radius, collision_clearance_default_, segment_number, p2));
00478 }
00479 delete body;
00480 }
00481 }
00482 }
00483 }
00484 }
00485 }
00486
00487 void ChompRobotModel::populatePlanningGroupCollisionPoints() {
00488
00489 for (std::map<std::string, ChompPlanningGroup>::iterator group_it=planning_groups_.begin(); group_it!=planning_groups_.end(); ++group_it)
00490 {
00491
00492 group_it->second.collision_points_.clear();
00493
00494 ROS_DEBUG_STREAM("Group is " << group_it->first);
00495
00496
00497
00498
00499
00500 for (vector<string>::const_iterator link_name_it=monitor_->getCollisionModels()->getGroupLinkUnion().begin();
00501 link_name_it!=monitor_->getCollisionModels()->getGroupLinkUnion().end(); ++link_name_it)
00502 {
00503 std::map<std::string, std::vector<ChompCollisionPoint> >::iterator link_it = link_collision_points_.find(*link_name_it);
00504 if (link_it != link_collision_points_.end())
00505 {
00506 ROS_DEBUG_STREAM("Adding points for link " << *link_name_it << " point num " << link_it->second.size());
00507 for (std::vector<ChompCollisionPoint>::iterator point_it=link_it->second.begin(); point_it!=link_it->second.end(); ++point_it)
00508 {
00509 if(group_it->second.addCollisionPoint(*point_it, *this)) {
00510 ROS_DEBUG_STREAM("Adding point " << group_it->second.collision_points_.size()-1 << " from link " << *link_name_it);
00511 }
00512 }
00513 } else {
00514
00515 }
00516 link_it = link_attached_object_collision_points_.find(*link_name_it);
00517 if (link_it != link_attached_object_collision_points_.end())
00518 {
00519 ROS_DEBUG("\t%s", link_it->first.c_str());
00520 for (std::vector<ChompCollisionPoint>::iterator point_it=link_it->second.begin(); point_it!=link_it->second.end(); ++point_it)
00521 {
00522 group_it->second.addCollisionPoint(*point_it, *this);
00523 }
00524 }
00525 }
00526 ROS_DEBUG_STREAM("Group " << group_it->first << " point num " << group_it->second.collision_points_.size());
00527 }
00528 }
00529
00530
00531
00532
00533
00534
00535
00536
00537
00538
00539
00540
00541
00542
00543
00544
00545
00546
00547
00548
00549
00550
00551
00552
00553
00554
00555
00556
00557
00558
00559
00560
00561
00562
00563
00564
00565
00566
00567
00568
00569
00570
00571
00572
00573
00574
00575
00576
00577 }