机器人导航时偶然出现倒退的小速度-0.02
,但周围又没有障碍物,其实就是参数max_vel_x_backwards=0.02
a=[1,2,3; 4,5,6]
是一个2×3的矩阵1
21 2 3
4 5 6
matrix = [1;2;3;4;5]
是5x1的矩阵, matrix = [1,2,3,4,5]
是1x5的矩阵
matrix = [1,2,3,4,5]'
是做了转置,结果是5x1的矩阵
matrix(:, 1)
是矩阵的第一列
zeros(m,n): 生成一个 m 行 n 列的零矩阵,m=n 时可简写为 zeros(n)
ones(m,n): 生成一个 m 行 n 列的元素全为 1 的矩阵, 当m=n 时可写为 ones(n)
eye(m,n): 生成一个主对角线全为 1 的 m 行 n 列矩阵, m=n 时可简写为 eye(n)
,即为 n 维单位矩阵
rand(m,n): 产生 0~1
间均匀分布的随机矩阵, m=n 时简写为 rand(n)
randn(m,n): 产生均值为0,方差为1的标准正态分布矩阵,m=n 时简写为 randn(n)
zeros(m, n)
中的n可以为0,此时矩阵实际是空。1
2
3matrix = zeros(5,0)
matrix = [matrix, [1;2;3;4;5] ]
matrix = [matrix, [11;12;13;14;15] ]
最终matrix是5x2的矩阵,也就是逐步扩展1
2
3
4
51 11
2 12
3 13
4 14
5 15
这篇论文发表于2021.10,大部分内容在官网上,对一些重点内容做一下记录。
算法框架包括探索算法TARE
(exploration planner
); 路径算法FAR
(route planner
)
我们的算法不依赖只有仿真才提供的信息,比如 semantic and terrain segmentation groundtruth. 算法是为了让用户重点开发上层的规划算法。
在2021 DARPA地下挑战赛中, CMU-OSU Team Explorer 虽然没拿到冠军,但获得”探索最多区域奖“(26 out of 28 sectors).
For outdoor settings, the most well-known dataset is KITTI Vision Benchmark Dataset
[4] collected
from a self-driving suite in road driving scenarios. The
dataset contains sensor data from stereo cameras, 3D Lidar,
and GPS/INS ground truth for benchmarking depth reconstruction, odometry estimation, object segmentation, etc.
For localization purposes, the long-term localization benchmark includes a comprehensive list of datasets: Aachen Day-Night dataset, Extended CMU Seasons dataset, RobotCar Seasons dataset, and SILDa Weather and Time of Day dataset.
For indoor navigation, iGibson [15], [16], Sapien [17], AI2Thor [18], Virtual Home [19], ThreeDWorld [20], MINOS [21], House3D [22] and CHALET [23] use synthetic scenes, while reconstructed scenes are also available in iGibson, AI Habitatand MINOS. Compared to datasets, simulation environments have the advantage of providing access to ground truth data, e.g. vehicle pose and semantic segmentation to simplify the algorithm development and allowing full navigation system tests in closed control loop。
For indoor scenes, datasets such as NYUDepth dataset [7], TUM SLAM dataset [8], inLoc dataset [9], MIT Stata center dataset, and KTH-INDOL dataset [11], [12] are available. Datasets are useful in developing and
Simulation environments: Carla [13] and AirSim [14] are two representative simulation environments for autonomous driving and flying. These simulators support various conditions such as lighting and weather changes, moving objects such as pedestrians, and incident scenes.
其他的导航框架: ROS Navigation Stack 和港科大的 fast_planner ,不过是针对无人机的。
我们的导航框架: 支持photorealistic house models from Matterport3D 以及向AI Habitat提供接口。这两个在机器人学和计算视觉中应用很多。Users are provided with scan data and RGB, depth, and semantic images rendered by AI Habitat. Users have the option of running AI Habitat side by side with our system or in post-processing
参考:
阅读笔记 《Matterport3D: Learning from RGB-D Data inIndoor Environments》
AI Habitat室内仿真平台使用
local planner
保证了到达目标时的安全,它预计算 a motion primitive library and associates the motion primitives to 车周围的3D locations(这里说的就是free_paths
对应的曲线簇)。 The motion primitives are modeled as Monte Carlo samples and organized in groups
现实中快遇到障碍物时,local planner
可以在几毫秒内判断出哪些 motion primitives 会和障碍相撞,然后从motion primitives中选出最可能朝向目标的一组。
The module also has interface to take in additional range data for collision avoidance as an extension option
模块建立了一个代价地图,地图中的每一个点和一个traversal cost相关联. 代价值取决于 local smoothness of the terrain.
我们使用体素网格表示环境,分析 distributions of data points in adjacent voxels to 估计地面高度. The points are associated with higher traversal costs if they are further apart from the ground.
模块还能处理negative obstacles
,这些障碍生成空区域with no data points on the terrain map. 如果开启了negative obstacle
的处理,模块认为那些区域不可经过
可视化算法的性能. 可视化工具显示地图,已探索区域,车的轨迹. Metrics包括 explored volume, traveling distance, and algorithm runtime are plotted and logged to files.
另外,支持手柄和导航交互,在多种操作模式之间切换 to ease the process of system debugging.
Safety margin: local planner
使用车和waypoint
之间的距离作为规划尺度(planning horizon)。即使waypoint
很接近障碍,也可以让车到达。但是,如果车不能在waypoint
停下,上层规划器倾向于让车到waypoint
保持一定距离(默认≥
3.75m)。If the waypoint is closer, users can project the waypoint further away and keep the waypoint in the same direction w.r.t. the vehicle to fully use the safety margin. (这句话没理解什么意思)
但是,如果车需要经过窄通道,降低这一距离可以让local planner
找到安全合适的路径。
大转弯: Typically, a high-level planner selects the waypoint along the path that is a distance, namely look-ahead distance, ahead of the vehicle and sends the waypoint to the local planner (possibly after projecting the waypoint further away from the vehicle as discussed above).
When handling sharp turns (≥ 90 deg), the look-ahead distance needs to be properly set or the waypoint may jump to the back of the vehicle, causing the vehicle to osculate back-and-forth. We recommend to select the waypoint on the starting segment of the path that is in line-of-sight from the vehicle.
动态障碍: terrain analysis
模块在动态障碍走过之后,通过ray-tracing
清除动态障碍。这是在车的附近范围实现的(到车的距离≤5m), 因为雷达数据在远处比较稀疏,以及难以权衡清除动态障碍和thin structures之间的矛盾。 用户根据自己的情况来清除动态障碍,TARE和FAR都有这一步骤。
The state estimation module can detect and introduce loop closures. The module outputs state estimation in the odometry frame generated by 3D Lidar-based odometry containing accumulated drift. When loop closure is triggered, it outputs loop closure adjustments to globally relax the vehicle trajectory and corresponding maps. Loop closure adjustments are used by the high-level planners since they are in charge of planning at the global scale.
The local planner and terrain analysis modules are extended to handle complex terrains including negative obstacles such as cliffs, pits, and water puddles with a downward-looking depth sensor. The TARE planner, FAR planner, and other planners (for stuck recovery, etc) are run in parallel for tasks such as exploration, go-to waypoint, and return home.
On top of these planners, behavior executive and multi-robot coordination modules are built specifically for the challenge. The modules share explored and unexplored areas across multirobots and call TARE and FAR planners cooperatively. In particular, when a long-distance transition is determined due to new areas containing artifacts are discovered or operator waypoints are received, the behavior executive switches to
FAR planner for relocating the vehicle. During the relocation, FAR planner uses a sparse roadmap merged from multi-robots for high-level guidance. After the relocation is complete, TARE planner takes place for exploration
DARPA最后决赛是在Louisville Mega Cavern, KY
. 赛道包括隧道、urban、洞穴环境。我们的三台车使用TARE
和 FAR
进行探索。
红色轨迹:车先使用TARE一直探索到B,然后使用FAR经过C,一到达C,车换成TARE进行剩下的探索。
绿色轨迹:车只用TARE;蓝色轨迹:车先使用FAR经过A,在换成TARE进行之后的搜索。
三台车各行走596.6m, 499.8m, 445.2m。共花费时间2259s
这里只看论文不太明白,看实际视频才清楚。实际是两辆车和一架无人机进行探索。
这部分我暂时用不到,就不研究了。
训练基于学习的探索和导航算法。大家可以使用我们的仿真平台作为专家系统(expert system)来训练基于学习的规划算法。专家系统里包含状态估计,局部避障,上层的探索或者路径规划算法。训练的对象可以是一些端对端的方法,比如只有一层深度网络的探索或者路径规划算法。
基于激光或者视觉的sim-to-real学习。大家可以用我们的仿真平台训练一些基于学习的方法,并将训练好的系统应用在现实世界中。因为我们提供了多个仿真世界以及支持来自Matterport3D的90个photorealistic环境模型,并且兼容AI Habitat的RGB,深度,和语义(Semantic)图像的渲染功能,所以不管是基于激光还是视觉的算法,大家都可以找到适用的环境模型,当然也可以根据需求换上自己的模型。举个简单的例子,需要做Semantic-in-loop导航的人可以使用我们提供的带有语义信息的环境,使用我们的地面机器人仿真平台,去训练他们的算法,并且在训练结束后,直接将算法移植到实际的机器人上。下面是我们的仿真机器人在Matterport3D的两个环境模型中导航的场景,用AI Habitat实时生成RGB,深度及语义图像。
开发人群导航(social navigation)算法。大家可以在我们的仿真环境中加入动态的障碍物或者行人,模拟真实环境中的社区场景,辅助开发人群导航算法,甚至可以在这种场景中预测动态物体的行为及其轨迹。
Dual-Stage Viewpoint Planner 包含两个阶段:探索阶段用于扩展地图边界,重定位阶段用于 explicitly 把机器人传到环境中不同的子区域。探索阶段采用RRT,并动态地扩展RRT over replanning steps. 重定位阶段维护一个graph结构 through the mapped environment. 在探索过程中,算法在两个阶段来回切换,以探索整个环境。
1 | sudo apt update |
编译结束后,运行1
2
3# 车库仿真环境,可以换成其他的
roslaunch vehicle_simulator system_garage.launch
roslaunch dsvp_launch explore_garage.launch
然后是Matterport3D
环境的配置,先跳过:To run DSV Planner in a Matterport3D environment, follow instructions to setup the development environment to use the Matterport3D environment. Then, use the command lines below to launch the system and DSV Planner.1
2roslaunch vehicle_simulator system_matterport.launch
roslaunch dsvp_launch explore_matterport.launch
local_planner.launch
包括节点localPlanner
和pathFollower
,以及发布sensor ---> vehicle
和 sensor ---> camera
的tf变换
避障: 由local_planner
实现. 程序一启动就先预生成 Motion primitives
. The motion primitives are modeled as Monte Carlo samples and organized in groups 现实中快遇到障碍物时,local planner
可以在几毫秒内判断出哪些 motion primitives 会和障碍相撞,然后从motion primitives中选出最可能朝向目标的一组。
Sending waypoints, navigation boundary, and speed: 一收到waypoint, navigation boundary, and speed 的消息, the system will navigate the vehicle inside the navigation boundary to the waypoint. 发送的navigation boundary
和速度是可设置的,默认速度2m/s
. 可以参考waypoint_example
如何发送这些消息
Waypoint: 话题way_point
,geometry_msgs::PointStamped
类型的消息,在map
坐标系。 发布者当然是rvizGA
和 localPlanner
1 | header: |
Navigation boundary (optional): 话题navigation_boundary
,geometry_msgs::PolygonStamped
的消息, 在map
坐标系。 默认没有发布,订阅者是localPlanner
system_real_robot.launch
中的部分:1
2
3
4
5<include file="$(find local_planner)/launch/local_planner.launch" >
<arg name="cameraOffsetZ" value="$(arg cameraOffsetZ)"/>
<arg name="goalX" value="$(arg vehicleX)"/>
<arg name="goalY" value="$(arg vehicleY)"/>
</include>
这个launch其实就是localPlanner
和 pathFollower
两个节点,再加两个tf转换1
2
3<node pkg="tf" type="static_transform_publisher" name="vehicleTransPublisher" args="-$(arg sensorOffsetX) -$(arg sensorOffsetY) 0 0 0 0 /sensor /vehicle 1000"/>
<node pkg="tf" type="static_transform_publisher" name="sensorTransPublisher" args="0 0 $(arg cameraOffsetZ) -1.5707963 0 -1.5707963 /sensor /camera 1000"/>
节点localPlanner
一直在发布话题path
,可以将源码中的宏PLOTPATHSET
改为0,最好是做成ROS Param.
只有path follower
会发布cmd_vel
,在机器人前往目标点的过程中, local planner会不断的对比机器人当前位置和目标点位置的差距,根据这个差值去控制机器人的直线速度和转向速度,最终不断逼近目标点。
代码中常出现的laserCloud
和vehicleX
都是在map
坐标系下
Matlab文件path_generator.m
的目的是生成3个ply文件和correspondences.txt
。这里就是一个可优化的方向。
生成的的是3个离线的曲线,也就是local_planner\paths
的startPaths.ply
, pathList.ply
, paths.ply
。 这3个文件都在localPlanner.cpp
的main函数里使用
startPaths.ply
文件的文件头1
2
3
4
5
6
7
8ply
format ascii 1.0
element vertex 707 # 点的总数
property float x
property float y
property float z
property int group_id
end_header
然后是很多的点,形式是0.842435 -0.113153 0.000000 2
,依次是x,y,z,索引。可以用Cloud Compare
打开
记录第一次采样的路径点,7个路径组,每个有101个点。每个都是三次样条曲线,根据Matlab中设置的参数,对称的每条路径依次偏移9°,每条路径有101个点,即0:0.01:1
,按说起始点都是(0,0)
,也就是共用了原点,但是从CloudCompare
里看,点数还是707,起点的y坐标相差很小很小,我认为这是Matlab的浮点数误差导致生成了7个起点
代码中对应函数readStartPaths
:读取文件startPaths.ply
,把其中的点都放入点云类型的变量startPaths
同理还有paths.ply
记录三次采样生成的所有路径点,仔细数一数,共有7x7x7=343条路径(第二次采样的路径组分成的7个不应统计), 这和论文里说的35x35=1225不同了。 每条路径有301个点,最右边的点,也就是x最大的点是(3, 0)
。最上方的点大约(1.679, 2.486)
代码中对应函数readPaths
: 读取文件paths.ply
,把其中的点都放入点云类型的变量paths
,但考虑 pointSkipNum
后两段段还是三次样条曲线,但生成的方式有所改变,不再是简单的1:0.01:2
的遍历,而是对角度做了一定比例的缩放,并不是偏移-54°,而是偏移-44.55°和-55.96°。公式比较复杂,就不深入研究了
以最下方的曲线为例,三段的最后一个点的坐标如下:
该文件记录了每条路径的最后一个路径点,共7x7x7=343个点
代码中对应函数readPathList
: 读取文件pathList.ply
,只加入变量pathList
和 endDirPathList
path_generator.m
中的部分如下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# 对于碰撞检查,使用覆盖了传感器范围的体素网格。
# 根据样条距离,传感器范围为 3.2*4.5 ,在该区域生成体素网格,在这里考虑了车辆半径的遮挡
voxelSize = 0.02;
searchRadius = 0.45;
# 根据pathList的形状确定的尺寸,比模拟路径的范围稍大点
offsetX = 3.2;
offsetY = 4.5;
# offsetX / voxelSize
voxelNumX = 161;
# 这里是 offsetY * 2 / voxelSize, 体素范围关于x轴对称
voxelNumY = 451;
fprintf('\nPreparing voxels\n');
indPoint = 1;
voxelPointNum = voxelNumX * voxelNumY;
# 一个有很多行 只有2列的矩阵
voxelPoints = zeros(voxelPointNum, 2);
# 在外层循环中,从外向内计算,同采样的路径一样,靠近车体的位置Y的宽度也会随着scaleY减小
for indX = 0 : voxelNumX - 1
x = offsetX - voxelSize * indX;
scaleY = x / offsetX + searchRadius / offsetY * (offsetX - x) / offsetX;
for indY = 0 : voxelNumY - 1
y = scaleY * (offsetY - voxelSize * indY);
voxelPoints(indPoint, 1) = x;
voxelPoints(indPoint, 2) = y;
indPoint = indPoint + 1;
end
end
# 所有坐标都存到了 voxelPoints, zeros(voxelPointNum, 1)相当于扩展了一列 0
plot3(voxelPoints(:, 1), voxelPoints(:, 2), zeros(voxelPointNum, 1), 'k.');
pause(1.0);
其实这里很简单,逐个计算voxelPoints
,发现它是下图,x
是一个点,点的间距只有0.02
matlab运行结果得到 fig图 如下,如果放大,会发现是密密麻麻的点
再放大,会发现前向的模拟路径在里面
之所以把体素建模为梯形而不是三角形,应该是在起始点考虑了车辆的宽度。
correspondences.txt
在代码中的readCorrespondences
函数使用
path_generator.m
中的代码如下:1
2
3
4
5
6fprintf('\nCollision checking\n');
# rangesearch(X,Y,r):寻找X集合中的点,其与 Y 集合中的点的距离小于r
# 这里就是寻找 paths 的点 和 体素集合中的点中小于搜索半径的点集合
# 记录路径点附近的所有体素网格
[ind, dis] = rangesearch(pathAll(1 : 2, :)', voxelPoints, searchRadius);
# ...... 剩余的省略
直接看文件,每行第一个数是体素网格的索引,即0~72610
。 每行最后一个数是-1,在readCorrespondences
函数会看到这是作为判断该网格是否有对应的路径。 二者中间就是pathList
的pathID
,范围0~342
程序运行时,路径被放置在体素中心的障碍物所遮挡。 在这里,考虑以车辆的半径来计算遮挡,当然不是Matlab里的0.45
最右边的一堆体素网格没有任何路径,这就是txt文件中只有网格索引和-1的情况。
1 | sudo apt update |
创建工程目录mkdir -p autoware.ai/src
,把代码下载到这里,我已经提前下载好,把autoware.ai.repos
也放进去
1 | # 安装依赖项,时间很久 |
同理可以只编译runtime_manager
,启动在src/utilities/runtime_manager/launch/runtime_manager.launch
从OpenCV的github release下载,然后解压
1 | cd opencv-4.2.0 |
添加路径库 sudo vim /etc/ld.so.conf.d/opencv.conf
,打开了一个新文档,在里面写入/usr/local/lib
配置环境变量sudo vim /etc/profile
,在后面添加以下内容
1 | PKG_CONFIG_PATH=$PKG_CONFIG_PATH:/usr/local/lib/pkgconfig |
3.测试1
2
3
4
5
6cd ~
# opencv的源码目录
cd opencv/samples/cpp/example_cmake
cmake .
make
./opencv_example
如果弹出一个视频窗口,有文字hello,opencv,代表安装成功
1 | locate libopencv_video.so |
sudo pip3 install opencv-python
,python后不用加3。对于在Python环境中使用,比如说查看版本1 | cyp@cyp:~$ python |
在使用g++编译使用opencv的C++程序时,使用 g++ <cpp_code> pkg-config opencv --libs --cflags opencv
也可以使用cmake编译
在opencv编译好后,所在目录中一般会有一个叫OpenCVConfig.cmake的文件,这个文件中指定了CMake要去哪里找OpenCV,其.h文件在哪里等,比如其中一行:1
2# Provide the include directories to the caller
set(OpenCV_INCLUDE_DIRS "/home/ubuntu/src/opencv-3.1.0/build" "/home/ubuntu/src/opencv-3.1.0/include" "/home/ubuntu/src/opencv-3.1.0/include/opencv")
只要让CMake找到这个文件,这个文件就指定了Opencv的所有路径,因此设置OpenCV_DIR为包含OpenCVConfig.cmake的目录,如在C++工程CMakeLists.txt中添加:1
set(OpenCV_DIR "/home/ubuntu/src/opencv-3.1.0/build")
因此,我们期望使用哪个版本的Opencv,只要找到对应的OpenCVConfig.cmake文件,并且将其路径添加到工程的CMakeLists.txt中即可了。
joy
话题类型是sensor_msgs/Joy
,发布者rvizGA
,订阅者有:
Rviz上发布waypoint
后,得到的joy
消息,而且每次是相同的:1
2
3
4
5
6
7
8header:
seq: 0
stamp:
secs: 1640595487
nsecs: 707291876
frame_id: "waypoint_tool"
axes: [0.0, 0.0, -1.0, 0.0, 1.0, 1.0, 0.0, 0.0]
buttons: [0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0]
查看joystickHandler
函数,发现joySpeed
和 joySpeedRaw
都会被赋值为 1
话题speed
也没有发布者,提供给用户,类型std_msgs::Float32
,订阅者是pathFollower
和localPlanner
,目前看不出使用的必要。
话题stop
提供给用户,用于停止车的行走,类型std_msgs::Int8
vehicleSpeed
逐步增加,也就是说输出速度是逐渐增加的
1 | string pathFolder; // 使用matlab生成路径集合的文件路径 |