第2讲
文章目录
1 SLAM的数学表述
运动方程
x
k
=
f
(
x
k
−
1
,
u
k
,
w
k
)
\boldsymbol{x}_k=f\left(\boldsymbol{x}_{k-1}, \boldsymbol{u}_k, \boldsymbol{w}_k\right)
xk=f(xk−1,uk,wk)
观测方程
z
k
,
j
=
h
(
y
j
,
x
k
,
v
k
,
j
)
\boldsymbol{z}_{k, j}=h\left(\boldsymbol{y}_j, \boldsymbol{x}_k, \boldsymbol{v}_{k, j}\right)
zk,j=h(yj,xk,vk,j)
2 创建虚拟环境
1 准备虚拟机和Ubuntu镜像
3 使用前的准备工作
3.1 换源
更换源,找到软件和更新,或者通过命令打开
software-properties-gtk
3.2 安装一些包
更新
sudo apt update
sudo apt upgrade
sudo apt install git
sudo apt install htop
sudo apt install vim
sudo apt install terminator # 超级终端
sudo apt install net-tools
sudo apt-get install openssh-serve # ssh-serve
sudo apt-get install ufw
sudo apt install g++
sudo apt-get install mlocate # 安装locate 定位安装包文件等
sudo apt install cmake # 安装cmake
sudo snap install tree # 查看目录结构
3.3 安装vscode
# 安装vscode 可以直接在软件商店获取 下面使用命令行安装
sudo apt install software-properties-common apt-transport-https wget # 解决依赖
# 获取 Microsoft 的 GPG 密钥
wget -q https://packages.microsoft.com/keys/microsoft.asc -O- | sudo apt-key add -
# 启用 Visual Studio 代码存储库
sudo add-apt-repository "deb [arch=amd64] https://packages.microsoft.com/repos/vscode stable main"
# 安装code
sudo apt install code
# 检查版本
code –version
# 卸载
sudo apt remove code
3.4 Git源码
新建文件slambook2,在此文件夹打开终端,拷贝书中代码,recursive
命令是为了将作者仓库中提供的一些第三方库也下载下来,安装作者使用的版本会减少很多报错。
git clone --recursive https://github.com/gaoxiang12/slambook2.git
3.5 查看安装包的版本
有时候因为安装包的版本问题导致编译失败,想要查看版本,却不知道怎么查看。偶然发现大部分都提供了ConfigVersion.cmake文件,我们可以通过这个文件来查看。
# 每天一个小技巧 如何查看安装包的版本 找到xxxConfigVersion.cmake
# 第1步
locate xxx | grep ConfigVersion.cmake
# 第2步,查看对应路径 eg eigen库
cat /usr/lib/cmake/eigen3/Eigen3ConfigVersion.cmake | grep VERSION
# 一般都会在开始set(PACKAGE_VERSION "xxx")写明
# Pangolin
cat /usr/local/lib/cmake/Pangolin/PangolinConfigVersion.cmake | grep PACKAGE_VERSION
# Sophus
cat /usr/local/share/sophus/cmake/SophusConfigVersion.cmake | grep PACKAGE_VERSION
# OpenCV
cat /usr/local/opencv3/share/OpenCV/OpenCVConfig-version.cmake| grep VERSION
# g2o
cat /usr/local/lib/cmake/g2o/g2oConfigVersion.cmake | grep VERSION
# ceres
cat /home/pj/slambook/package/ceres/ceres-solver-1.14.0/build/CeresConfigVersion.cmake | grep VERSION
而且这些文件还会给出重要的信息
3.6 int mian(int argc, char** argv)
int mian(int argc, char** argv)
{
.....
}
/// 解释一下这种特定的写法
argv为指针的指针, argc为整数。另外 char **argv 可以写为char *argv[ ] 或者 char argv[ ][ ]
main()括号内是固定的写法。
下面给出一个例子来理解这两个参数的用法:
假设程序的名称为prog,
1.当只输入prog,则由操作系统传来的参数为:
argc=1,表示只有一个程序名称。
argc只有一个元素,argv[0]指向输入的程序路径及名称:./prog
2.当输入prog para_1,有一个参数,则由操作系统传来的参数为:
argc=2,表示除了程序名外还有一个参数。
argv[0]指向输入的程序路径及名称。
argv[1]指向参数para_1字符串。
3.当输入prog para_1 para_2 有2个参数,则由操作系统传来的参数为:
argc=3,表示除了程序名外还有2个参数。
argv[0]指向输入的程序路径及名称。
argv[1]指向参数para_1字符串。
argv[2]指向参数para_2字符串。
习题
习题3
3. g++命令有哪些参数?怎么填写参数可以更改生成的程序文件名?
g++ m.cpp -o m # -o 后面指定输出名
习题5
5. 刻意在代码中添加一些语法错误,看看编译会生成什么样的信息。你能看懂g++的错误信息吗?
删除一个分号;
~/SLAMBOOK2/slambook2/ch2$ g++ helloSLAM.cpp -o a
helloSLAM.cpp: In function ‘int main(int, char**)’:
helloSLAM.cpp:6:3: error: expected ‘;’ before ‘return’
return 0;
^~~~~~
习题6
6. 如果忘了把库链接到可执行程序上,编译会报错吗?报什么样的错?
# 在第二章提供的CMakeLists.txt中
# 将target_link_libraries(useHello hello_shared)删除
~/SLAMBOOK2/slambook2/ch2/build$ mkdir build
~/SLAMBOOK2/slambook2/ch2/build$ cd build
~/SLAMBOOK2/slambook2/ch2/build$ cmake .. # CMakeLists.txt没有错误,所以cmake不会报错
-- The C compiler identification is GNU 7.5.0
-- The CXX compiler identification is GNU 7.5.0
-- Check for working C compiler: /usr/bin/cc
-- Check for working C compiler: /usr/bin/cc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Detecting C compile features
-- Detecting C compile features - done
-- Check for working CXX compiler: /usr/bin/c++
-- Check for working CXX compiler: /usr/bin/c++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Configuring done
-- Generating done
-- Build files have been written to: ~/SLAMBOOK2/slambook2/ch2/build
~/SLAMBOOK2/slambook2/ch2/build$ make
Scanning dependencies of target useHello
[ 12%] Building CXX object CMakeFiles/useHello.dir/useHello.cpp.o
[ 25%] Linking CXX executable useHello
CMakeFiles/useHello.dir/useHello.cpp.o: In function `main':
/home/p/SLAMBOOK2/slambook2/ch2/useHello.cpp:5: undefined reference to `printHello()'
collect2: error: ld returned 1 exit status # 找不到这个函数的定义
CMakeFiles/useHello.dir/build.make:94: recipe for target 'useHello' failed
make[2]: *** [useHello] Error 1 # 目标useHello编译失败
CMakeFiles/Makefile2:67: recipe for target 'CMakeFiles/useHello.dir/all' failed
make[1]: *** [CMakeFiles/useHello.dir/all] Error 2
Makefile:83: recipe for target 'all' failed
make: *** [all] Error 2
习题8
8. 完善Hello SLAM小程序,把它做成一个小程序库,安装到本地硬盘中。然后,新建一个工程,使用find package找这个库并调用。
这里利用到两个知识点,一个是安装,一个是find_package
的使用。Github链接
- 新建文件如下
p@p:~/SLAMBOOK2/homework$ tree
.
├── build
├── cmake # find文件
│ └── FindHELLO.cmake
├── CMakeLists.txt # 外层CMakeLists.txt
├── include # 放置安装的头文件
│ └── hello.h
├── main
│ ├── CMakeLists.txt
│ └── main.cpp # 主函数
└── src # 放置安装的源文件
└── hello.cpp
└── lib # 输出动态库的位置
- 最外层CMakeLists.txt文件
cmake_minimum_required(VERSION 3.10) # 声明版本 cmake --version查看你的cmake版本
project(HELLO) # 项目名
add_subdirectory(main bin) # 添加子文件
- hello.h
#pragma once
void HelloFunc();
- hello.cpp
#include <iostream>
void HelloFunc(){
std::cout << "Hello World" << std::endl;
}
- main.cpp
#include "hello.h"
int main(){
HelloFunc();
}
- main文件下的CMakeLists.txt
include_directories("../include") # 包含头文件,要不然src找不到路径
set(CMAKE_BUILD_TYPE "Release")
set(LIBHELLO_SRC ../src/hello.cpp) # 设置源文件路径
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${PROJECT_SOURCE_DIR}/lib) # 动态库位置
add_library(hello SHARED ${LIBHELLO_SRC}) # 添加库
install(FILES ../include/hello.h DESTINATION include) # 安装头文件
# 参数DESTINATION指安装路径, CMAKE_INSTALL_PREFIX 默认是在 /usr/local/ 也就是说,这里实际的安装位置是 /usr/local/include
install(TARGETS hello
LIBRARY DESTINATION lib # LIBRARY 动态库
ARCHIVE DESTINATION lib) # ARCHIVE 静态库
set(CMAKE_MODULE_PATH "../cmake")
message(${CMAKE_MODULE_PATH})
find_package(HELLO REQUIRED) # 注意参数库 xxx 要和 cmake文件下的FindXXX.cmake保持一致
message(STATUS "HELLO_INCLUDE_DIRS " ${HELLO_INCLUDE_DIR} )
message(STATUS " HELLO_LIBRARY " ${HELLO_LIBRARY} )
if(HELLO_FOUND)
MESSAGE(${CMAKE_MODULE_PATH})
add_executable(aaa main.cpp)
target_include_directories(aaa PRIVATE ${HELLO_INCLUDE_DIR})
target_link_libraries(aaa ${HELLO_LIBRARY})
# else(HELLO_FOUND) # 因为之前是先安装,在find的,所以当时写了这两行,但是安装和find放一起千万要记得注释掉,否则一直报错。
# message(FATAL_ERROR "HELLO library not found")
endif(HELLO_FOUND)
- FindHELLO.cmake
find_path(HELLO_INCLUDE_DIR hello.h /usr/local/include/ ) # 找头文件
find_library(HELLO_LIBRARY NAMES hello PATH /usr/local/lib) # 找库文件 NAMES 库名
# PATH 查找的路径
if(HELLO_INCLUDE_DIR AND HELLO_LIBRARY)
set(HELLO_FOUND TRUE)
endif(HELLO_INCLUDE_DIR AND HELLO_LIBRARY)
- 编译过程
这样做有个缺点,编译安装完后还需要再编译一次才会生成可执行文件aaa。这是因为在sudo make install 命令之前是没有安装的,之后就再find就不需要多次编译。所以感觉还是先安装,再编译比较好。
p@p:~/SLAMBOOK2/homework/build$ cmake -D CMAKE_INSTALL_PREFIX=/usr/local ..
# 默认安装路径 等价cmake ..
-- The C compiler identification is GNU 7.5.0
-- The CXX compiler identification is GNU 7.5.0
-- Check for working C compiler: /usr/bin/cc
-- Check for working C compiler: /usr/bin/cc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Detecting C compile features
-- Detecting C compile features - done
-- Check for working CXX compiler: /usr/bin/c++
-- Check for working CXX compiler: /usr/bin/c++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Detecting CXX compile features
-- Detecting CXX compile features - done
../cmake
-- HELLO_INCLUDE_DIRS HELLO_INCLUDE_DIR-NOTFOUND
-- HELLO_LIBRARY HELLO_LIBRARY-NOTFOUND
-- Configuring done
-- Generating done
-- Build files have been written to: /home/p/SLAMBOOK2/homework/build
p@p:~/SLAMBOOK2/homework/build$ make -j2
Scanning dependencies of target hello
[ 50%] Building CXX object bin/CMakeFiles/hello.dir/__/src/hello.cpp.o
[100%] Linking CXX shared library libhello.so
[100%] Built target hello
p@p:~/SLAMBOOK2/homework/build$ sudo make install
[sudo] password for p:
[100%] Built target hello
Install the project...
-- Install configuration: ""
-- Installing: /usr/local/include/hello.h
-- Installing: /usr/local/lib/libhello.so
p@p:~/SLAMBOOK2/homework/build$ cmake ..
../cmake
-- HELLO_INCLUDE_DIRS /usr/local/include
-- HELLO_LIBRARY /usr/local/lib/libhello.so
../cmake
-- Configuring done
-- Generating done
-- Build files have been written to: /home/p/SLAMBOOK2/homework/build
p@p:~/SLAMBOOK2/homework/build$ make
Scanning dependencies of target aaa
[ 25%] Building CXX object bin/CMakeFiles/aaa.dir/main.cpp.o
[ 50%] Linking CXX executable aaa
[ 50%] Built target aaa
[100%] Built target hello