12.ROS導航模塊:gmapping、AMCL、map_server、move_base案例

目錄

1 導航概述

2 導航簡介

2.1 導航模塊簡介

1.全局地圖

2.自身定位

3.路徑規劃

4.運動控制

5.環境感知

2.2 導航坐標系odom、map

1.簡介

2.特點

3.坐標系變換

2.3 導航條件說明

1.硬件

2.軟件

3 導航實現

3.1 創建本篇博客的功能包

3.2 建圖--gmapping

3.2.1 gmapping簡介

3.2.2 gmapping節點說明

3.2.2.1訂閱的Topic

3.2.2.2發布的Topic

3.2.2.3服務

3.2.2.4參數

3.2.2.5所需的坐標變換

3.2.2.6發布的坐標變換

3.2.3 gmapping使用

3.2.3.1編寫gmapping節點相關launch文件

3.2.3.2 執行

3.3 地圖服務 map_server

3.3.1 map_server使用之地圖保存節點(map_saver)

3.3.2? map_server使用之地圖發布節點(map_saver)

3.3.3 地圖配置文件

3.4 amcl定位

3.4.1 概念

3.4.1.1訂閱的Topic

3.4.1.2發布的Topic

3.4.1.3服務

3.4.1.4調用的服務

3.4.1.5參數

3.4.16坐標變換

3.4.2 AMCL的使用

3.4.2.1 編寫AMCL相關的文件

3.4.2.2 編寫測試文件

3.5 路徑規劃move_base、代價地圖

3.5.1 簡介

3.5.2 move_base節點說明

3.5.3?move_base與代價地圖

3.5.4 move_base的使用

3.5.4.1 編寫launch文件

3.5.4.2 配置文件

3.4.5.3 launch文件集成

3.4.5.4 測試

3.4.5.5 顯示全局/本地代價地圖與全局/本地路徑規劃

3.4.5.6 配置文件的解釋

3.4.5.7 參數配置小技巧

3.5.5 導航與SLAM建圖

3.5.5.1?編寫launch文件

4 導航信息

4.1 地圖

4.1.1 nav_msgs/MapMetaData

4.1.2 nav_msgs/OccupancyGrid

4.2 里程計數據

4.3 TF

4.4 定位

4.5 路徑規劃


1 導航概述

????????導航是機器人系統中最重要的模塊之一,比如現在較為流行的服務型室內機器人,就是依賴于機器人導航來實現室內自主移動的,本章主要就是介紹仿真環境下的導航實現,主要內容有:

  • 導航相關概念
  • 導航實現:機器人建圖(SLAM)、地圖服務、定位、路徑規劃....以可視化操作為主。
  • 導航消息:了解地圖、里程計、雷達、攝像頭等相關消息格式。

預期達成的學習目標:

  • 了解導航模塊中的組成部分以及相關概念
  • 能夠在仿真環境下獨立完成機器人導航

2 導航簡介

2.1 導航模塊簡介

????????在ROS中機器人導航(Navigation)由多個功能包組合實現,ROS 中又稱之為導航功能包集,關于導航模塊,官方介紹如下:

一個二維導航堆棧,它接收來自里程計、傳感器流和目標姿態的信息,并輸出發送到移動底盤的安全速度命令。

????????更通俗的講: 導航其實就是機器人自主的從 A 點移動到 B 點的過程。

????????秉著"不重復發明輪子"的原則,ROS 中導航相關的功能包集為機器人導航提供了一套通用的實現,開發者不再需要關注于導航算法、硬件交互... 等偏復雜、偏底層的實現,這些實現都由更專業的研發人員管理、迭代和維護,開發者可以更專注于上層功能,而對于導航功能的調用,只需要根據自身機器人相關參數合理設置各模塊的配置文件即可,當然,如果有必要,也可以基于現有的功能包二次開發實現一些定制化需求,這樣可以大大提高研發效率,縮短產品落地時間。總而言之,對于一般開發者而言,ROS 的導航功能包集優勢如下:

  • 安全: 由專業團隊開發和維護

  • 功能: 功能更穩定且全面

  • 高效: 解放開發者,讓開發者更專注于上層功能實現

????????機器人是如何實現導航的呢?或換言之,機器人是如何從 A 點移動到 B 點呢?ROS 官方為了提供了一張導航功能包集的圖示,該圖中囊括了 ROS 導航的一些關鍵技術:

??????? 假定我們已經以特定方式配置機器人,導航功能包集將使其可以運動。上圖概述了這種配置方式。白色的部分是必須且已實現的組件,灰色的部分是可選且已實現的組件,藍色的部分是必須為每一個機器人平臺創建的組件。

總結下來,涉及的關鍵技術有如下五點:

  1. 全局地圖

  2. 自身定位

  3. 路徑規劃

  4. 運動控制

  5. 環境感知

????????機器人導航實現與無人駕駛類似,關鍵技術也是由上述五點組成,只是無人駕駛是基于室外的,而我們當前介紹的機器人導航更多是基于室內的。

????????

1.全局地圖

在現實生活中,當我們需要實現導航時,可能會首先參考一張全局性質的地圖,然后根據地圖來確定自身的位置、目的地位置,并且也會根據地圖顯示來規劃一條大致的路線.... 對于機器人導航而言,也是如此,在機器人導航中地圖是一個重要的組成元素,當然如果要使用地圖,首先需要繪制地圖。關于地圖建模技術不斷涌現,這其中有一門稱之為 SLAM 的理論脫穎而出:

  1. SLAM(simultaneous localization and mapping),也稱為CML (Concurrent Mapping and Localization), 即時定位與地圖構建,或并發建圖與定位。SLAM問題可以描述為: 機器人在未知環境中從一個未知位置開始移動,在移動過程中根據位置估計和地圖進行自身定位,同時在自身定位的基礎上建造增量式地圖,以繪制出外部環境的完全地圖。

  2. 在 ROS 中,較為常用的 SLAM 實現也比較多,比如: gmapping、hector_slam、cartographer、rgbdslam、ORB_SLAM ....

  3. 當然如果要完成 SLAM ,機器人必須要具備感知外界環境的能力,尤其是要具備獲取周圍環境深度信息的能力。感知的實現需要依賴于傳感器,比如: 激光雷達、攝像頭、RGB-D攝像頭...

  4. SLAM 可以用于地圖生成,而生成的地圖還需要被保存以待后續使用,在 ROS 中保存地圖的功能包是 map_server

另外注意: SLAM 雖然是機器人導航的重要技術之一,但是 二者并不等價,確切的講,SLAM 只是實現地圖構建和即時定位。

2.自身定位

導航伊始和導航過程中,機器人都需要確定當前自身的位置,如果在室外,那么 GPS 是一個不錯的選擇,而如果室內、隧道、地下或一些特殊的屏蔽 GPS 信號的區域,由于 GPS 信號弱化甚至完全不可用,那么就必須另辟蹊徑了,比如前面的 SLAM 就可以實現自身定位,除此之外,ROS 中還提供了一個用于定位的功能包: amcl

amcl(adaptiveMonteCarloLocalization)自適應的蒙特卡洛定位,是用于2D移動機器人的概率定位系統。它實現了自適應(或KLD采樣)蒙特卡洛定位方法,該方法使用粒子過濾器根據已知地圖跟蹤機器人的姿態。

3.路徑規劃

導航就是機器人從A點運動至B點的過程,在這一過程中,機器人需要根據目標位置計算全局運動路線,并且在運動過程中,還需要時時根據出現的一些動態障礙物調整運動路線,直至到達目標點,該過程就稱之為路徑規劃。在 ROS 中提供了 move_base 包來實現路徑規則,該功能包主要由兩大規劃器組成:

  1. 全局路徑規劃(gloable_planner)

    根據給定的目標點和全局地圖實現總體的路徑規劃,使用 Dijkstra 或 A* 算法進行全局路徑規劃,計算最優路線,作為全局路線

  2. 本地時時規劃(local_planner)

    在實際導航過程中,機器人可能無法按照給定的全局最優路線運行,比如:機器人在運行中,可能會隨時出現一定的障礙物... 本地規劃的作用就是使用一定算法(Dynamic Window Approaches) 來實現障礙物的規避,并選取當前最優路徑以盡量符合全局最優路徑

全局路徑規劃與本地路徑規劃是相對的,全局路徑規劃側重于全局、宏觀實現,而本地路徑規劃側重與當前、微觀實現。

4.運動控制

導航功能包集假定它可以通過話題"cmd_vel"發布geometry_msgs/Twist類型的消息,這個消息基于機器人的基座坐標系,它傳遞的是運動命令。這意味著必須有一個節點訂閱"cmd_vel"話題, 將該話題上的速度命令轉換為電機命令并發送。

5.環境感知

感知周圍環境信息,比如: 攝像頭、激光雷達、編碼器...,攝像頭、激光雷達可以用于感知外界環境的深度信息,編碼器可以感知電機的轉速信息,進而可以獲取速度信息并生成里程計信息。

在導航功能包集中,環境感知也是一重要模塊實現,它為其他模塊提供了支持。其他模塊諸如: SLAM、amcl、move_base 都需要依賴于環境感知。

2.2 導航坐標系odom、map

1.簡介

定位是導航中的重要實現之一,所謂定位,就是參考某個坐標系(比如:以機器人的出發點為原點創建坐標系)在該坐標系中標注機器人。定位原理看似簡單,但是這個這個坐標系不是客觀存在的,我們也無法以上帝視角確定機器人的位姿,定位實現需要依賴于機器人自身,機器人需要逆向推導參考系原點并計算坐標系相對關系,該過程實現常用方式有兩種:

  • 通過里程計定位:時時收集機器人的速度信息計算并發布機器人坐標系與父級參考系的相對關系。
  • 通過傳感器定位:通過傳感器收集外界環境信息通過匹配計算并發布機器人坐標系與父級參考系的相對關系。

兩種方式在導航中都會經常使用。

2.特點

兩種定位方式都有各自的優缺點。

里程計定位:

  • 優點:里程計定位信息是連續的,沒有離散的跳躍。
  • 缺點:里程計存在累計誤差,不利于長距離或長期定位。

傳感器定位:

  • 優點:比里程計定位更精準;
  • 缺點:傳感器定位會出現跳變的情況,且傳感器定位在標志物較少的環境下,其定位精度會大打折扣。

兩種定位方式優缺點互補,應用時一般二者結合使用。

3.坐標系變換

上述兩種定位實現中,機器人坐標系一般使用機器人模型中的根坐標系(base_link 或 base_footprint),里程計定位時,父級坐標系一般稱之為 odom,如果通過傳感器定位,父級參考系一般稱之為 map。當二者結合使用時,map 和 odom 都是機器人模型根坐標系的父級,這是不符合坐標變換中"單繼承"的原則的,所以,一般會將轉換關系設置為: map -> odom -> base_link 或 base_footprint。

2.3 導航條件說明

導航實現,在硬件和軟件方面是由一定要求的,需要提前準備。

1.硬件

雖然導航功能包集被設計成盡可能的通用,在使用時仍然有三個主要的硬件限制:

  1. 它是為差速驅動的輪式機器人設計的。它假設底盤受到理想的運動命令的控制并可實現預期的結果,命令的格式為:x速度分量,y速度分量,角速度(theta)分量。

  2. 它需要在底盤上安裝一個單線激光雷達。這個激光雷達用于構建地圖和定位。

  3. 導航功能包集是為正方形的機器人開發的,所以方形或圓形的機器人將是性能最好的。 它也可以工作在任意形狀和大小的機器人上,但是較大的機器人將很難通過狹窄的空間。

2.軟件

導航功能實現之前,需要搭建一些軟件環境:

  1. 毋庸置疑的,必須先要安裝 ROS

  2. 當前導航基于仿真環境,先保證上一章的機器人系統仿真可以正常執行

    在仿真環境下,機器人可以正常接收 /cmd_vel 消息,并發布里程計消息,傳感器消息發布也正常,也即導航模塊中的運動控制和環境感知實現完畢

后續導航實現中,我們主要關注于: 使用 SLAM 繪制地圖、地圖服務、自身定位與路徑規劃。

3 導航實現

本節內容主要介紹導航的完整性實現,旨在掌握機器人導航的基本流程,該章涉及的主要內容如下:

  • SLAM建圖(選用較為常見的gmapping)

  • 地圖服務(可以保存和重現地圖)

  • 機器人定位

  • 路徑規劃

  • 上述流程介紹完畢,還會對功能進一步集成實現探索式的SLAM建圖。


準備工作

請先安裝相關的ROS功能包:

  • 安裝 gmapping 包(用于構建地圖):sudo apt install ros-<ROS版本>-gmapping

  • 安裝地圖服務包(用于保存與讀取地圖):sudo apt install ros-<ROS版本>-map-server

  • 安裝 navigation 包(用于定位以及路徑規劃):sudo apt install ros-<ROS版本>-navigation

新建功能包,并導入依賴: gmapping map_server amcl move_base

3.1 創建本篇博客的功能包

??????? CMakeLists.txt配置:

cmake_minimum_required(VERSION 2.8.3)
project(nav_robot)######################
### Cmake flags
######################
set(CMAKE_BUILD_TYPE "Release")
set(CMAKE_CXX_FLAGS "-std=c++11")
set(CMAKE_CXX_FLAGS_RELEASE "-O3 -Wall -g -pthread")find_package(catkin REQUIRED COMPONENTSroscpprospyroslib# msgurdfxacrogmappingmap_serveramclmove_base
)catkin_package()include_directories(${catkin_INCLUDE_DIRS})

??????? package.xml配置:

<?xml version="1.0"?>
<package><name>nav_robot</name><version>0.0.0</version><description>A test</description><maintainer email="haha@nefu.com">haha</maintainer><author>HITLHW</author><license>BSD-3</license><buildtool_depend>catkin</buildtool_depend><build_depend>gmapping</build_depend><run_depend>gmapping</run_depend><build_depend>map_server</build_depend><run_depend>map_server</run_depend><build_depend>amcl</build_depend><run_depend>amcl</run_depend><build_depend>move_base</build_depend><run_depend>move_base</run_depend></package>

??????? 編譯一下:

??????? 沒問題。

3.2 建圖--gmapping

3.2.1 gmapping簡介

SLAM算法有多種,當前我們選用gmapping,后續會再介紹其他幾種常用的SLAM實現。

gmapping 是ROS開源社區中較為常用且比較成熟的SLAM算法之一,gmapping可以根據移動機器人里程計數據和激光雷達數據來繪制二維的柵格地圖,對應的,gmapping對硬件也有一定的要求:

  • 該移動機器人可以發布里程計消息
  • 機器人需要發布雷達消息(該消息可以通過水平固定安裝的雷達發布,或者也可以將深度相機消息轉換成雷達消息)

關于里程計與雷達數據,仿真環境中可以正常獲取的,不再贅述,柵格地圖如案例所示。

gmapping 安裝前面也有介紹,命令如下:

sudo apt install ros-<ROS版本>-gmapping

3.2.2 gmapping節點說明

gmapping 功能包中的核心節點是:slam_gmapping。為了方便調用,需要先了解該節點訂閱的話題、發布的話題、服務以及相關參數。

3.2.2.1訂閱的Topic

tf (tf/tfMessage)

  • 用于雷達、底盤與里程計之間的坐標變換消息。

scan(sensor_msgs/LaserScan)

  • SLAM所需的雷達信息。
3.2.2.2發布的Topic

map_metadata(nav_msgs/MapMetaData)

  • 地圖元數據,包括地圖的寬度、高度、分辨率等,該消息會固定更新。

map(nav_msgs/OccupancyGrid)

  • 地圖柵格數據,一般會在rviz中以圖形化的方式顯示。

~entropy(std_msgs/Float64)

  • 機器人姿態分布熵估計(值越大,不確定性越大)。
3.2.2.3服務

dynamic_map(nav_msgs/GetMap)

  • 用于獲取地圖數據。
3.2.2.4參數

~base_frame(string, default:"base_link")

  • 機器人基坐標系。

~map_frame(string, default:"map")

  • 地圖坐標系。

~odom_frame(string, default:"odom")

  • 里程計坐標系。

~map_update_interval(float, default: 5.0)

  • 地圖更新頻率,根據指定的值設計更新間隔。

~maxUrange(float, default: 80.0)

  • 激光探測的最大可用范圍(超出此閾值,被截斷)。

~maxRange(float)

  • 激光探測的最大范圍。

.... 參數較多,上述是幾個較為常用的參數,其他參數介紹可參考官網。

3.2.2.5所需的坐標變換

雷達坐標系→基坐標系

  • 一般由 robot_state_publisher 或 static_transform_publisher 發布。

基坐標系→里程計坐標系

  • 一般由里程計節點發布。
3.2.2.6發布的坐標變換

地圖坐標系→里程計坐標系

  • 地圖到里程計坐標系之間的變換。

3.2.3 gmapping使用

3.2.3.1編寫gmapping節點相關launch文件
<launch>
<param name="use_sim_time" value="true"/><node pkg="gmapping" type="slam_gmapping" name="slam_gmapping" output="screen"><remap from="scan" to="scan"/><param name="base_frame" value="base_footprint"/><!--底盤坐標系--><param name="odom_frame" value="odom"/> <!--里程計坐標系--><param name="map_update_interval" value="5.0"/><param name="maxUrange" value="16.0"/><param name="sigma" value="0.05"/><param name="kernelSize" value="1"/><param name="lstep" value="0.05"/><param name="astep" value="0.05"/><param name="iterations" value="5"/><param name="lsigma" value="0.075"/><param name="ogain" value="3.0"/><param name="lskip" value="0"/><param name="srr" value="0.1"/><param name="srt" value="0.2"/><param name="str" value="0.1"/><param name="stt" value="0.2"/><param name="linearUpdate" value="1.0"/><param name="angularUpdate" value="0.5"/><param name="temporalUpdate" value="3.0"/><param name="resampleThreshold" value="0.5"/><param name="particles" value="30"/><param name="xmin" value="-50.0"/><param name="ymin" value="-50.0"/><param name="xmax" value="50.0"/><param name="ymax" value="50.0"/><param name="delta" value="0.05"/><param name="llsamplerange" value="0.01"/><param name="llsamplestep" value="0.01"/><param name="lasamplerange" value="0.005"/><param name="lasamplestep" value="0.005"/></node><node pkg="joint_state_publisher" name="joint_state_publisher" type="joint_state_publisher" /><node pkg="robot_state_publisher" name="robot_state_publisher" type="robot_state_publisher" /><node pkg="rviz" type="rviz" name="rviz" /><!-- 可以保存 rviz 配置并后期直接使用--><!--<node pkg="rviz" type="rviz" name="rviz"/>-->
</launch>

??????? 參數:

1.use_sim_time:使用仿真時間,仿真下設置該參數為true。

2.<remap from="scan" to="scan"/> 設置雷達話題:to后面要設置為自己激光雷達的話題

3.map_update_interval 地圖更新時間

4.maxUrange 雷達長度閾值

5.必須設置的:

????? <param name="base_frame" value="base_footprint"/><!--底盤坐標系-->
????? <param name="odom_frame" value="odom"/> <!--里程計坐標系-->

3.2.3.2 執行

1.先啟動 Gazebo 仿真環境(此過程略)(上篇博客的)

roslaunch test gazebo_car.launch

2.然后再啟動地圖繪制的 launch 文件:

roslaunch nav_robot gmmaping.launch

3.啟動鍵盤鍵盤控制節點,用于控制機器人運動建圖

rosrun teleop_twist_keyboard teleop_twist_keyboard.py

??????? 調節RVIZ顯示

??????? 這三個是重合的。

??????? 我們添加map:

??????? 控制機器人運動構建地圖。

??????? 撞上了,...。

3.3 地圖服務 map_server

????????上一節我們已經實現通過gmapping的構建地圖并在rviz中顯示了地圖,不過,上一節中地圖數據是保存在內存中的,當節點關閉時,數據也會被一并釋放,我們需要將柵格地圖序列化到的磁盤以持久化存儲,后期還要通過反序列化讀取磁盤的地圖數據再執行后續操作。在ROS中,地圖數據的序列化與反序列化可以通過 map_server 功能包實現。

????????map_server功能包中提供了兩個節點: map_saver 和 map_server,前者用于將柵格地圖保存到磁盤,后者讀取磁盤的柵格地圖并以服務的方式提供出去。

3.3.1 map_server使用之地圖保存節點(map_saver)

訂閱的topic:

map(nav_msgs/OccupancyGrid)

  • 訂閱此話題用于生成地圖文件。

????????地圖保存的語法比較簡單,編寫一個launch文件,內容如下:

<launch><arg name="filename" value="$(find mycar_nav)/map/nav" /><node name="map_save" pkg="map_server" type="map_saver" args="-f $(arg filename)" />
</launch>

????????其中 mymap 是指地圖的保存路徑以及保存的文件名稱。

????????SLAM建圖完畢后,執行該launch文件即可。

測試:

首先,參考上一節,依次啟動仿真環境,鍵盤控制節點與SLAM節點;

然后,通過鍵盤控制機器人運動并繪圖;

最后,通過上述地圖保存方式保存地圖。

結果:在指定路徑下會生成兩個文件,xxx.pgm 與 xxx.yaml

??????? 第一行是地圖保存的地址:我們創立文件夾:

??????? 第二行:filename是保存的地圖的名稱,我們來演示一下。

roslaunch test gazebo_car.launch
roslaunch nav_robot gmmaping.launch
rosrun teleop_twist_keyboard teleop_twist_keyboard.py

??????? 我們建立好地圖后,啟動我們的地圖保存節點:

roslaunch nav_robot octomapserver.launch

??????? 發現地圖已經被保存下來了:

????????xxx.pgm 本質是一張圖片,直接使用圖片查看程序即可打開。

????????xxx.yaml 保存的是地圖的元數據信息,用于描述圖片,內容格式如下:

image: /home/liuhongwei/Desktop/final/nav_zhaoxuzuo/src/map/nav.pgm
resolution: 0.050000
origin: [-50.000000, -50.000000, 0.000000]
negate: 0
occupied_thresh: 0.65
free_thresh: 0.196

3.3.2? map_server使用之地圖發布節點(map_saver)

發布的話題

map_metadata(nav_msgs / MapMetaData)

  • 發布地圖元數據。

map(nav_msgs / OccupancyGrid)

  • 地圖數據。

服務

static_map(nav_msgs / GetMap)

  • 通過此服務獲取地圖。

參數

?frame_id(字符串,默認值:“map”)

  • 地圖坐標系。
<launch><!-- 設置地圖的配置文件 --><arg name="map" default="nav.yaml" /><!-- 運行地圖服務器,并且加載設置的地圖--><node name="map_server" pkg="map_server" type="map_server" args="$(find mycar_nav)/map/$(arg map)"/>
</launch>

??????? 直接執行這個launch文件就行。

??????? 我們在rviz添加map組件:

3.3.3 地圖配置文件

??????? 1.image:地圖資源的路徑

??????? 2.resolutuin:地圖刻度尺單位 m/像素

??????? 3.origin:地圖的位姿信息(相對于rviz的原點信息)

??????? 4.occupied_thresh:占用閾值

??????? 5.free_thresh:空閑閾值,判斷地圖某一點是否被占用

??????? 6.negate:取反

??????? 為了演示這些參數的作用,我們打開RVIZ:

????????origin就是右下角相對于axis的偏移。X+50 Y-50。第三個角度為偏航角度。

??????? 我們如果把第三個參數改稱0.3(弧度)

??????? 對于占用閾值,地圖中的障礙物判斷:

??????? 規則:白色可通行 黑色障礙物 藍黑未知區域,怎么判斷呢???地圖中每個像素都有取值[0,255] 白色255 黑0 ,像素值設置為x。根據像素值設置一個比例:

??????? p = 255-x / 255 白色0黑色1,如果p>占用閾值為障礙物,p<空閑閾值可以通行。

??????? 取反是黑的變白,白變黑。

3.4 amcl定位

3.4.1 概念

????????所謂定位就是推算機器人自身在全局地圖中的位置,當然,SLAM中也包含定位算法實現,不過SLAM的定位是用于構建全局地圖的,是屬于導航開始之前的階段,而當前定位是用于導航中,導航中,機器人需要按照設定的路線運動,通過定位可以判斷機器人的實際軌跡是否符合預期。在ROS的導航功能包集navigation中提供了 amcl 功能包,用于實現導航中的機器人定位。

????????AMCL(adaptive Monte Carlo Localization) 是用于2D移動機器人的概率定位系統,它實現了自適應(或KLD采樣)蒙特卡洛定位方法,可以根據已有地圖使用粒子濾波器推算機器人位置。

????????amcl 功能包中的核心節點是:amcl。為了方便調用,需要先了解該節點訂閱的話題、發布的話題、服務以及相關參數。

3.4.1.1訂閱的Topic

scan(sensor_msgs/LaserScan)

  • 激光雷達數據。

tf(tf/tfMessage)

  • 坐標變換消息。

initialpose(geometry_msgs/PoseWithCovarianceStamped)

  • 用來初始化粒子濾波器的均值和協方差。

map(nav_msgs/OccupancyGrid)

  • 獲取地圖數據。
3.4.1.2發布的Topic

amcl_pose(geometry_msgs/PoseWithCovarianceStamped)

  • 機器人在地圖中的位姿估計。

particlecloud(geometry_msgs/PoseArray)

  • 位姿估計集合,rviz中可以被 PoseArray 訂閱然后圖形化顯示機器人的位姿估計集合。

tf(tf/tfMessage)

  • 發布從 odom 到 map 的轉換。
3.4.1.3服務

global_localization(std_srvs/Empty)

  • 初始化全局定位的服務。

request_nomotion_update(std_srvs/Empty)

  • 手動執行更新和發布更新的粒子的服務。

set_map(nav_msgs/SetMap)

  • 手動設置新地圖和姿態的服務。
3.4.1.4調用的服務

static_map(nav_msgs/GetMap)

  • 調用此服務獲取地圖數據。
3.4.1.5參數

~odom_model_type(string, default:"diff")

  • 里程計模型選擇: "diff","omni","diff-corrected","omni-corrected" (diff 差速、omni 全向輪)

~odom_frame_id(string, default:"odom")

  • 里程計坐標系。

~base_frame_id(string, default:"base_link")

  • 機器人極坐標系。

~global_frame_id(string, default:"map")

3.4.16坐標變換

里程計本身也是可以協助機器人定位的,不過里程計存在累計誤差且一些特殊情況時(車輪打滑)會出現定位錯誤的情況,amcl 則可以通過估算機器人在地圖坐標系下的姿態,再結合里程計提高定位準確度。

  • 里程計定位:只是通過里程計數據實現 /odom_frame 與 /base_frame 之間的坐標變換。
  • amcl定位: 可以提供 /map_frame 、/odom_frame 與 /base_frame 之間的坐標變換。

3.4.2 AMCL的使用

3.4.2.1 編寫AMCL相關的文件
<launch>
<node pkg="amcl" type="amcl" name="amcl" output="screen"><!-- Publish scans from best pose at a max of 10 Hz --><param name="odom_model_type" value="diff"/><!-- 里程計模式為差分 --><param name="odom_alpha5" value="0.1"/><param name="transform_tolerance" value="0.2" /><param name="gui_publish_rate" value="10.0"/><param name="laser_max_beams" value="30"/><param name="min_particles" value="500"/><param name="max_particles" value="5000"/><param name="kld_err" value="0.05"/><param name="kld_z" value="0.99"/><param name="odom_alpha1" value="0.2"/><param name="odom_alpha2" value="0.2"/><!-- translation std dev, m --><param name="odom_alpha3" value="0.8"/><param name="odom_alpha4" value="0.2"/><param name="laser_z_hit" value="0.5"/><param name="laser_z_short" value="0.05"/><param name="laser_z_max" value="0.05"/><param name="laser_z_rand" value="0.5"/><param name="laser_sigma_hit" value="0.2"/><param name="laser_lambda_short" value="0.1"/><param name="laser_lambda_short" value="0.1"/><param name="laser_model_type" value="likelihood_field"/><!-- <param name="laser_model_type" value="beam"/> --><param name="laser_likelihood_max_dist" value="2.0"/><param name="update_min_d" value="0.2"/><param name="update_min_a" value="0.5"/><param name="odom_frame_id" value="odom"/><!-- 里程計坐標系 --><param name="base_frame_id" value="base_footprint"/><!-- 添加機器人基坐標系 --><param name="global_frame_id" value="map"/><!-- 添加地圖坐標系 --><param name="resample_interval" value="1"/><param name="transform_tolerance" value="0.1"/><param name="recovery_alpha_slow" value="0.0"/><param name="recovery_alpha_fast" value="0.0"/>
</node>
</launch>

????????odom_model_type:運動類型,差速

???????? <param name="odom_frame_id" value="odom"/><!-- 里程計坐標系 -->
?????????<param name="base_frame_id" value="base_footprint"/><!-- 添加機器人基坐標系 -->
?????????<param name="global_frame_id" value="map"/><!-- 添加地圖坐標系 -->

3.4.2.2 編寫測試文件

??????? testamcl.launch

????????amcl節點是不可以單獨運行的,運行 amcl 節點之前,需要先加載全局地圖,然后啟動 rviz 顯示定位結果,上述節點可以集成進launch文件,內容示例如下:

<launch><arg name="map" default="nav.yaml" /><node name="map_server" pkg="map_server" type="map_server" args="$(find nav_robot)/map/$(arg map)"/><include file="$(find nav_robot)/launch/amcl.launch" /><node pkg="rviz" type="rviz" name="rviz"/>
</launch>

??????? 先啟動gazebo仿真環境:roslaunch test gazebo_car.launch

??????? 啟動鍵盤控制節點:rosrun teleop_twist_keyboard tele_twist_keyboard.py

??????? 啟動集成的amcl的launch文件:roslaunch nav_robot testamcl.launch

??????? 啟動如下節點: ???

<node pkg="joint_state_publisher" type="joint_state_publisher" name="joint_state_publisher" />
<node pkg="robot_state_publisher" type="robot_state_publisher" name="robot_state_publisher" />

????????在啟動的 rviz 中,添加RobotModel、Map組件,分別顯示機器人模型與地圖,添加 posearray 插件,設置topic為particlecloud來顯示 amcl 預估的當前機器人的位姿,箭頭越是密集,說明當前機器人處于此位置的概率越高;

??????? 我們控制機器人運動!

????????箭頭越是密集,說明當前機器人處于此位置的概率越高;

3.5 路徑規劃move_base、代價地圖

3.5.1 簡介

????????毋庸置疑的,路徑規劃是導航中的核心功能之一,在ROS的導航功能包集navigation中提供了 move_base 功能包,用于實現此功能。

????????move_base 功能包提供了基于動作(action)的路徑規劃實現,move_base 可以根據給定的目標點,控制機器人底盤運動至目標位置,并且在運動過程中會連續反饋機器人自身的姿態與目標點的狀態信息。如前所述move_base主要由全局路徑規劃與本地路徑規劃組成。

3.5.2 move_base節點說明

????????move_base功能包中的核心節點是:move_base。為了方便調用,需要先了解該節點action、訂閱的話題、發布的話題、服務以及相關參數。

動作訂閱

move_base/goal(move_base_msgs/MoveBaseActionGoal)

  • move_base 的運動規劃目標。

move_base/cancel(actionlib_msgs/GoalID)

  • 取消目標。

動作發布

move_base/feedback(move_base_msgs/MoveBaseActionFeedback)

  • 連續反饋的信息,包含機器人底盤坐標。

move_base/status(actionlib_msgs/GoalStatusArray)

  • 發送到move_base的目標狀態信息。

move_base/result(move_base_msgs/MoveBaseActionResult)

  • 操作結果(此處為空)。

訂閱的Topic

move_base_simple/goal(geometry_msgs/PoseStamped)

  • 運動規劃目標(與action相比,沒有連續反饋,無法追蹤機器人執行狀態)。

發布的Topic

cmd_vel(geometry_msgs/Twist)

  • 輸出到機器人底盤的運動控制消息。

服務

~make_plan(nav_msgs/GetPlan)

  • 請求該服務,可以獲取給定目標的規劃路徑,但是并不執行該路徑規劃。

~clear_unknown_space(std_srvs/Empty)

  • 允許用戶直接清除機器人周圍的未知空間。

~clear_costmaps(std_srvs/Empty)

  • 允許清除代價地圖中的障礙物,可能會導致機器人與障礙物碰撞,請慎用。

3.5.3?move_base與代價地圖

????????機器人導航(尤其是路徑規劃模塊)是依賴于地圖的,地圖在SLAM時已經有所介紹了,ROS中的地圖其實就是一張圖片,這張圖片有寬度、高度、分辨率等元數據,在圖片中使用灰度值來表示障礙物存在的概率。不過SLAM構建的地圖在導航中是不可以直接使用的,因為:

  1. SLAM構建的地圖是靜態地圖,而導航過程中,障礙物信息是可變的,可能障礙物被移走了,也可能添加了新的障礙物,導航中需要時時的獲取障礙物信息;
  2. 在靠近障礙物邊緣時,雖然此處是空閑區域,但是機器人在進入該區域后可能由于其他一些因素,比如:慣性、或者不規則形體的機器人轉彎時可能會與障礙物產生碰撞,安全起見,最好在地圖的障礙物邊緣設置警戒區,盡量禁止機器人進入...

所以,靜態地圖無法直接應用于導航,其基礎之上需要添加一些輔助信息的地圖,比如時時獲取的障礙物數據,基于靜態地圖添加的膨脹區等數據。

????????

????????代價地圖有兩張:global_costmap(全局代價地圖) 和 local_costmap(本地代價地圖),前者用于全局路徑規劃,后者用于本地路徑規劃。

兩張代價地圖都可以多層疊加,一般有以下層級:

  • Static Map Layer:靜態地圖層,SLAM構建的靜態地圖。

  • Obstacle Map Layer:障礙地圖層,傳感器感知的障礙物信息。

  • Inflation Layer:膨脹層,在以上兩層地圖上進行膨脹(向外擴張),以避免機器人的外殼會撞上障礙物。

  • Other Layers:自定義costmap。

上圖中,橫軸是距離機器人中心的距離,縱軸是代價地圖中柵格的灰度值。

  • 致命障礙:柵格值為254,此時障礙物與機器人中心重疊,必然發生碰撞;
  • 內切障礙:柵格值為253,此時障礙物處于機器人的內切圓內,必然發生碰撞;
  • 外切障礙:柵格值為[128,252],此時障礙物處于其機器人的外切圓內,處于碰撞臨界,不一定發生碰撞;
  • 非自由空間:柵格值為(0,127],此時機器人處于障礙物附近,屬于危險警戒區,進入此區域,將來可能會發生碰撞;
  • 自由區域:柵格值為0,此處機器人可以自由通過;
  • 未知區域:柵格值為255,還沒探明是否有障礙物。

膨脹空間的設置可以參考非自由空間。

3.5.4 move_base的使用

路徑規劃算法在move_base功能包的move_base節點中已經封裝完畢了,但是還不可以直接調用,因為算法雖然已經封裝了,但是該功能包面向的是各種類型支持ROS的機器人,不同類型機器人可能大小尺寸不同,傳感器不同,速度不同,應用場景不同....最后可能會導致不同的路徑規劃結果,那么在調用路徑規劃節點之前,我們還需要配置機器人參數。具體實現如下:

  1. 先編寫launch文件模板
  2. 編寫配置文件
  3. 集成導航相關的launch文件
  4. 測試
3.5.4.1 編寫launch文件
<launch><node pkg="move_base" type="move_base" respawn="false" name="move_base" output="screen" clear_params="true"><rosparam file="$(find 功能包)/param/costmap_common_params.yaml" command="load" ns="global_costmap" /><rosparam file="$(find 功能包)/param/costmap_common_params.yaml" command="load" ns="local_costmap" /><rosparam file="$(find 功能包)/param/local_costmap_params.yaml" command="load" /><rosparam file="$(find 功能包)/param/global_costmap_params.yaml" command="load" /><rosparam file="$(find 功能包)/param/base_local_planner_params.yaml" command="load" /></node></launch>

????????clear_params:這個節點執行之前,參數重置。

????????respawn:節點關閉后不會重啟。

????????在功能包下新建 param 目錄,復制下載的文件到此目錄: costmap_common_params_burger.yaml、local_costmap_params.yaml、global_costmap_params.yaml、base_local_planner_params.yaml,并將costmap_common_params_burger.yaml 重命名為:costmap_common_params.yaml。

3.5.4.2 配置文件
#機器人幾何參,如果機器人是圓形,設置 robot_radius,如果是其他形狀設置 footprint
robot_radius: 0.12 #圓形
# footprint: [[-0.12, -0.12], [-0.12, 0.12], [0.12, 0.12], [0.12, -0.12]] #其他形狀obstacle_range: 3.0 # 用于障礙物探測,比如: 值為 3.0,意味著檢測到距離小于 3 米的障礙物時,就會引入代價地圖
raytrace_range: 3.5 # 用于清除障礙物,比如:值為 3.5,意味著清除代價地圖中 3.5 米以外的障礙物#膨脹半徑,擴展在碰撞區域以外的代價區域,使得機器人規劃路徑避開障礙物
inflation_radius: 0.2
#代價比例系數,越大則代價值越小
cost_scaling_factor: 3.0#地圖類型
map_type: costmap
#導航包所需要的傳感器
observation_sources: scan
#對傳感器的坐標系和數據進行配置。這個也會用于代價地圖添加和清除障礙物。例如,你可以用激光雷達傳感器用于在代價地圖添加障礙物,再添加kinect用于導航和清除障礙物。
scan: {sensor_frame: laser, data_type: LaserScan, topic: scan, marking: true, clearing: true}
global_costmap:global_frame: map #地圖坐標系robot_base_frame: base_footprint #機器人坐標系# 以此實現坐標變換update_frequency: 1.0 #代價地圖更新頻率publish_frequency: 1.0 #代價地圖的發布頻率transform_tolerance: 0.5 #等待坐標變換發布信息的超時時間static_map: true # 是否使用一個地圖或者地圖服務器來初始化全局代價地圖,如果不使用靜態地圖,這個參數為false.
local_costmap:global_frame: odom #里程計坐標系robot_base_frame: base_footprint #機器人坐標系update_frequency: 10.0 #代價地圖更新頻率publish_frequency: 10.0 #代價地圖的發布頻率transform_tolerance: 0.5 #等待坐標變換發布信息的超時時間static_map: false  #不需要靜態地圖,可以提升導航效果rolling_window: true #是否使用動態窗口,默認為false,在靜態的全局地圖中,地圖不會變化width: 3 # 局部地圖寬度 單位是 mheight: 3 # 局部地圖高度 單位是 mresolution: 0.05 # 局部地圖分辨率 單位是 m,一般與靜態地圖分辨率保持一致
TrajectoryPlannerROS:# Robot Configuration Parametersmax_vel_x: 0.5 # X 方向最大速度min_vel_x: 0.1 # X 方向最小速速max_vel_theta:  1.0 # min_vel_theta: -1.0min_in_place_vel_theta: 1.0acc_lim_x: 1.0 # X 加速限制acc_lim_y: 0.0 # Y 加速限制acc_lim_theta: 0.6 # 角速度加速限制# Goal Tolerance Parameters,目標公差xy_goal_tolerance: 0.10yaw_goal_tolerance: 0.05# Differential-drive robot configuration
# 是否是全向移動機器人holonomic_robot: false# Forward Simulation Parameters,前進模擬參數sim_time: 0.8vx_samples: 18vtheta_samples: 20sim_granularity: 0.05

3.4.5.3 launch文件集成

??????? 如果要實現導航,需要集成地圖服務、amcl 、move_base 與 Rviz 等,集成示例如下:

<launch><arg name="map" default="nav.yaml" /><node name="map_server" pkg="map_server" type="map_server" args="$(find nav_robot)/map/$(arg map)"/><include file="$(find nav_robot)/launch/amcl.launch" /><include file="$(find nav_robot)/launch/move_base.launch" /><node pkg="rviz" type="rviz" name="rviz" /><node pkg="joint_state_publisher" type="joint_state_publisher" name="joint_state_publisher" /><node pkg="robot_state_publisher" type="robot_state_publisher" name="robot_state_publisher" /></launch>

3.4.5.4 測試

1.先啟動 Gazebo 仿真環境(此過程略);

roslaunch test gazebo_car.launch

2.啟動導航相關的 launch 文件;

roslaunch nav_robot nav_test.launch

3.添加Rviz組件(參考演示結果),可以將配置數據保存,后期直接調用;

??????? 我們選擇一個2D Nav。

??????? 等一回。。。

??????? 導航到了!

3.4.5.5 顯示全局/本地代價地圖與全局/本地路徑規劃

??????? 我們先在RVIZ中提供一個全局的代價地圖:

??????? 再添加一個本地代價地圖:

??????? 添加路徑的全局路徑規劃,本地路徑規劃:

3.4.5.6 配置文件的解釋

costmap_common_params.yaml

????????該文件是move_base 在全局路徑規劃與本地路徑規劃時調用的通用參數,包括:機器人的尺寸、距離障礙物的安全距離、傳感器信息等。配置參考如下:

#機器人幾何參,如果機器人是圓形,設置 robot_radius,如果是其他形狀設置 footprint
robot_radius: 0.12 #圓形
# footprint: [[-0.12, -0.12], [-0.12, 0.12], [0.12, 0.12], [0.12, -0.12]] #其他形狀obstacle_range: 3.0 # 用于障礙物探測,比如: 值為 3.0,意味著檢測到距離小于 3 米的障礙物時,就會引入代價地圖
raytrace_range: 3.5 # 用于清除障礙物,比如:值為 3.5,意味著清除代價地圖中 3.5 米以外的障礙物#膨脹半徑,擴展在碰撞區域以外的代價區域,使得機器人規劃路徑避開障礙物
inflation_radius: 0.2(米)
#代價比例系數,越大則代價值越小
cost_scaling_factor: 3.0#地圖類型
map_type: costmap
#導航包所需要的傳感器
observation_sources: scan
#對傳感器的坐標系和數據進行配置。這個也會用于代價地圖添加和清除障礙物。例如,你可以用激光雷達傳感器用于在代價地圖添加障礙物,再添加kinect用于導航和清除障礙物。
scan: {sensor_frame: laser, data_type: LaserScan, topic: scan, marking: true, clearing: true}

??????? 我們的機器人是0.1m,但是考慮到還有一些別的突出,,把它的半徑設置為0.1m。

????????obstacle_range、raytrace_range表示當動態物體進入的時候,什么時候加入RVIZ中的代價地圖(障礙物距離我3m時會引入代價地圖中,障礙物距離我3.5m外清除出代價地圖)

??????? 將膨脹半徑增加,看看會出現什么樣的效果:

????????代價比例系數,越大則代價值越小。

??????? #導航包所需要的傳感器
????????observation_sources: scan
????????#對傳感器的坐標系和數據進行配置。這個也會用于代價地圖添加和清除障礙物。例如,你可以用激光雷達傳感器用于在代價地圖添加障礙物,再添加kinect用于導航和清除障礙物。
????????scan: {sensor_frame: laser, data_type: LaserScan, topic: scan, marking: true(是否用激光雷達用作障礙物的標注和清除), clearing: true}

??????? 全局代價地圖的配置 global_costmap_params.yaml

global_costmap:global_frame: map #地圖坐標系robot_base_frame: base_footprint #機器人坐標系# 以此實現坐標變換update_frequency: 1.0 #代價地圖更新頻率publish_frequency: 1.0 #代價地圖的發布頻率transform_tolerance: 1.0 #等待坐標變換發布信息的超時時間static_map: true # 是否使用一個地圖或者地圖服務器來初始化全局代價地圖,如果不使用靜態地圖,這個參數為false.

??????? 本地代價地圖:local_costmap_params.yaml

local_costmap:global_frame: odom #里程計坐標系robot_base_frame: base_footprint #機器人坐標系update_frequency: 10.0 #代價地圖更新頻率publish_frequency: 10.0 #代價地圖的發布頻率transform_tolerance: 0.5 #等待坐標變換發布信息的超時時間static_map: false  #不需要靜態地圖,可以提升導航效果rolling_window: true #是否使用動態窗口,默認為false,在靜態的全局地圖中,地圖不會變化width: 3 # 局部地圖寬度 單位是 mheight: 3 # 局部地圖高度 單位是 mresolution: 0.05 # 局部地圖分辨率 單位是 m,一般與靜態地圖分辨率保持一致

??????? 機器人運動參數:基本的局部規劃器參數配置,這個配置文件設定了機器人的最大和最小速度限制值,也設定了加速度的閾值。

TrajectoryPlannerROS:# Robot Configuration Parametersmax_vel_x: 0.5 # X 方向最大速度min_vel_x: 0.1 # X 方向最小速速max_vel_theta:  1.0 # min_vel_theta: -1.0min_in_place_vel_theta: 1.0acc_lim_x: 1.0 # X 加速限制acc_lim_y: 0.0 # Y 加速限制acc_lim_theta: 0.6 # 角速度加速限制# Goal Tolerance Parameters,目標公差xy_goal_tolerance: 0.10yaw_goal_tolerance: 0.05# Differential-drive robot configuration
# 是否是全向移動機器人holonomic_robot: false# Forward Simulation Parameters,前進模擬參數sim_time: 0.8vx_samples: 18vtheta_samples: 20sim_granularity: 0.05

????????Goal Tolerance Parameters,目標公差
? xy_goal_tolerance: 0.10
? yaw_goal_tolerance: 0.05

??????? 允許和導航目標有一點距離和角度偏差。

????????是否是全向移動機器人:麥克輪設置為true。

????????前進模擬參數:本地路徑規劃和全局路徑規劃有點大像喝酒一樣!!如果差距比較大就要調試這些參數了,如果想讓本地路徑規劃和全局路徑規劃貼合的話可以將sim_time設置的長一點。

3.4.5.7 參數配置小技巧

????????以上配置在實操中,可能會出現機器人在本地路徑規劃時與全局路徑規劃不符而進入膨脹區域出現假死的情況,如何盡量避免這種情形呢?

全局路徑規劃與本地路徑規劃雖然設置的參數是一樣的,但是二者路徑規劃和避障的職能不同,可以采用不同的參數設置策略:

  • 全局代價地圖可以將膨脹半徑和障礙物系數設置的偏大一些;
  • 本地代價地圖可以將膨脹半徑和障礙物系數設置的偏小一些。

這樣,在全局路徑規劃時,規劃的路徑會盡量遠離障礙物,而本地路徑規劃時,機器人即便偏離全局路徑也會和障礙物之間保留更大的自由空間,從而避免了陷入“假死”的情形。

3.5.5 導航與SLAM建圖

????????SLAM建圖中,我們是通過鍵盤控制機器人移動實現建圖的,而后續又介紹了機器人的自主移動實現,那么可不可以將二者結合,實現機器人自主移動的SLAM建圖呢?

上述需求是可行的。雖然可能會有疑問,導航時需要地圖信息,之前導航實現時,是通過 ????????map_server 包的 map_server 節點來發布地圖信息的,如果不先通過SLAM建圖,那么如何發布地圖信息呢?SLAM建圖過程中本身就會時時發布地圖信息,所以無需再使用map_server,SLAM已經發布了話題為 /map 的地圖消息了,且導航需要定位模塊,SLAM本身也是可以實現定位的。

該過程實現比較簡單,步驟如下:

  1. 編寫launch文件,集成SLAM與move_base相關節點;
  2. 執行launch文件并測試。
3.5.5.1?編寫launch文件

????????集成SLAM與move_base相關節點

<launch><!-- 啟動SLAM節點 --><include file="$(find nav_robot)/launch/gmmapping.launch" /><!-- 運行move_base節點 --><include file="$(find nav_robot)/launch/move_base.launch" /><!-- 運行rviz --><node pkg="rviz" type="rviz" name="rviz" />
</launch>

1.首先運行gazebo仿真環境;

2.然后執行launch文件;

3.在rviz中通過2D Nav Goal設置目標點,機器人開始自主移動并建圖了;

4.最后可以使用 map_server 保存地圖。

??????? 設置目標點:

??????? OK~

4 導航信息

在導航功能包集中包含了諸多節點,毋庸置疑的,不同節點之間的通信使用到了消息中間件(數據載體),在上一節的實現中,這些消息已經在rviz中做了可視化處理,比如:地圖、雷達、攝像頭、里程計、路徑規劃...的相關消息在rviz中提供了相關組件,本節主要介紹這些消息的具體格式。

4.1 地圖

4.1.1 nav_msgs/MapMetaData

nav_msgs/MapMetaData

  • 地圖元數據,包括地圖的寬度、高度、分辨率等。

nav_msgs/OccupancyGrid

  • 地圖柵格數據,一般會在rviz中以圖形化的方式顯示。

調用rosmsg info nav_msgs/MapMetaData顯示消息內容如下:origin改變的話地圖相對于RVIZ也會改變

time map_load_time
float32 resolution #地圖分辨率
uint32 width #地圖寬度
uint32 height #地圖高度
geometry_msgs/Pose origin #地圖位姿數據geometry_msgs/Point positionfloat64 xfloat64 yfloat64 zgeometry_msgs/Quaternion orientationfloat64 xfloat64 yfloat64 zfloat64 w

4.1.2 nav_msgs/OccupancyGrid

調用 rosmsg info nav_msgs/OccupancyGrid顯示消息內容如下:

??????? 我們演示一下,讓map_server讀取地圖:

??????? 我們輸出map信息到一個txt文件:rostopic echo /map >> map.txt

??????? 看一下數據:

??????? 大部分數據都是-1表示未探索區域,0是空閑,100是占用。

??????? 但是全局代價地圖有0-100之間的數據,靠近障礙物高,遠離低。

std_msgs/Header headeruint32 seqtime stampstring frame_id
#--- 地圖元數據
nav_msgs/MapMetaData infotime map_load_timefloat32 resolutionuint32 widthuint32 heightgeometry_msgs/Pose origingeometry_msgs/Point positionfloat64 xfloat64 yfloat64 zgeometry_msgs/Quaternion orientationfloat64 xfloat64 yfloat64 zfloat64 w
#--- 地圖內容數據,數組長度 = width * height
int8[] data

4.2 里程計數據

????????里程計相關消息是:nav_msgs/Odometry,調用rosmsg info nav_msgs/Odometry 顯示消息內容如下:

std_msgs/Header headeruint32 seqtime stampstring frame_id
string child_frame_id
geometry_msgs/PoseWithCovariance posegeometry_msgs/Pose pose #里程計位姿geometry_msgs/Point positionfloat64 xfloat64 yfloat64 zgeometry_msgs/Quaternion orientationfloat64 xfloat64 yfloat64 zfloat64 wfloat64[36] covariance
geometry_msgs/TwistWithCovariance twistgeometry_msgs/Twist twist #速度geometry_msgs/Vector3 linearfloat64 xfloat64 yfloat64 zgeometry_msgs/Vector3 angularfloat64 xfloat64 yfloat64 z    # 協方差矩陣float64[36] covariance

4.3 TF

坐標變換相關消息是: tf/tfMessage,調用rosmsg info tf/tfMessage 顯示消息內容如下:

geometry_msgs/TransformStamped[] transforms #包含了多個坐標系相對關系數據的數組std_msgs/Header headeruint32 seqtime stampstring frame_idstring child_frame_idgeometry_msgs/Transform transformgeometry_msgs/Vector3 translationfloat64 xfloat64 yfloat64 zgeometry_msgs/Quaternion rotationfloat64 xfloat64 yfloat64 zfloat64 w

4.4 定位

定位相關消息是:geometry_msgs/PoseArray,調用rosmsg info geometry_msgs/PoseArray顯示消息內容如下:

std_msgs/Header headeruint32 seqtime stampstring frame_id
geometry_msgs/Pose[] poses #預估的點位姿組成的數組geometry_msgs/Point positionfloat64 xfloat64 yfloat64 zgeometry_msgs/Quaternion orientationfloat64 xfloat64 yfloat64 zfloat64 w

4.5 路徑規劃

目標點相關消息是:move_base_msgs/MoveBaseActionGoal,調用rosmsg info move_base_msgs/MoveBaseActionGoal顯示消息內容如下:

std_msgs/Header headeruint32 seqtime stampstring frame_id
actionlib_msgs/GoalID goal_idtime stampstring id
move_base_msgs/MoveBaseGoal goalgeometry_msgs/PoseStamped target_posestd_msgs/Header headeruint32 seqtime stampstring frame_idgeometry_msgs/Pose pose #目標點位姿geometry_msgs/Point positionfloat64 xfloat64 yfloat64 zgeometry_msgs/Quaternion orientationfloat64 xfloat64 yfloat64 zfloat64 w

路徑規劃相關消息是:nav_msgs/Path,調用rosmsg info nav_msgs/Path顯示消息內容如下:

std_msgs/Header headeruint32 seqtime stampstring frame_id
geometry_msgs/PoseStamped[] poses #由一系列點組成的數組std_msgs/Header headeruint32 seqtime stampstring frame_idgeometry_msgs/Pose posegeometry_msgs/Point positionfloat64 xfloat64 yfloat64 zgeometry_msgs/Quaternion orientationfloat64 xfloat64 yfloat64 zfloat64 w

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/209634.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/209634.shtml
英文地址,請注明出處:http://en.pswp.cn/news/209634.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

JavaScript基礎知識整理(最全知識點, 精簡版,0基礎版)

文章目錄 一、輸入和輸出內容 1.1 輸出 1.1.1 在瀏覽器的控制臺輸出打印 1.1.2 直接在瀏覽器的頁面上輸出內容 1.1.3 頁面彈出警告對話框 1.2 輸入 二、變量 2.1 變量是什么 2.2 變量的聲明和賦值 2.3 變量的命名規范和規范 三、變量擴展&#xff08;數組&#xff09; 3.1 數組…

Cypress:前端自動化測試的終極利器

引言&#xff1a; 在現代軟件開發中&#xff0c;前端自動化測試已經成為了一個不可或缺的環節。它不僅可以提高開發效率&#xff0c;減少手動測試的工作量&#xff0c;還可以保證軟件的穩定性和質量。而在眾多的前端自動化測試工具中&#xff0c;Cypress無疑是其中的佼佼者。本…

openGauss學習筆記-144 openGauss 數據庫運維-例行維護-慢sql診斷

文章目錄 openGauss學習筆記-144 openGauss 數據庫運維-例行維護-慢sql診斷144.1 背景信息144.2 前提條件 openGauss學習筆記-144 openGauss 數據庫運維-例行維護-慢sql診斷 144.1 背景信息 在SQL語句執行性能不符合預期時&#xff0c;可以查看SQL語句執行信息&#xff0c;便…

文章解讀與仿真程序復現思路——中國電機工程學報EI\CSCD\北大核心《考慮垃圾處理與調峰需求的可持續化城市多能源系統規劃》

這個標題涵蓋了城市多能源系統規劃中的兩個重要方面&#xff1a;垃圾處理和調峰需求&#xff0c;并強調了規劃的可持續性。 考慮垃圾處理&#xff1a; 含義&#xff1a; 垃圾處理指的是城市廢棄物的管理和處置。這可能涉及到廢物分類、回收利用、焚燒或填埋等方法。重要性&…

GIS入門,Leaflet介紹,Leaflet可以做什么,網頁中如何使用Leaflet地圖,vue中如何使用Leaflet地圖

VueLeafLet教程推薦&#xff1a;《VueLeaflet入門》 Leaflet介紹 Leaflet是一個開源的JavaScript庫&#xff0c;用于創建交互式的地圖和地圖應用。Leaflet框架具有輕量級、靈活性強、易于使用和擴展等特點&#xff0c;支持各種地圖服務商&#xff08;如OpenStreetMap、Google…

前端知識筆記(三十八)———HTTPS:保護網絡通信安全的關鍵

當談到網絡通信和數據傳輸時&#xff0c;安全性是一個至關重要的問題。在互聯網上&#xff0c;有許多敏感信息需要通過網絡進行傳輸&#xff0c;例如個人身份信息、銀行賬戶信息和商業機密等。為了保護這些信息不被未經授權的人訪問和篡改&#xff0c;HTTPS&#xff08;超文本傳…

【開源】基于Vue+SpringBoot的河南軟件客服系統

文末獲取源碼&#xff0c;項目編號&#xff1a; S 067 。 \color{red}{文末獲取源碼&#xff0c;項目編號&#xff1a;S067。} 文末獲取源碼&#xff0c;項目編號&#xff1a;S067。 目錄 一、摘要1.1 項目介紹1.2 項目錄屏 二、功能模塊2.1 系統管理人員2.2 業務操作人員 三、…

搞懂內存函數

引言 本文介紹memcpy的使用和模擬實現、memmove的使用和模擬實現、memcmp使用、memset使用 ? 豬巴戒&#xff1a;個人主頁? 所屬專欄&#xff1a;《C語言進階》 &#x1f388;跟著豬巴戒&#xff0c;一起學習C語言&#x1f388; 目錄 引言 memcpy memcpy的使用 memcpy的…

JS加密/解密之HOOK實戰2

上一篇文章介紹了HOOK常規的應用場景&#xff0c;這篇我們講一下HOOK其他原生函數。又是一個新的其他思路 很多時候&#xff0c;當我們想要某些網站的請求參數的時候&#xff0c;因為某些加密導致了獲取起來很復雜。 這時候hook就十分方便了 源代碼 var _JSON_Parse JSON.…

scp 指令詳細介紹

目錄 1. 基本語法 2. 例子 從本地到遠程 從遠程到本地 從遠程到遠程 使用端口和指定私鑰 遞歸復制目錄 3. 注意事項 如何拷貝文件的軟鏈接 SCP&#xff08;Secure Copy Protocol&#xff09;是一種用于在計算機之間安全地傳輸文件的協議。它通過加密的方式在網絡上安全…

Vue:Vue的開發者工具不顯示Vue實例中的data數據

一、情況描述 代碼&#xff1a; 頁面&#xff1a; 可以看到&#xff0c;input獲取到了data數據&#xff0c;但是&#xff0c;vue-devtool沒有獲取到data數據 二、解決辦法 解決辦法1&#xff1a; data.name的值不能全是中文&#xff0c;比如改成aa尚硅谷 解決辦法2&…

C語言 編程題

C語言學習&#xff01; 1.小明上課需要走n階臺階&#xff0c;他每次可以選擇走一階或者走兩階&#xff0c;他一共有多少種走法&#xff1f; 輸入描述&#xff1a;輸入包含一個整數n&#xff08;1 ≤ n ≤30&#xff09; 輸出描述&#xff1a;輸出一個整數&#xff0c;即小明可…

LeetCode 1457. 二叉樹中的偽回文路徑||位運算 DFS

1457. 二叉樹中的偽回文路徑 給你一棵二叉樹&#xff0c;每個節點的值為 1 到 9 。我們稱二叉樹中的一條路徑是 「偽回文」的&#xff0c;當它滿足&#xff1a;路徑經過的所有節點值的排列中&#xff0c;存在一個回文序列。 請你返回從根到葉子節點的所有路徑中 偽回文 路徑的…

Golang優雅實現按比例切分流量

我們在進行灰度發布時&#xff0c;往往需要轉發一部分流量到新上線的服務上&#xff0c;進行小規模的驗證&#xff0c;隨著功能的不斷完善&#xff0c;我們也會逐漸增加轉發的流量&#xff0c;這就需要按比例去切分流量&#xff0c;那么如何實現流量切分呢&#xff1f; 我們很容…

力扣(LeetCode)-1. 兩數之和

給定一個整數數組 nums 和一個整數目標值 target&#xff0c;請你在該數組中找出 和為目標值 target 的那 兩個 整數&#xff0c;并返回它們的數組下標。 你可以假設每種輸入只會對應一個答案。但是&#xff0c;數組中同一個元素在答案里不能重復出現。 你可以按任意順序返回…

【交流】PHP生成唯一邀請碼

目錄 前言&#xff1a; 1.隨機生成&#xff0c;核對user表是否已存在 代碼&#xff1a; 解析&#xff1a; 缺點&#xff1a; 2.建表建庫&#xff0c;每次從表中隨機抽取一條&#xff0c;用完時擴充 表結構 表視圖 代碼 解析 缺點 結論&#xff1a; 前言&#xff1a; …

LinuxBasicsForHackers筆記 -- 壓縮和歸檔

壓縮分為有損或無損。有損壓縮對于減小文件大小非常有效&#xff0c;但會丟失信息的完整性。換句話說&#xff0c;壓縮后的文件與原始文件并不完全相同。 這種類型的壓縮非常適合圖形、視頻和音頻文件&#xff0c;文件中的微小差異幾乎不會被注意到。 本章重點介紹這種無損壓縮…

解讀Stable Video Diffusion:詳細解讀視頻生成任務中的數據清理技術

Diffusion Models視頻生成-博客匯總 前言:Stable Video Diffusion已經開源一周多了,技術報告《Stable Video Diffusion: Scaling Latent Video Diffusion Models to Large Datasets》對數據清洗的部分描述非常詳細,雖然沒有開源源代碼,但是博主正在嘗試復現其中的操作。這篇…

醫學影像PACS信息化數字平臺源碼

PACS系統對醫院影像科意義重大&#xff0c;將業務量巨大的影像檢驗流程依托于信息化技術&#xff0c;對于進行信息化建設的醫院而言&#xff0c;是十分必要的。 PACS系統源碼&#xff0c;集成三維影像后處理功能&#xff0c;包括三維多平面重建、三維容積重建、三維表面重建、三…

包裝類, 泛型---java

目錄 一. 包裝類 1.1 基本數據類型和對應的包裝類 1.2 裝箱和拆箱 二. 泛型 2.1什么是泛型 2.2泛型的引入 2.3 泛型類語法 2.4 泛型類的使用 2.5 裸類型(Raw Type)(了解) 2.6 泛型是如何編譯的 2.7 泛型的上界 2.8 泛型方法 一. 包裝類 在 Java 中&#xff0c;由于基本…