基于已知建图的算法

覆盖栅格建图算法的实现


文章参考了机器人学习–栅格地图(occupancy grid map)构建(部分代码解析)

前言


在完成深蓝学院激光SLAM课程第七章——基于已知建图的算法过程中,根据栅格建图算法实现建图。但是建图效果不理想,出现以下问题:建图效果不理想,边缘特征不明显。

一、基于已知建图的算法

改进前的算法:

//占据栅格地图
void OccupanyMapping(std::vector<GeneralLaserScan>& scans,std::vector<Eigen::Vector3d>& robot_poses)
{
    //枚举所有的激光雷达数据
    for(int i = 0; i < scans.size();i++)
    {
        GeneralLaserScan scan = scans[i];
        Eigen::Vector3d robotPose = robot_poses[i];

        //机器人的下标robotIndex
        //从世界坐标系到栅格坐标系
        //robotPose的[x,y,z]中的[x,y](也就是下面的robotPose(0),robotPose(1))
        GridIndex robotIndex = ConvertWorld2GridIndex(robotPose(0),robotPose(1));

        for(int id = 0; id < scan.range_readings.size();id++)
        {
            double dist = scan.range_readings[id];  //得到该帧激光雷达的距离
            double angle = scan.angle_readings[id]; //得到该帧激光雷达的角度

            //剔除异常数据,跳过该次循环,不作处理
            if(std::isinf(dist) || std::isnan(dist)) continue;

            //计算得到该激光点的世界坐标系的坐标
            double theta = robotPose(2);    //机器人的航向角
            double laser_x = dist * cos(angle);
            double laser_y = dist * sin(angle);

            double world_x = cos(theta) * laser_x - sin(theta) * laser_y + robotPose(0);
            double world_y = sin(theta) * laser_x + cos(theta) * laser_y + robotPose(1);

            //start of TODO 对对应的map的cell进行更新.
            /*目前已知:1、激光点在世界坐标系的坐标world_x   world_y
                      2、每帧机器人位姿对应栅格地图robotIndex
             */

            //1、将转化后的激光数据再映射到栅格坐标系下去 得到每个激光点的栅格序号Index
            GridIndex laserIndex = ConvertWorld2GridIndex(world_x,world_y);
            //2、判断该激光数据的栅格index是否在设定的900*900的区域內
            if(isValidGridIndex(laserIndex) == false)
                continue;//跳过当前这次循环
            //3、寻找激光点和机器人对应的栅格之间的空闲栅格 将空闲(free)栅格序号存入到freeIndex中
            std::vector<GridIndex> freeIndex = TraceLine(robotIndex.x,robotIndex.y,laserIndex.x,laserIndex.y);

            //4、处理空闲栅格
            for(int i = 0;i < freeIndex.size(); i++)
            {
                GridIndex tmpIndex = freeIndex[i];
                //将空闲栅格的栅格序号,转化到数组序号,该数组用于存储每一个栅格的数据
                int linearIndex = GridIndexToLinearIndex(tmpIndex);
                //得到该空闲栅格的数据(初始默认50)
                int data = pMap[linearIndex];
                if(data>0)
                    data += mapParams.log_free;
                else
                    data = 0;
                pMap[linearIndex] = data;
            }
            //5、处理占据栅格
            if(pMap[GridIndexToLinearIndex(laserIndex)]<100)
                pMap[GridIndexToLinearIndex(laserIndex)] += mapParams.log_occ;
            else
                pMap[GridIndexToLinearIndex(laserIndex)] = 100;
            //end of TODO
        }
    }
}

改进前的建图效果:

在这里插入图片描述

二、原因

1、出问题的代码:

            double world_y = sin(theta) * laser_x + cos(theta) * laser_y + robotPose(1);

此处world_y中少了一个符号,应改为下面的代码:

            double world_y = -(sin(theta) * laser_x + cos(theta) * laser_y) + robotPose(1);

2、原因分析:

在这里插入图片描述
如上图:激光点的坐标是基于当前机器人坐标系的,因此需要将其转化到世界坐标系下。因此才有了代码:

	//计算得到该激光点在世界坐标系的坐标
	double theta = robotPose(2);    //机器人的航向角
	double laser_x = dist * cos(angle);
	double laser_y = dist * sin(angle);

	double world_x = cos(theta) * laser_x - sin(theta) * laser_y + robotPose(0);
	double world_y = sin(theta) * laser_x + cos(theta) * laser_y + robotPose(1);

注:这里的robotPose对应机器人模型(x,y,θ),robotPose(0)是x,robotPose(1)是y
theta是机器人(x,y,θ)中的θ
为什么需要加符号“-”?
原因: 这里的世界坐标系world_x,不是真实的世界坐标系,而是像素坐标系,y轴与真实的世界坐标系相反,这样是laser_y加负号的原因

三、改进后的建图效果

修改代码后的效果如下图:
在这里插入图片描述

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值