在Ego-Planner 中 如何根据索引值来判断有无障碍物

1.Gridmap 地图数据存储

首先我们需要大概了解在Ego-Planner 地图信息是怎么存储的。定义了一个名为MappingData的数据结构,用于存储地图和相关信息

其中 

std::vector<double> occupancy_buffer_;
//存储地图中每个体素(voxel)的占据信息 double类型
std::vector<char> occupancy_buffer_inflate_;
//存储的是膨胀后的占据信息 char类型

完整代码如下:

struct MappingData {
  // main map data, occupancy of each voxel and Euclidean distance

  std::vector<double> occupancy_buffer_;
  std::vector<char> occupancy_buffer_inflate_;

  // camera position and pose data

  Eigen::Vector3d camera_pos_, last_camera_pos_;
  Eigen::Matrix3d camera_r_m_, last_camera_r_m_;
  Eigen::Matrix4d cam2body_;

  // depth image data

  cv::Mat depth_image_, last_depth_image_;
  int image_cnt_;

  // flags of map state

  bool occ_need_update_, local_updated_;
  bool has_first_depth_;
  bool has_odom_, has_cloud_;

  // odom_depth_timeout_
  ros::Time last_occ_update_time_;
  bool flag_depth_odom_timeout_;
  bool flag_use_depth_fusion;

  // depth image projected point cloud

  vector<Eigen::Vector3d> proj_points_;
  int proj_points_cnt;

  // flag buffers for speeding up raycasting

  vector<short> count_hit_, count_hit_and_miss_;
  vector<char> flag_traverse_, flag_rayend_;
  char raycast_num_;
  queue<Eigen::Vector3i> cache_voxel_;

  // range of updating grid

  Eigen::Vector3i local_bound_min_, local_bound_max_;

  // computation time

  double fuse_time_, max_fuse_time_;
  int update_num_;

  EIGEN_MAKE_ALIGNED_OPERATOR_NEW
};

通过 : 来设置地图尺寸的大小 

node_.param("grid_map/resolution", mp_.resolution_, -1.0);

node_.param("grid_map/map_size_x", x_size, -1.0);

node_.param("grid_map/map_size_y", y_size, -1.0);

node_.param("grid_map/map_size_z", z_size, -1.0);

关于resolution 它指定了地图的分辨率,即在地图中一个体素(voxel)代表的实际空间的大小。分辨率通常以米/体素(meters per voxel)为单位表示 较低的分辨率会导致地图更粗糙,而较高的分辨率会导致地图更细致,

上面这些参数的值可以根据应用需求进行配置。例如,如果你的应用需要一个非常精细的地图,你可以选择较小的分辨率,以及更大的尺寸值,以覆盖更广阔的地理范围。如果你的应用只关注一个小区域的地图,可以选择更大的分辨率和较小的尺寸。

mp_.map_size_ = Eigen::Vector3d(x_size, y_size, z_size);

使用mp_.map_voxel_num_(i)来存储了地图在维度i上的体素(Voxel)数量

for (int i = 0; i < 3; ++i)

mp_.map_voxel_num_(i) = ceil(mp_.map_size_(i) / mp_.resolution_);

occupancy_buffer_occupancy_buffer_inflate_ 将在后续的地图构建和更新过程中用于存储地图的占据信息和其他相关数据。初始化时,它们都被赋予了初始值,然后随着地图的更新和修改而不断变化。地图的占据信息通常表示了每个体素被占据的程度,可以用于导航、碰撞检测和环境建模等任务。

int buffer_size = mp_.map_voxel_num_(0) * mp_.map_voxel_num_(1) * mp_.map_voxel_num_(2); // 计算体积

md_.occupancy_buffer_ = vector<double>(buffer_size, mp_.clamp_min_log_ - mp_.unknown_flag_);

md_.occupancy_buffer_inflate_ = vector<char>(buffer_size, 0); //buffer_size大的一个容器(也就相当于一个数组) 初始值为0 

通过toAddress()将三维空间的用于将三维空间中的体素坐标 (Eigen::Vector3i 类型) 转换为一维数组中的地址(索引)

inline int GridMap::toAddress(const Eigen::Vector3i& id) {

return id(0) * mp_.map_voxel_num_(1) * mp_.map_voxel_num_(2) + id(1) * mp_.map_voxel_num_(2) + id(2);

}

2. 检查是否是障碍物

在A star 搜索时 可以 使用checkOccupancy()函数用于检查指定位置是否为障碍物或被占据。没有被占用返回false 

inline bool checkOccupancy(const Eigen::Vector3d &pos) 
	{ 
		return (bool)grid_map_->getInflateOccupancy(pos); 

	}

通过getInflateOccupancy(Eigen::Vector3d pos) 来获取膨胀后的体素占用信息 

inline int GridMap::getInflateOccupancy(Eigen::Vector3d pos) {
  if (!isInMap(pos)) return -1;
    //isInMap(pos) 判断这个点是否处于地图之中

  Eigen::Vector3i id;

  posToIndex(pos, id); //转换为index 

  return int(md_.occupancy_buffer_inflate_[toAddress(id)]);
    //一般栅格地图 0表示 未被占据  1 表示占据 -1 表示为定义
}


inline int GridMap::toAddress(const Eigen::Vector3i& id) {
  return id(0) * mp_.map_voxel_num_(1) * mp_.map_voxel_num_(2) + id(1) * mp_.map_voxel_num_(2) + id(2);
}
// map_voxel_num_    map range in index
//将三维空间点转换为一维数组的索引值

  • 3
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Ego-Planner是一个基于ROS的路径规划器,它可以在给定的地图和起点、终点信息下,生成一条可行的路径。以下是Ego-Planner的代码框架: 1. 首先需要定义一个EgoPlanner类,其包含了一些必要的成员变量和函数。 ```c++ class EgoPlanner { private: ros::NodeHandle nh_; ros::Subscriber sub_map_; ros::Subscriber sub_pose_; ros::Subscriber sub_goal_; ros::Publisher pub_path_; nav_msgs::OccupancyGrid map_; geometry_msgs::PoseStamped start_; geometry_msgs::PoseStamped goal_; public: EgoPlanner(); // 构造函数 ~EgoPlanner(); // 析构函数 void mapCallback(const nav_msgs::OccupancyGrid::ConstPtr& msg); // 地图回调函数 void poseCallback(const geometry_msgs::PoseStamped::ConstPtr& msg); // 当前位置回调函数 void goalCallback(const geometry_msgs::PoseStamped::ConstPtr& msg); // 目标位置回调函数 void plan(); // 路径规划函数 }; ``` 2. 在构造函数,需要完成ROS节点的初始化、订阅和发布话题的设置。 ```c++ EgoPlanner::EgoPlanner() { nh_ = ros::NodeHandle("~"); sub_map_ = nh_.subscribe("map", 1, &EgoPlanner::mapCallback, this); sub_pose_ = nh_.subscribe("pose", 1, &EgoPlanner::poseCallback, this); sub_goal_ = nh_.subscribe("goal", 1, &EgoPlanner::goalCallback, this); pub_path_ = nh_.advertise<nav_msgs::Path>("path", 1); } ``` 3. 在地图、当前位置和目标位置的回调函数,需要将接收到的信息保存到对应的成员变量。 ```c++ void EgoPlanner::mapCallback(const nav_msgs::OccupancyGrid::ConstPtr& msg) { map_ = *msg; } void EgoPlanner::poseCallback(const geometry_msgs::PoseStamped::ConstPtr& msg) { start_ = *msg; } void EgoPlanner::goalCallback(const geometry_msgs::PoseStamped::ConstPtr& msg) { goal_ = *msg; } ``` 4. 在路径规划函数,需要调用路径规划算法,生成一条可行的路径,并将路径发布出去。 ```c++ void EgoPlanner::plan() { // 调用路径规划算法,生成一条可行的路径 std::vector<geometry_msgs::PoseStamped> path = pathPlanning(map_, start_, goal_); // 将路径发布出去 nav_msgs::Path path_msg; path_msg.header.frame_id = "map"; path_msg.header.stamp = ros::Time::now(); path_msg.poses = path; pub_path_.publish(path_msg); } ``` 5. 在主函数,创建EgoPlanner对象,并进入ROS循环。 ```c++ int main(int argc, char** argv) { ros::init(argc, argv, "ego_planner"); EgoPlanner planner; ros::Rate rate(10); while (ros::ok()) { planner.plan(); ros::spinOnce(); rate.sleep(); } return 0; } ``` 以上就是Ego-Planner的代码框架,其路径规划算法需要根据具体情况进行选择和实现。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值