对应的片段:
1 2 3 4 5 6 7 8 9 10 11 12
| obstacles_.clear();
if (costmap_converter_) updateObstacleContainerWithCostmapConverter(); else updateObstacleContainerWithCostmap();
updateObstacleContainerWithCustomObstacles();
|
obstacles_
来源于两部分:
来自代价地图updateObstacleContainerWithCostmap()
或者 CostmapConverter 的updateObstacleContainerWithCostmapConverter()
来自用户发布的障碍物消息updateObstacleContainerWithCustomObstacles()
分别由参数include_costmap_obstacles
和 costmap_converter_plugin
决定,还有动态障碍include_dynamic_obstacles
。 之后又对应buildGraph
中的AddEdgesObstacles
与AddEdgesDynamicObstacles
其实目前用的是costmap_converter
updateObstacleContainerWithCostmap
获得当前朝向的单位向量
1 2 3 4
| Eigen::Vector2d PoseSE2::orientationUnitVec() const { return Eigen::Vector2d(std::cos(_theta), std::sin(_theta) ); }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| if (cfg_.obstacles.include_costmap_obstacles) { Eigen::Vector2d robot_orient = robot_pose_.orientationUnitVec(); for (unsigned int i=0; i<costmap_->getSizeInCellsX()-1; ++i) { for (unsigned int j=0; j<costmap_->getSizeInCellsY()-1; ++j) { if (costmap_->getCost(i,j) == costmap_2d::LETHAL_OBSTACLE) { Eigen::Vector2d obs; costmap_->mapToWorld(i,j, obs.coeffRef(0), obs.coeffRef(1));
Eigen::Vector2d obs_dir = obs - robot_pose_.position(); if ( obs_dir.dot(robot_orient) < 0 && obs_dir.norm() > cfg_.obstacles.costmap_obstacles_behind_robot_dist ) continue; obstacles_.push_back(ObstaclePtr(new PointObstacle(obs))); } } } }
|
这里是参数include_costmap_obstacles
唯一出现的地方。 参数costmap_obstacles_behind_robot_dist
默认是1.
函数根据costmap中的障碍物信息更新障碍物容器。在这里,可以找到前方距离障碍物的最短距离。然后根据该距离值调整max_vel_x
,这样优化时最大线速度的约束会随着障碍物的远近而调整,在一定程度上会改善避障效果。
自定义障碍
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81
| void TebLocalPlannerROS::updateObstacleContainerWithCustomObstacles() { boost::mutex::scoped_lock l(custom_obst_mutex_); if (!custom_obstacle_msg_.obstacles.empty()) { Eigen::Affine3d obstacle_to_map_eig; try { tf::StampedTransform obstacle_to_map; tf_->waitForTransform(global_frame_, ros::Time(0), custom_obstacle_msg_.header.frame_id, ros::Time(0), custom_obstacle_msg_.header.frame_id, ros::Duration(0.5) ); tf_->lookupTransform(global_frame_, ros::Time(0), custom_obstacle_msg_.header.frame_id, ros::Time(0), custom_obstacle_msg_.header.frame_id, obstacle_to_map); tf::transformTFToEigen(obstacle_to_map, obstacle_to_map_eig); } catch (tf::TransformException ex) { ROS_ERROR("%s",ex.what()); obstacle_to_map_eig.setIdentity(); } for (size_t i=0; i<custom_obstacle_msg_.obstacles.size(); ++i) { if (custom_obstacle_msg_.obstacles.at(i).polygon.points.size() == 1 && custom_obstacle_msg_.obstacles.at(i).radius > 0 ) { Eigen::Vector3d pos( custom_obstacle_msg_.obstacles.at(i).polygon.points.front().x, custom_obstacle_msg_.obstacles.at(i).polygon.points.front().y, custom_obstacle_msg_.obstacles.at(i).polygon.points.front().z ); obstacles_.push_back(ObstaclePtr(new CircularObstacle( (obstacle_to_map_eig * pos).head(2), custom_obstacle_msg_.obstacles.at(i).radius) ) ); } else if (custom_obstacle_msg_.obstacles.at(i).polygon.points.size() == 1 ) { Eigen::Vector3d pos( custom_obstacle_msg_.obstacles.at(i).polygon.points.front().x, custom_obstacle_msg_.obstacles.at(i).polygon.points.front().y, custom_obstacle_msg_.obstacles.at(i).polygon.points.front().z ); obstacles_.push_back(ObstaclePtr(new PointObstacle( (obstacle_to_map_eig * pos).head(2) ))); } else if (custom_obstacle_msg_.obstacles.at(i).polygon.points.size() == 2 ) { Eigen::Vector3d line_start( custom_obstacle_msg_.obstacles.at(i).polygon.points.front().x, custom_obstacle_msg_.obstacles.at(i).polygon.points.front().y, custom_obstacle_msg_.obstacles.at(i).polygon.points.front().z ); Eigen::Vector3d line_end( custom_obstacle_msg_.obstacles.at(i).polygon.points.back().x, custom_obstacle_msg_.obstacles.at(i).polygon.points.back().y, custom_obstacle_msg_.obstacles.at(i).polygon.points.back().z ); obstacles_.push_back(ObstaclePtr(new LineObstacle( (obstacle_to_map_eig * line_start).head(2), (obstacle_to_map_eig * line_end).head(2) ) ) ); } else if (custom_obstacle_msg_.obstacles.at(i).polygon.points.empty()) { ROS_WARN("Invalid custom obstacle received. List of polygon vertices is empty. Skipping..."); continue; } else { PolygonObstacle* polyobst = new PolygonObstacle; for (size_t j=0; j<custom_obstacle_msg_.obstacles.at(i).polygon.points.size(); ++j) { Eigen::Vector3d pos( custom_obstacle_msg_.obstacles.at(i).polygon.points[j].x, custom_obstacle_msg_.obstacles.at(i).polygon.points[j].y, custom_obstacle_msg_.obstacles.at(i).polygon.points[j].z ); polyobst->pushBackVertex( (obstacle_to_map_eig * pos).head(2) ); } polyobst->finalizePolygon(); obstacles_.push_back(ObstaclePtr(polyobst)); } if(!obstacles_.empty()) { obstacles_.back()->setCentroidVelocity(custom_obstacle_msg_.obstacles[i].velocities, custom_obstacle_msg_.obstacles[i].orientation); obstacles_.back()->setDynamic(); } } } }
|
消息costmap_converter/ObstacleArrayMsg
定义:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| std_msgs/Header header costmap_converter/ObstacleMsg[] obstacles
std_msgs/Header header
geometry_msgs/Polygon polygon
float64 radius
int64 id
geometry_msgs/Quaternion orientation
geometry_msgs/TwistWithCovariance velocities
|
类Obstacle
定义在obstacle.h
,派生类有PointObstacle
, CircularObstacle
, LineObstacle
,PolygonObstacle
1 2
| typedef boost::shared_ptr<Obstacle> ObstaclePtr; typedef std::vector<ObstaclePtr> ObstContainer;
|