2D 激光 SLAM-Cartographer 实战

源码

https://github.com/cartographer-project/cartographer
https://github.com/cartographer-project/cartographer_ros
课 程 下 的 注 释 版 代 码 :
https://github.com/xiangli0608/cartographer_detailed_comments_ws
备用地址:
https://gitee.com/LauZanMo/cartographer
https://gitee.com/xiaojake/cartographer_ros
论文地址:https://ieeexplore.ieee.org/document/7487258
cartographer 整体可以分为三个部分:
一是 input sensor data,也就是读取单线激光雷达的 scan、轮速计的输入以及 IMU,
二是 Local SLAM 部分,也被称为前端。 该部分的主要任务是建立维护子地图(Submaps),
但 问 题 是 该 部 分 建 图 误 差 会 随 着 时 间 累 积 。 该 部 分 相 关 的 参 数 定 义 在
/src/cartographer/configuration_files/trajectory_builder_2d.lua
/src/cartographer/configuration_files/trajectory_builder_3d.lua 中。
三是 Global SLAM 部分,也称为后端. 该部分的主要任务是进行 Loop Closure。闭环检测本
质上也是一个优化问题,文中将其表达成了 pixel-accurate match 的形式,采用 Branch-and
Bound Approach (BBA)的方法来解决。具体使用 Branch-and-Bound 方法,可以参见论
Real-Time Loop Closure in 2D LIDAR
SLAM(https://ieeexplore.ieee.org/document/7487258)。如果是 3D 情况下,该部分还负责根
据 IMU 数据找出重力的方向。
可以看出,从传感器出发,Laser 的数据经过两个滤波器后进行 Scan Matching,用来构建子
图 submap, 而新的 Laser Scan 进来后也会插入到已经维护着的子图的适当位置。如何决定
插入的最优位姿,就是通过 Ceres Scan Matching 来实现的。估计出来的最优位姿也会与里
程计和 IMU 数据融合,用来估计下一时刻的位姿。
总体而言,Local Slam 部分负责生成较好的子图,而 Global Slam 部分进行全局优化,将不
同的子图以最匹配的位姿连接在一起。

Cartographer 安装编译与 demo 运行

#下载 https://github.com/abseil/abseil-cpp
cd abseil-cpp
mkdir build && cd build
cmake ..
make
sudo make install
# 安装 abseil 的动态库:可以将之前的 build 文件夹删掉,重新建立 build 文
件夹
mkdir build && cd build
cmake .. -DBUILD_SHARED_LIBS=ON
make
sudo make install
#安装其他依赖
sudo apt-get update
sudo apt-get install -y python-wstool python-rosdep ninja-build
sudo apt-get install cmake
sudo apt-get install build-essential
sudo apt-get install libgoogle-glog-dev
sudo apt-get install libatlas-base-dev
# 创建 cartographer_ws 工作空间,并将以下三个链接都拷到 src 文件夹里:
# https://github.com/cartographer-project/cartographer
# https://github.com/cartographer-project/cartographer_ros
# https://github.com/ceres-solver/ceres-solver
#编译 ceres
cd ceres-solver
mkdir ceres-bin
cd ceres-bin
cmake ..
make
make test
sudo make install
#安装 protobuf3 https://github.com/protocolbuffers/protobuf/releases
cd protobuf
mkdir build
cd build
cmake -G Ninja \
-DCMAKE_POSITION_INDEPENDENT_CODE=ON \
cvlife.net -DCMAKE_BUILD_TYPE=Release \
-Dprotobuf_BUILD_TESTS=OFF \
../cmake
ninja
sudo ninja install
#构建 cartographer 工作空间
mkdir -p cartographer_ws/src
cd cartographer_ws/src
catkin_init_workspace
#cartographer 编译
cd cartographer_ws
rosdep update
rosdep install --from-paths src --ignore-src --
rosdistro=${ROS_DISTRO} -y
#Build and install.这一步会花费很长的时间,耐心等待
catkin_make_isolated --install --use-ninja
source install_isolated/setup.bash
#运行测试
wget -P ~/Downloads https://storage.googleapis.com/cartographer
public-data/bags/backpack_2d/cartographer_paper_deutsches_museum.bag
roslaunch cartographer_ros demo_backpack_2d.launch
bag_filename:=${HOME}/Downloads/cartographer_paper_deutsches_museum.bag

Cartographer 保存轨迹

#保存轨迹
#思路:在使用 cartographer 建图的过程中,找到 cartographer 提供的
“/trajectory_query” 服务(可以用“rosrun rqt_service_caller
rqt_service_caller”命令),请求后会得到当前轨迹每一帧的位姿。在源码
中找到这部分内容,将其保存为 txt 文件即可。
#方法:源码 node.cc 中,修改 HandleTrajectoryQuery 函数:
bool Node::HandleTrajectoryQuery(
::cartographer_ros_msgs::TrajectoryQuery::Request& request,
::cartographer_ros_msgs::TrajectoryQuery::Response& response) {
cvlife.net absl::MutexLock lock(&mutex_);
response.status = TrajectoryStateToStatus(
request.trajectory_id,
{TrajectoryState::ACTIVE, TrajectoryState::FINISHED,
TrajectoryState::FROZEN} /* valid states */);
if (response.status.code != cartographer_ros_msgs::StatusCode::OK)
{
LOG(ERROR) << "Can't query trajectory from pose graph: "
<< response.status.message;
return true;
}
map_builder_bridge_.HandleTrajectoryQuery(request, response);
// 保存轨迹为 txt 文件
std::cout << "receiving" << std::endl;
std::string txt_filename = "/home/xxx/xxx.txt";
std::ofstream outf(txt_filename, std::ios::app);
for (int i = 0; i < response.trajectory.size(); i++){
int32_t sec = response.trajectory[i].header.stamp.sec;
int32_t nsec = response.trajectory[i].header.stamp.nsec;
double x = response.trajectory[i].pose.position.x;
double y = response.trajectory[i].pose.position.y;
double z = response.trajectory[i].pose.position.z;
outf << std::setprecision(20) << sec << "." << nsec << " " << x
<< " " << y << " " << z << std::endl;
}
return true;
}
rosrun rqt_service_caller rqt_service_caller
#选择/trajectory query 即可
#评估
evo_ape tum gt.txt result.txt -vap
#通常使用绝对轨迹误差的 RMSE 来衡量算法的定位精度
#保存 pgm 珊格地图
rosrun map_server map_saver
传感器实测方法及常见问题
参考 https://blog.csdn.net/weixin_44314245/article/details/110881565
https://blog.csdn.net/Darcy_MFFL/article/details/112433149
https://blog.csdn.net/weixin_42576673/article/details/107280930

Cartographer 工程化建议

rplidar 适配 cartographer 的方式:
1.修改 cartgrapher_ros/cartprapher_files 下的 revo_lds.lua 文件,把下面的两个配置选项替换
成“laser”
tracking_frame = "laser",
published_frame = "laser"
2.修改 cartographer_ros 下的 demo_revo_lds.launch 文件
<launch>
<param name="/use_sim_time" value="flase" />
<!-- 首先是 rplidar 节点:因此必须保证是安装了 rplidar_ros -->
<node pkg="rplidar_ros" type="rplidarNode" name="rplidarNode"
output="screen">
<param name="serial_port" type="string"
value="/dev/ttyUSB0"/>
<param name="serial_baudrate" type="int" value="265000"/>
<param name="frame_id" type="string" value="laser"/>
<param name="inverted" type="bool" value="false"/>
<param name="angle_compensate" type="bool" value="true"/>
</node>
<!-- 然后是 cartographer 节点:他在这里调用了 revo_lds.lua 文件,这个文
件我修改了 首先把 “map”改成了“/map” -->
<node name="cartographer_node" pkg="cartographer_ros"
type="cartographer_node" args="
-configuration_directory $(find
cartographer_ros)/configuration_files
-configuration_basename revo_lds.lua"
output="screen">
<remap from="scan" to="scan" />
</node>
<node name="rviz" pkg="rviz" type="rviz" required="true"
args="-d $(find
cartographer_ros)/configuration_files/demo_2d.rviz" />"
</launch>
3.进入工作空间重新编译
catkin_make_isolated --install --use-ninja
4.启动
roslaunch cartographer_ros demo_revo_lds.launch
注释版的
cartographer
源 码 地 址 :
https://github.com/xiangli0608/cartographer_detailed_comments_ws

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/760678.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

企业化运维(6)_redis数据库

Redis&#xff08;Remote Dictionary Server )&#xff0c;即远程字典服务&#xff0c;是一个开源的使用ANSIC语言编写、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库&#xff0c;并提供多种语言的API。 redis是一个key-value存储系统。和Memcached类似&#xff0…

Vuetify3:关于两组件并列刷新变成两行并非一行问题,满足响应式

我们在使用vuetify3 开发站点的时候&#xff0c;我们需要两个组件并排&#xff0c;而且需要满足响应式&#xff1a; 那我们如何解决这个问题呢&#xff1f; 我们在开发的时候&#xff0c;一开始我们直接使用官方提供的弹性布局直接上代码&#xff1a; <template><v…

InnoDB 表空间2---系统表空间

系统表空间 了解完了独立表空间的基本结构&#xff0c;系统表空间的结构也就好理解多了&#xff0c;系统表空间的结构和独立表空间基本类似&#xff0c;只不过由于整个MySQL进程只有一个系统表空间&#xff0c;在系统表空间中会额外记录一些有关整个系统信息的页&#xff0c;所…

docker仓库--centos7.9部署harbor详细过程与使用以及常见问题

文章目录 前言1.docker-compose是什么2.harbor是什么 centos7部署harbor详细过程与使用环境一、部署docker二、部署harbor1.下载docker-compose工具2.harbor安装3.拷贝样本文件&#xff0c;并修改文件4.安装harbor&#xff0c;安装完成自行启动5.查看 三、harbor的使用1.创建项…

「C++系列」C++ 数据类型

文章目录 一、C 数据类型二、C 数据类型占位与范围三、类型转换1. 隐式类型转换&#xff08;Automatic Type Conversion&#xff09;2. 显式类型转换&#xff08;Explicit Type Conversion&#xff09;3. 示例代码 四、数据类型案例1. 整型2. 浮点型3. 字符型4. 布尔型5. 枚举类…

Redis基础教程(四):redis键(key)

&#x1f49d;&#x1f49d;&#x1f49d;首先&#xff0c;欢迎各位来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里不仅可以有所收获&#xff0c;同时也能感受到一份轻松欢乐的氛围&#xff0c;祝你生活愉快&#xff01; &#x1f49d;&#x1f49…

论文阅读之旋转目标检测ARC:《Adaptive Rotated Convolution for Rotated Object Detection》

论文link&#xff1a;link code&#xff1a;code ARC是一个改进的backbone&#xff0c;相比于ResNet&#xff0c;最后的几层有一些改变。 Introduction ARC自适应地旋转以调整每个输入的条件参数&#xff0c;其中旋转角度由路由函数以数据相关的方式预测。此外&#xff0c;还采…

【PL理论深化】(13) 变量与环境:文法结构 | 真假表达式:isZero E | let 表达式叠放 | 定义的规则 | 条件语句的使用

&#x1f4ac; 写在前面&#xff1a;从现在开始&#xff0c;让我们正式设计和实现编程语言。首先&#xff0c;让我们扩展在之前定义的整数表达式语言&#xff0c;以便可以使用变量和条件表达式。 目录 0x00 文法结构 0x01 真假表达式&#xff1a;isZero E 0x02 let 表达式叠…

Leetcode 78 数组子集

题目描述&#xff1a; 给你一个整数数组 nums &#xff0c;数组中的元素 互不相同 。返回该数组所有可能的 子集&#xff08;幂集&#xff09;。 解集 不能 包含重复的子集。你可以按 任意顺序 返回解集。 示例 1&#xff1a; 输入&#xff1a;nums [1,2,3] 输出&#xff1…

Python-数据分析组合可视化实例图【附完整源码】

数据分析组合可视化实例图 开篇&#xff1a;应女朋友的要求&#xff0c;于是写下了这篇详细的数据可视化代码及完整注释 一&#xff1a;柱状图、折线图横向组合网格布局 本段代码使用了pyecharts库来创建一个包含多个图表&#xff08;柱状图、折线图&#xff09;和网格布局的…

服装分销的系统架构

背景 服装的分销规则&#xff1a;组织结构由总公司代理商专卖店构成。总公司全权负责销售业务&#xff0c;并决定给代理商的份额&#xff1b;代理商再给货到专卖店&#xff0c;整个组织机构呈现树状结构&#xff1b;上级机构对下级机构拥有控制权&#xff0c;主要控制其销售的服…

利用谷歌云serverless代码托管服务Cloud Functions构建Gemini Pro API

谷歌在2024年4月发布了全新一代的多模态模型Gemini 1.5 Pro&#xff0c;Gemini 1.5 Pro不仅能够生成创意文本和代码&#xff0c;还能理解、总结上传的图片、视频和音频内容&#xff0c;并且支持高达100万tokens的上下文。在多个基准测试中表现优异&#xff0c;性能超越了ChatGP…

MySQL高阶:事务和并发

事务和并发 1. 事务创建事务 2. 并发和锁定并发问题 3. 事务隔离等级3.1 读取未提交隔离级别3.2 读取已提交隔离级别3.3 重复读取隔离级别3.4 序列化隔离级别 4. 死锁 1. 事务 事务&#xff08;trasaction&#xff09;是完成一个完整事件的一系列SQL语句。这一组SQL语句是一条…

植物大战僵尸融合版2024最新版本登场,绝对能满足你的所有期待!

一开场&#xff0c;就让我们直切主题。各位玩家&#xff0c;是否已对《植物大战僵尸》中的传统植物和僵孠对决失去了新鲜感&#xff1f;是否渴望体验更具创意、更富挑战性的游戏玩法&#xff1f;那么&#xff0c;让我来告诉你&#xff0c;《植物大战僵尸融合版》1新版本的登场&…

AI论文速读 | 2024[KDD]ASeer基于异步时空图卷积网络的不规则交通时间序列预测

题目&#xff1a;Irregular Traffic Time Series Forecasting Based on Asynchronous Spatio-Temporal Graph Convolutional Network 作者&#xff1a;Weijia Zhang, Le Zhang, Jindong Han&#xff08;韩金栋&#xff09;, Hao Liu&#xff08;刘浩&#xff09;, Jingbo Zhou…

纯硬件FOC驱动BLDC

1. 硬件FOC 图 1 为采用 FOC 的方式控制 BLDC 电机的过程&#xff0c;经由 FOC 变换( Clark 与 Park 变换) &#xff0c;将三相电流转换为空间平 行电流 ID 与空间垂直电流 IQ。经过 FOC 逆变化逆( Clark 变换与逆 Park 变换) &#xff0c;将两相电流转换为三相电流用于控 制电…

容器:deque

以下是对于deque容器知识的整理 1、构造 2、赋值 3、大小操作 4、插入 5、删除 6、数据存取 7、排序 #include <iostream> #include <deque> #include <algorithm> using namespace std; /* deque容器&#xff1a;双端数组&#xff0c;可以对头端进行插入删…

网页用事件监听器播放声音

一、什么是监听器&#xff1a; 在前端页面中&#xff0c;事件监听器&#xff08;Event Listener&#xff09;是一种编程机制&#xff0c;它允许开发者指定当特定事件&#xff08;如用户点击按钮、鼠标悬停、页面加载完成等&#xff09;发生时执行特定的代码块。简而言之&#x…

clonezilla(再生龙)克隆物理机linux系统,然后再去另一台电脑安装

前言: 总共需要2个u盘,一个装再生龙系统,一个是使用再生龙把硬盘备份到另一个盘里面,恢复的时候,先使用再生龙引导,然后再插上盘进行复制 1.制作启动u盘 1.1下载再生龙Clonezilla 下載 1.2下载UltraISO(https://cn.ultraiso.net/uiso9_cn.exe) 1.3 打开UltraISO,选择co…

Vue 解决报错 VM6290:1 Uncaught SyntaxError: Unexpected identifier ‘Promise‘

Vue 报错 VM6290:1 Uncaught SyntaxError: Unexpected identifier ‘Promise’ 排查 控制台报了一个错误 , Uncaught SyntaxError: Unexpected identifier ‘Promise’&#xff0c;网上查到的方法是 缺少符号&#xff0c;语法写法错误&#xff0c;但这些都没有解决我的问题&am…