1、Gitclone对应仓库并编译

  • 从下方链接下载:

    https://github.com/XidianLemon/calibration_camera_lidar

    下载后到自己项目的src中,然后正常catkin_make编译:

    提示遇到错误,运行命令sudo apt install ros-noetic-jsk-recognition-msgs即可

    1
    2
    3
    4
    5
    Could not find a package configuration file provided by
    "jsk_recognition_msgs" with any of the following names:

    jsk_recognition_msgsConfig.cmake
    jsk_recognition_msgs-config.cmake

2、仿真中进行录制

  • 参考链接博文,下载场景,并自行导入自己的小车模型,然后开启小车的仿真,录制rosbag

    模型的下载地址:

    1
    https://pan.baidu.com/s/1H314s6Hn-bY1qFphinnNrg?pwd=2022

    博客的链接地址:

    1
    https://blog.csdn.net/weixin_43807148/article/details/114241862

2、阿里云OSS控制台账号获取

3、Typora安装与配置

Ubuntu 20.04完整安装ORB_SLAM2及配置对应ROS

0、创建包路径

  • 强烈建议,先在终端创建路径Packages,然后在这个文件夹下进行后续的1、2、3、这三个包的安装

1、安装Opencv4.2.0

  • 下载压缩包

    1
    https://github.com/opencv/opencv/archive/4.2.0.zip
  • 使用unzip -x opencv4.2.0.zip 解压,进入文件夹后依次运行如下命令

    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
    # 依赖库安装
    sudo apt-get install build-essential cmake git
    sudo apt-get install libgtk2.0-dev pkg-config libavcodec-dev
    sudo apt-get install libavformat-dev libswscale-dev
    sudo apt-get install python-dev python-numpy python3-dev python3-numpy
    sudo apt-get install libtbb2 libtbb-dev libjasper-dev libdc1394-22-dev
    sudo apt-get install libjpeg-dev libpng-dev libtiff-dev
    # 正式安装
    mkdir build && cd build
    cmake -D CMAKE_INSTALL_PREFIX=/usr/local/opencv4 -D CMAKE_BUILD_TYPE="Release" -D OPENCV_GENERATE_PKGCONFIG=ON ..
    make -j4
    sudo make install
    # 检查安装
    sudo gedit /etc/ld.so.conf.d/opencv.conf
    # 进入编辑页面后输入
    /usr/local/opencv4/lib
    # 然后ctrl+s保存,关闭gedit页面后还在这个终端下运行
    sudo ldconfig
    # 编辑bashrc文件,运行
    sudo gedit ~/.bashrc
    # 在文件最后添加
    #opencv-4.2.0
    export PKG_CONFIG_PATH=${PKG_CONFIG_PATH}:/usr/local/opencv4/lib/pkgconfig
    export LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:./usr/local/opencv4/lib
    # 然后ctrl+s保存,关闭gedit页面后还在这个终端下运行
    source ~/.bashrc
    # 最终检查,依次运行下列命令
    pkg-config --modversion opencv4
    pkg-config --cflags opencv4
    pkg-config --libs opencv4
    # 均有正常输出即可,其中第一个命令输出为4.2.0

2、安装依赖Pangolin

  • 安装依赖项

    1
    2
    sudo apt-get install libglew-dev libboost-dev libboost-thread-dev libboost-filesystem-dev
    sudo apt-get install ffmpeg libavcodec-dev libavutil-dev libavformat-dev libswscale-dev libpng-dev

    安装Pangolin 0.6(稳定版)(官网下载地址),不要下载最新master版,编译的时候可能有错误)

  • 配置并编译

    1
    2
    3
    4
    5
    cd Pangolin 
    mkdir build && cd build
    cmake -DCPP11_NO_BOOST=1 ..
    make
    sudo make install
  • 验证

    1
    2
    3
    4
    5
    cd ../examples/HelloPangolin
    mkdir build && cd build
    cmake ..
    make
    ./HelloPangolin

    成功后会弹出一个终端,里面是一个立方体有三色,关闭即可。

3、安装依赖Eigen3

  • 方案一:直接安装

    Eigen3是一个纯头文件的库,这个特点让使用者省去了很多安装和环境配置的麻烦,可以直接安装:

    1
    sudo apt-get install libeigen3-dev
  • 方案二:源码安装

    源码(地址)安装,执行以下指令:

    1
    2
    3
    4
    5
    cd eigen3
    mkdir build && cd build
    cmake ..
    make
    sudo make install

    安装后头文件在:

    1
    /usr/local/include/eigen3/

    复制头文件到/usr/local/include

    1
    sudo cp -r /usr/local/include/eigen3/Eigen /usr/local/include

4、安装ORB_SLAM2

  • 使用鱼香ROS的一键配置命令,配置rosdepc,终端执行下列命令,然后输入密码,选择rosdepc,然后配置好了之后会提示让rosdep init之类的命令,执行命令就好了

    1
    wget http://fishros.com/install -O fishros && . fishros
  • 进入到自己的ROS工作空间的src文件夹下,下载并解压源文件,然后打开,此处我的工作空间地址为:/home/zhao/WS/Now/ant_ws/src/ORB_SLAM2

  • 修改各个CMakeLists.txt,将其中关于OpenCV的部分做如下修改:

    1、主目录ORB_SLAM2下的CMakeLists.txt

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    # 注释掉下面这7行,类似的也是把涉及到的部分注释调
    # find_package(OpenCV 3.0 QUIET)
    # if(NOT OpenCV_FOUND)
    # find_package(OpenCV 2.4.3 QUIET)
    # if(NOT OpenCV_FOUND)
    # message(FATAL_ERROR "OpenCV > 2.4.3 not found.")
    # endif()
    # endif()

    # 然后添加这两行
    set(CMAKE_PREFIX_PATH "/usr/local/opencv4")
    find_package(OpenCV 4.0 QUIET)

    2、ORB_SLAM2/Thirdparty/DBoW2文件夹下的CMakeLists.txt

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    # find_package(OpenCV 3.0 QUIET)
    # if(NOT OpenCV_FOUND)
    # find_package(OpenCV 2.4.3 QUIET)
    # if(NOT OpenCV_FOUND)
    # message(FATAL_ERROR "OpenCV > 2.4.3 not found.")
    # endif()
    # endif()

    set(CMAKE_PREFIX_PATH "/usr/local/opencv4")
    find_package(OpenCV 4.0 QUIET)

    3、ORB_SLAM2/Examples/ROS/ORB_SLAM2文件夹下的CMakeLists.txt

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    # find_package(OpenCV 3.0 QUIET)
    # if(NOT OpenCV_FOUND)
    # find_package(OpenCV 2.4.3 QUIET)
    # if(NOT OpenCV_FOUND)
    # message(FATAL_ERROR "OpenCV > 2.4.3 not found.")
    # endif()
    # endif()

    set(CMAKE_PREFIX_PATH "/usr/local/opencv4")
    find_package(OpenCV 4.0 QUIET)
  • 修改ros示例源文件,为Examples/ROS/ORB_SLAM2/src路径下的所有.cc文件添加头文件

    1
    #include <unistd.h>
  • ORB_SLAM2/Examples/文件夹下的所有示例源文件中导入图像数据的参数 CV_LOAD_IMAGE_UNCHANGED 修改为下列表述,建议在这个文件夹下使用code . 命令开启vscode,使用侧边栏的搜索,然后全局替换(应该是6个)

    1
    cv::IMREAD_UNCHANGED
  • 把ORB-SLAM2源码目录中include/LoopClosing.h文件中的

    1
    2
    typedef map<KeyFrame*,g2o::Sim3,std::less<KeyFrame*>,
    Eigen::aligned_allocator<std::pair<const KeyFrame*, g2o::Sim3> > > KeyFrameAndPose;

    修改成:

    1
    2
    typedef map<KeyFrame*,g2o::Sim3,std::less<KeyFrame*>,
    Eigen::aligned_allocator<std::pair<KeyFrame *const, g2o::Sim3> > > KeyFrameAndPose;
  • 解压源文件,在该文件夹下打开终端:

    这里建议使用记事本打开build.sh,然后逐个命令执行,方便检查错误,且注意!每次运行到最后的make命令如果失败了,在修复了之后需要依次删除对应的build文件夹,重新创建并编译!

    1
    2
    3
    cd ORB_SLAM2
    chmod +x build.sh
    ./build.sh

    如果在运行时出现问题:

    1
    error: ’usleep’ was not declared in this scope

    那么找到对应的.cc文件,在其开头的#include部分添加内容:

    1
    #include <unistd.h>

    然后,需要对照着build.sh中的内容,将涉及到的所有build文件夹全部删除并重新开始!

  • 在终端添加ROS路径,执行以下两行命令

    1
    2
    echo 'export ROS_PACKAGE_PATH=${ROS_PACKAGE_PATH}:'"`pwd`/Examples/ROS" >> ~/.bashrc
    source ~/.bashrc
  • 编译ros节点,此时便不再会出现问题了

    1
    ./build_ros.sh

5、Reference

1、问题描述

在 Ubuntu 旧环境下,博客文件夹位于 /home/zhao/Blog,该目录已连接到 GitHub 仓库,并包含 Hexo 相关的配置文件和依赖。希望在 新 Ubuntu 系统 下重建该博客环境,并确保与 GitHub 仓库保持同步。然而,在执行 hexo 相关命令时遇到了一些问题,主要包括:

  1. .gitignore 配置可能导致部分文件未被同步。
  2. npx hexo generate 报错 TypeError: Object.fromEntries is not a function,怀疑是 Node.js 版本过旧
  3. hexo clean 报错 Command 'hexo' not found,怀疑是 Hexo 未全局安装

2、问题分析与解决方案

2.1 .gitignore 配置检查

.gitignore 文件中,以下内容可能影响同步:

1
2
3
4
5
6
7
8
# .DS_Store
# Thumbs.db
# db.json
# *.log
# node_modules/
# public/
# .deploy*/
# _multiconfig.yml
  • node_modules/public/ 目录可以忽略,因为它们可以通过 npm installhexo generate 重新生成。
  • db.json 可能包含 Hexo 的数据缓存,忽略它不会影响博客功能。

结论.gitignore 并未影响关键文件的同步,因此问题可能出现在 Node.js 版本或 Hexo 安装上。


2.2 解决 Node.js 版本过旧问题

错误信息:

1
TypeError: Object.fromEntries is not a function

原因: Object.fromEntries 需要 Node.js 12+,而旧版本 Node.js 可能低于 12.0.0。

解决方案:

1
2
3
4
5
6
7
8
9
10
11
12
# 检查当前 Node.js 版本
node -v

# 更新 Node.js(推荐使用官方 PPA)
sudo apt update
sudo apt install -y curl
curl -fsSL https://deb.nodesource.com/setup_18.x | sudo -E bash -
sudo apt install -y nodejs

# 确保安装成功
node -v
npm -v

2.3 解决 Hexo 未全局安装问题

错误信息:

1
Command 'hexo' not found

原因: Hexo 可能只作为 本地依赖 存在于 node_modules/ 目录中,而没有全局安装。

解决方案 1(推荐):使用 npx 运行 Hexo

1
2
3
npx hexo clean
npx hexo generate
npx hexo server

解决方案 2(可选):全局安装 Hexo

1
2
3
4
npm install -g hexo-cli

# 确保安装成功
hexo -v

3、完整的博客环境恢复步骤

  1. 安装 Node.js 和 npm(参考 2.2 章节)。
  2. 进入博客目录 并安装依赖:
    1
    2
    cd /home/zhao/Blog
    npm install
  3. 清理缓存并重新生成博客
    1
    2
    3
    hexo clean
    hexo generate
    hexo server
  4. 本地访问博客
    在浏览器中打开 http://localhost:4000,检查博客是否正常显示。
  5. 同步 GitHub 远程仓库(可选)
    1
    2
    git remote -v  # 确保远程仓库正确
    git pull origin main # 拉取最新代码
  6. 配置DNS解析
    添加CNAME文件到仓库中,内容书写个人网站,此处我的为zhaoyuanhangblogs.top,然后进入仓库设置,选择Pages选项,下滑到DNS解析部分,开启强制HTTPS,并在上方添加同样的网站地址,然后Save,就会自动解析

4、总结

在新 Ubuntu 系统下迁移 Hexo 博客时,可能会遇到 Node.js 版本过旧Hexo 未全局安装 的问题。通过升级 Node.js、安装 Hexo 依赖以及正确执行 Hexo 命令,可以成功恢复博客环境并同步 GitHub 仓库。

至此,Hexo 博客已成功在新系统下恢复并可正常使用!🎉

从 Ubuntu 系统中卸载 ImageMagick 及相关依赖

在某些情况下,系统中可能安装了 ImageMagick 和其他 KDE 或图像处理相关的软件包,而这些应用程序可能不再需要或者是未曾手动安装的。本文记录了如何在 Ubuntu 系统中卸载 ImageMagick 及其相关依赖。

步骤 1:查找并列出 ImageMagick 相关包

首先,使用以下命令查看系统中已安装的与 ImageMagick 相关的软件包:

1
dpkg -l | grep -i imagemagick

如果系统中确实安装了 ImageMagick,你将看到类似如下的输出:

1
2
3
ii  imagemagick-6-common                        8:6.9.10.23+dfsg-2.1ubuntu11.10       all          image manipulation programs -- infrastructure
ii imagemagick-6.q16 8:6.9.10.23+dfsg-2.1ubuntu11.10 amd64 image manipulation programs -- quantum depth Q16
ii libmagick++-6.q16-8:amd64 8:6.9.10.23+dfsg-2.1ubuntu11.10 amd64 C++ interface to ImageMagick -- quantum depth Q16

步骤 2:卸载 ImageMagick 相关包

接下来,使用 apt-get purge 命令卸载上述软件包:

1
sudo apt-get purge imagemagick-6-common imagemagick-6.q16 libmagick++-6.q16-8

该命令将彻底删除这些包及其相关配置文件。

步骤 3:清理无用的依赖和残留文件

卸载软件包后,运行以下命令清理不再需要的依赖和残留文件:

1
sudo apt autoremove --purge

此命令会自动删除那些与 ImageMagick 相关的、已不再需要的依赖包。

步骤 4:更新系统的应用菜单

为了确保卸载后的应用不再显示在应用程序栏中,可以更新系统的应用菜单:

1
sudo update-desktop-database

步骤 5:重启系统

最后,建议重启系统以确保所有更改生效:

1
sudo reboot

总结

通过以上步骤,你可以从 Ubuntu 系统中成功卸载 ImageMagick 及其相关的所有组件,同时清理系统中的多余依赖和配置文件。这些步骤可以帮助你更好地管理系统中不再需要的应用程序,释放系统空间。

如果Ubuntu没有声音输出,可以尝试以下几种解决方法:

  1. 检查音量设置:确保音量没有被静音或调到最低。点击系统菜单栏上的音量图标,调整音量设置。
  2. 检查音频设备连接:确保音频设备(例如扬声器、耳机等)已正确连接到计算机,并且没有松动或断开。
  3. 检查音频输出设备设置:点击系统菜单栏上的音量图标,选择“Sound Settings”(声音设置),在“Output”(输出)选项卡中,确保选择了正确的音频输出设备。
  4. 更新驱动程序:打开终端,运行以下命令更新系统的软件包和驱动程序:
1
2
sudo apt update
sudo apt upgrade

1、重启 PulseAudio 服务:

在终端中运行以下命令以重启 PulseAudio 服务:(本人尝试这个方法后成功切换)

1
pulseaudio -k
  • 然后,重启电脑,看看是否有声音输出(重启电脑这一步我没有操作,可自行看是否需要重启电脑)

2、检查默认音频设备:

打开终端,运行以下命令以查看默认音频设备:

1
aplay -l

然后,编辑 PulseAudio 配置文件,运行以下命令:

1
sudo nano /etc/pulse/default.pa

找到以下行并取消注释(删除行前的“#”符号):

1
load-module module-alsa-sink device=<默认音频设备>

<默认音频设备> 替换为 aplay -l 命令中显示的默认音频设备的标识符。保存文件并重启电脑。

3、安装和配置 ALSA 驱动程序:

打开终端,运行以下命令以安装 ALSA 驱动程序:

1
sudo apt install alsa-utils

然后,运行以下命令以配置 ALSA 驱动程序:

1
sudo alsa force-reload

重启电脑后,看看是否有声音输出。

如果上述方法仍然无法解决问题,可能需要更深入的故障排除或考虑使用其他音频设备。

Reference

1
https://www.yisu.com/ask/26427066.html

  • 红色警告信息:

  • 终端运行如下指令

    1
    sudo gedit /opt/ros/noetic/lib/python3/dist-packages/roslaunch/nodeprocess.py 

    将其中的_TIMEOUT_SIGINT后缀的数字15,修改为更短的时间即可

1、标定IMU+LiDAR

1、录制ROS包

  • 录制rosbag,仅需包含imu和lidar数据,具体/topic需要自行修改:
1
rosbag record /imu /velodyne_points -O data/ROSBAG/lidar_imu.bag
  • 保存的效果如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
zhao@zhao:~/WS/msfl_ws$ rosbag info data/ROSBAG/lidar_imu.bag 
path: data/ROSBAG/lidar_imu.bag
version: 2.0
duration: 3:17s (197s)
start: Jan 01 1970 08:00:03.46 (3.46)
end: Jan 01 1970 08:03:20.57 (200.57)
size: 384.0 MB
messages: 21684
compression: none [475/475 chunks]
types: sensor_msgs/Imu [6a62c6daae103f4ff57a132d6f95cec2]
sensor_msgs/PointCloud2 [1158d486dd51d683ce2f1be655c3c181]
topics: /imu 19713 msgs : sensor_msgs/Imu
/velodyne_points 1971 msgs : sensor_msgs/PointCloud2

2、安装依赖项

  • nlop包安装:
1
2
3
4
5
6
7
git clone https://github.com/stevengj/nlopt
cd nlopt
mkdir build
cd build
cmake ..
make -j8
sudo make install

这里可能会遇到在cmake ..的时候有fail现象,提示一些包未找到,为了保证后续运行顺利,我这边还是安装了:

1
2
3
4
5
sudo apt-get install guile-3.0 #这里我选择的是3.0版本
sudo apt-get install guile-3.0-dev
sudo apt-get install octave
sudo apt-get install liboctave-dev
sudo apt-get install swig

3、修改源码

  • 修改 loader.cpp
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
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
#include <geometry_msgs/TransformStamped.h>
#include <rosbag/bag.h>
#include <rosbag/view.h>
#include <sensor_msgs/Imu.h>

#include "lidar_align/loader.h"
#include "lidar_align/transform.h"

#include <sensor_msgs/Imu.h>

namespace lidar_align {

Loader::Loader(const Config& config) : config_(config) {}

Loader::Config Loader::getConfig(ros::NodeHandle* nh) {
Loader::Config config;
nh->param("use_n_scans", config.use_n_scans, config.use_n_scans);
return config;
}

void Loader::parsePointcloudMsg(const sensor_msgs::PointCloud2 msg,
LoaderPointcloud* pointcloud) {
bool has_timing = false;
bool has_intensity = false;
for (const sensor_msgs::PointField& field : msg.fields) {
if (field.name == "time_offset_us") {
has_timing = true;
} else if (field.name == "intensity") {
has_intensity = true;
}
}

if (has_timing) {
pcl::fromROSMsg(msg, *pointcloud);
return;
} else if (has_intensity) {
Pointcloud raw_pointcloud;
pcl::fromROSMsg(msg, raw_pointcloud);

for (const Point& raw_point : raw_pointcloud) {
PointAllFields point;
point.x = raw_point.x;
point.y = raw_point.y;
point.z = raw_point.z;
point.intensity = raw_point.intensity;

if (!std::isfinite(point.x) || !std::isfinite(point.y) ||
!std::isfinite(point.z) || !std::isfinite(point.intensity)) {
continue;
}

pointcloud->push_back(point);
}
pointcloud->header = raw_pointcloud.header;
} else {
pcl::PointCloud<pcl::PointXYZ> raw_pointcloud;
pcl::fromROSMsg(msg, raw_pointcloud);

for (const pcl::PointXYZ& raw_point : raw_pointcloud) {
PointAllFields point;
point.x = raw_point.x;
point.y = raw_point.y;
point.z = raw_point.z;

if (!std::isfinite(point.x) || !std::isfinite(point.y) ||
!std::isfinite(point.z)) {
continue;
}

pointcloud->push_back(point);
}
pointcloud->header = raw_pointcloud.header;
}
}

bool Loader::loadPointcloudFromROSBag(const std::string& bag_path,
const Scan::Config& scan_config,
Lidar* lidar) {
rosbag::Bag bag;
try {
bag.open(bag_path, rosbag::bagmode::Read);
} catch (rosbag::BagException e) {
ROS_ERROR_STREAM("LOADING BAG FAILED: " << e.what());
return false;
}

std::vector<std::string> types;
types.push_back(std::string("sensor_msgs/PointCloud2"));
rosbag::View view(bag, rosbag::TypeQuery(types));

size_t scan_num = 0;
for (const rosbag::MessageInstance& m : view) {
std::cout << " Loading scan: \e[1m" << scan_num++ << "\e[0m from ros bag"
<< '\r' << std::flush;

LoaderPointcloud pointcloud;
parsePointcloudMsg(*(m.instantiate<sensor_msgs::PointCloud2>()),
&pointcloud);

lidar->addPointcloud(pointcloud, scan_config);

if (lidar->getNumberOfScans() >= config_.use_n_scans) {
break;
}
}
if (lidar->getTotalPoints() == 0) {
ROS_ERROR_STREAM(
"No points were loaded, verify that the bag contains populated "
"messages of type sensor_msgs/PointCloud2");
return false;
}

return true;
}

bool Loader::loadTformFromROSBag(const std::string& bag_path, Odom* odom) {
rosbag::Bag bag;
try {
bag.open(bag_path, rosbag::bagmode::Read);
} catch (rosbag::BagException e) {
ROS_ERROR_STREAM("LOADING BAG FAILED: " << e.what());
return false;
}

std::vector<std::string> types;
types.push_back(std::string("sensor_msgs/Imu"));
rosbag::View view(bag, rosbag::TypeQuery(types));
size_t imu_num = 0;
double shiftX=0,shiftY=0,shiftZ=0,velX=0,velY=0,velZ=0;
ros::Time time;
double timeDiff,lastShiftX,lastShiftY,lastShiftZ;
for (const rosbag::MessageInstance& m : view){
std::cout <<"Loading imu: \e[1m"<< imu_num++<<"\e[0m from ros bag"<<'\r'<< std::flush;

sensor_msgs::Imu imu=*(m.instantiate<sensor_msgs::Imu>());

Timestamp stamp = imu.header.stamp.sec * 1000000ll +imu.header.stamp.nsec / 1000ll;
if(imu_num==1){
time=imu.header.stamp;
Transform T(Transform::Translation(0,0,0),Transform::Rotation(1,0,0,0));
odom->addTransformData(stamp, T);
}
else{
timeDiff=(imu.header.stamp-time).toSec();
time=imu.header.stamp;
velX=velX+imu.linear_acceleration.x*timeDiff;
velY=velX+imu.linear_acceleration.y*timeDiff;
velZ=velZ+(imu.linear_acceleration.z-9.801)*timeDiff;

lastShiftX=shiftX;
lastShiftY=shiftY;
lastShiftZ=shiftZ;
shiftX=lastShiftX+velX*timeDiff+imu.linear_acceleration.x*timeDiff*timeDiff/2;
shiftY=lastShiftY+velY*timeDiff+imu.linear_acceleration.y*timeDiff*timeDiff/2;
shiftZ=lastShiftZ+velZ*timeDiff+(imu.linear_acceleration.z-9.801)*timeDiff*timeDiff/2;

Transform T(Transform::Translation(shiftX,shiftY,shiftZ),
Transform::Rotation(imu.orientation.w,
imu.orientation.x,
imu.orientation.y,
imu.orientation.z));
odom->addTransformData(stamp, T);
}
}
// std::vector<std::string> types;
// types.push_back(std::string("geometry_msgs/TransformStamped"));
// rosbag::View view(bag, rosbag::TypeQuery(types));

// size_t tform_num = 0;
// for (const rosbag::MessageInstance& m : view) {
// std::cout << " Loading transform: \e[1m" << tform_num++
// << "\e[0m from ros bag" << '\r' << std::flush;

// geometry_msgs::TransformStamped transform_msg =
// *(m.instantiate<geometry_msgs::TransformStamped>());

// Timestamp stamp = transform_msg.header.stamp.sec * 1000000ll +
// transform_msg.header.stamp.nsec / 1000ll;

// Transform T(Transform::Translation(transform_msg.transform.translation.x,
// transform_msg.transform.translation.y,
// transform_msg.transform.translation.z),
// Transform::Rotation(transform_msg.transform.rotation.w,
// transform_msg.transform.rotation.x,
// transform_msg.transform.rotation.y,
// transform_msg.transform.rotation.z));
// odom->addTransformData(stamp, T);
// }

if (odom->empty()) {
ROS_ERROR_STREAM("No odom messages found!");
return false;
}

return true;
}

bool Loader::loadTformFromMaplabCSV(const std::string& csv_path, Odom* odom) {
std::ifstream file(csv_path, std::ifstream::in);

size_t tform_num = 0;
while (file.peek() != EOF) {
std::cout << " Loading transform: \e[1m" << tform_num++
<< "\e[0m from csv file" << '\r' << std::flush;

Timestamp stamp;
Transform T;

if (getNextCSVTransform(file, &stamp, &T)) {
odom->addTransformData(stamp, T);
}
}

return true;
}

// lots of potential failure cases not checked
bool Loader::getNextCSVTransform(std::istream& str, Timestamp* stamp,
Transform* T) {
std::string line;
std::getline(str, line);

// ignore comment lines
if (line[0] == '#') {
return false;
}

std::stringstream line_stream(line);
std::string cell;

std::vector<std::string> data;
while (std::getline(line_stream, cell, ',')) {
data.push_back(cell);
}

if (data.size() < 9) {
return false;
}

constexpr size_t TIME = 0;
constexpr size_t X = 2;
constexpr size_t Y = 3;
constexpr size_t Z = 4;
constexpr size_t RW = 5;
constexpr size_t RX = 6;
constexpr size_t RY = 7;
constexpr size_t RZ = 8;

*stamp = std::stoll(data[TIME]) / 1000ll;
*T = Transform(Transform::Translation(std::stod(data[X]), std::stod(data[Y]),
std::stod(data[Z])),
Transform::Rotation(std::stod(data[RW]), std::stod(data[RX]),
std::stod(data[RY]), std::stod(data[RZ])));

return true;
}

} // namespace lidar_align
  • 修改NLOPTConfig.cmake文件位置

    将 lidar_align 源码包里的 NLOPTConfig.cmake 复制到 ROS工作空间msfl_ws/src 路径下面

  • 修改源码CMakeLists.txt文件,添加以下代码:

1
2
set (CMAKE_PREFIX_PATH "/usr/local/lib/cmake/nlopt")
set(CMAKE_CXX_STANDARD 14)
  • 修改launch文件中的包路径
1
<arg name="bag_file" default="/home/zhao/WS/msfl_ws/data/ROSBAG/lidar_imu.bag"/>

4、运行代码

启动代码进行标定

1
2
3
catkin_make #此处建议先删除之前的build/ devel/
source devel/setup.bash
roslaunch lidar_align lidar_align.launch

运行结果如下

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
zhao@zhao:~/WS/msfl_ws$ roslaunch lidar_align lidar_align.launch 
... logging to /home/zhao/.ros/log/24f28d9c-c332-11ef-a81b-25d9e051409d/roslaunch-zhao-83450.log
Checking log directory for disk usage. This may take a while.
Press Ctrl-C to interrupt
Done checking log file disk usage. Usage is <1GB.

started roslaunch server http://zhao:41241/

SUMMARY
========

PARAMETERS
* /lidar_align/input_bag_path: /home/zhao/WS/msf...
* /lidar_align/input_csv_path: PATH/TO/YOUR.csv
* /lidar_align/output_calibration_path: /home/zhao/WS/msf...
* /lidar_align/output_pointcloud_path: /home/zhao/WS/msf...
* /lidar_align/transforms_from_csv: False
* /rosdistro: noetic
* /rosversion: 1.17.0

NODES
/
lidar_align (lidar_align/lidar_align_node)

ROS_MASTER_URI=http://localhost:11311

process[lidar_align-1]: started with pid [83464]
[ INFO] [1735198105.395046732]: Loading Pointcloud Data...
[ INFO] [1735198107.504482765]: Loading Transformation Data...
[ INFO] [1735198107.640942368]: Interpolating Transformation Data...
[ INFO] [1735198109.247437244]: Performing Global Optimization...
[ INFO] [1735198300.233199926]: Performing Local Optimization...
[ INFO] [1735198309.992561542]: Saving Aligned Pointcloud... eration: 204
[ INFO] [1735198310.543539562]: Saving Calibration File...
[ INFO] [1735198310.543604514]: Final Calibration:
Active Transformation Vector (x,y,z,rx,ry,rz) from the Pose Sensor Frame to the Lidar Frame:
[0, 0, 0, -1.39626, 0.465421, 0]

Active Transformation Matrix from the Pose Sensor Frame to the Lidar Frame:
0.909884 -0.270347 0.314679 0
-0.270347 0.188959 0.944038 0
-0.314679 -0.944038 0.0988438 0
0 0 0 1

Active Translation Vector (x,y,z) from the Pose Sensor Frame to the Lidar Frame:
[0, 0, 0]

Active Hamiltonen Quaternion (w,x,y,z) the Pose Sensor Frame to the Lidar Frame:
[0.74123, -0.636805, 0.212268, 0]

Time offset that must be added to lidar timestamps in seconds:
0

ROS Static TF Publisher: <node pkg="tf" type="static_transform_publisher" name="pose_lidar_broadcaster" args="0 0 0 -0.636805 0.212268 0 0.74123 POSE_FRAME LIDAR_FRAME 100" />
[lidar_align-1] process has finished cleanly
log file: /home/zhao/.ros/log/24f28d9c-c332-11ef-a81b-25d9e051409d/lidar_align-1*.log
all processes on machine have died, roslaunch will exit
shutting down processing monitor...
... shutting down processing monitor complete
done

2、对比调试数据发布信息

1、检查rosbag中的topic

检查LIO-SAM开源数据包与个人实际录制数据包中的topic信息,发现imu这一消息类型中,个人录制数据包中四元数错误

image-20241226222051020

此图为walking_dataset.bag/imu_raw话题的输出结果,可以看到orientation这一个四元数是正确的

image-20241226222319709

此图为msfl.bag中的/imu话题的输出结果,可以看到orientation这个四元数是错误的

2、中继发布/imu数据

3、注意到IMU的内参也要标定

  • 参考链接:
    1
    https://blog.csdn.net/qq_43112859/article/details/132879387

1、问题描述:

Linux:关机慢等待 90 秒提示 a stop job is running for XXX

2、解决方法:

  • 编辑配置文件:
    1
    sudo nano /etc/systemd/system.conf
    修改以下两个参数,比如改为 5s
    1
    2
    DefaultTimeoutStartSec=5s
    DefaultTimeoutStopSec=5s
  • 重启服务:
    1
    systemctl daemon-reload

1、安装依赖项

  • 参考之前的博客:【安装学习】ubuntu20.04与A-LOAM:01-安装ceres-solver
  • 注意!仅需顺序执行之前博客操作即可,不需要自行再次源码安装诸如eigen3之类的软件包(通过sudo apt-get安装即可)

2、修改代码内容

  • 将四个.cpp文件中的/camera_init修改为camera_init
  • scanRegistration.cpp中的 #include <opencv/cv.h> 修改为#include <opencv2/imgproc.hpp>
  • 修改kittiHelper.cppCV_LOAD_IMAGE_GRAYSCALEcv::IMREAD_GRAYSCALE
  • 无论之前是否已经catkin_make编译过,都需要重新编译,即删除build/devel/文件夹后重新执行catkin_make以使上方的ceres库生效
  • 若版本是ubuntu20.04 ros-noetic,也可以使用我修改后的fork仓库:https://github.com/QianYuan1437/A-LOAM-NOTED.git 注意branch

3、测试与保存

  • 下载测试ROSBAGhttps://drive.google.com/file/d/1s05tBQOLNEDDurlg48KiUWxCp-YqYyGH/view
  • 开启三个终端:注意运行顺序,先1再2最后3
    • 1、roscore
    • 2、roslaunch aloam_velodyne aloam_velodyne_VLP_16.launch
    • 3、rosbag play nsh_indoor_outdoor.bag
  • 如果需要保存点云信息,则需开启第四个终端
    • 4、有以下两种方法,但注意运行顺序为1,2,4,3
      1
      2
      #另起终端用bag_to_pcd方法保存点云图
      rosrun pcl_ros bag_to_pcd xxx.bag /laser_cloud_surround pcd
      运行结束,可以看到生成了一个pcd文件夹,将里面的文件按照修改时间排序,最新的就是最后的点云地图pcd文件。
      1
      2
      3
      4
      #另起终端,用pointcloud_to_pcd方法保存点云图
      mkdir pcd
      cd pcd
      rosrun pcl_ros pointcloud_to_pcd input:=/laser_cloud_surround
  • 点云地图查看:
    1
    pcl_viewer xxx.pcd
    pcd点云地图转ply格式
    1
    pcl_pcd2ply xxx.pcd xxxxxxx.ply
    当我们需要用第三方软件(MatLab/MeshLab)对点云地图进行处理时就需要将pcd转为ply,其中MeshLab必须使用由pointcloud_to_pcd方法创建pcd转成的ply格式点云!

4、参考链接

5、MSFL测试参考链接

1、安装依赖

安装 ubuntu-restricted-extrasubuntu-restricted-extras 包含常用的多媒体编解码器,包括支持 MKV 格式的解码器。

1
2
sudo apt update
sudo apt install ubuntu-restricted-extras

注意!Ubuntu终端显示文本让选择确定,OK等等:首先按下”TAB”键,会看到选中文本”确定”,”OK”然后按下回车键,即可!

2、成功

3、变速保存

可以使用 ffmpeg 将视频转换为3倍速播放的 mp4 格式。以下是具体操作步骤

在终端中执行以下命令:

1
ffmpeg -i 2024-12-24_15-32-53.mkv -filter:v "setpts=PTS/3" -an -c:v libx264 -preset fast -crf 23 2024-12-24_15-32-53_3x.mp4

解释

  • -i 2024-12-24_15-32-53.mkv: 指定输入文件。
  • -filter:v "setpts=PTS/3": 使用 setpts 过滤器将视频播放速度调整为原来的3倍速。PTS/3 表示时间戳变为原来的1/3。
  • -an: 删除音频轨道。如果需要加快音频速度,见下方。
  • -c:v libx264: 使用 H.264 编解码器。
  • -preset fast: 选择快速编码预设。
  • -crf 23: 设置视频质量,23 为默认值,数值越小质量越高(如需要更高质量可以调低)。
  • 2024-12-24_15-32-53_3x.mp4: 指定输出文件名。

如果需要保留并加速音频,音频也需要同步加速,可以使用以下命令:

1
ffmpeg -i 2024-12-24_15-32-53.mkv -filter_complex "[0:v]setpts=PTS/3[v];[0:a]atempo=3[a]" -map "[v]" -map "[a]" -c:v libx264 -preset fast -crf 23 2024-12-24_15-32-53_3x.mp4
  • [0:v]setpts=PTS/3[v]: 设置视频为3倍速。
  • [0:a]atempo=3[a]: 将音频加速3倍。atempo 最大支持2倍速,可多次链式叠加(例如 6倍速可用 atempo=2,atempo=3)。

最终文件检查:转码完成后,可以使用以下命令检查输出文件信息:

1
ffmpeg -i 2024-12-24_15-32-53_3x.mp4

这样可以确认视频和音频是否按预期处理。如果还有其他需求,随时告诉我! 😊