# 10.4 map_server & amcl
在某些固定場景下,我們已經知道了地圖(無論通過SLAM還是測量),這樣機器人每次啟動最好就能直接加載已知地圖,而是每次開機都重建。在這種情況下,就需要有一個節點來發布`/map`,提供場景信息了。
## 10.3.1 map_server
map_server是一個和地圖相關的功能包,它可以將已知地圖發布出來,供導航和其他功能使用,也可以保存SLAM建立的地圖。
要讓map_server發布`/map`,需要輸入給它兩個文件:
* 地圖文件,通常為pgm格式;
* 地圖的描述文件,通常為yaml格式
例如在`ROS-Academy-for-Beginners`里,我們提供了軟件博物館的地圖文件,見`slam_sim_demo/maps`下:
Software_Museum.pgm

Software_Museum.yaml
```xml
image: Software_Museum.pgm #指定地圖文件
resolution: 0.050000 #地圖的分辨率 單位為m/pixel
origin: [-25.000000, -25.000000, 0.000000] #地圖的原點
negate: 0 #0代表 白色為空閑 黑色為占據
occupied_thresh: 0.65 #當占據的概率大于0.65認為被占據
free_thresh: 0.196 #當占據的概率小于0.196認為無障礙
```
其中占據的概率 occ = (255-color_avg)/255.0, color_avg為RGB三個通道的平均值。
有了以上兩個文件,你可以通過指令來加載這張地圖,map_server相關命令如下:
| map_server命令 | 作用 |
| :------: | :------: |
| `rosrun map_server map_server Software_Museum.yaml` | 加載自定義的地圖 |
| `rosrun map_server map_saver -f mymap` | 保存當前地圖為mymap.pgn和mymap.yaml |
當我運行`rosrun map_server map_server ***.yaml`時,會有以下的通信接口:
### Topic
通常我們是在launch文件中加載map_server,發布地圖。而map_server發布的消息包括:
* /map_metadata: 發布地圖的描述信息
* /map: 發布鎖存的地圖消息
### Service
amcl的服務只有一個:
* static_map: 用于請求和響應當前的靜態地圖。
### Param
amcl有一個參數需要設置,就是發布地圖的frame。
* ~frame_id: string類型,默認為map。 綁定發布的地圖與tf中的哪個frame,通常就是map。
有兩個概念不要搞混淆,map既是一個topic,也是一個frame,前者是topic通信方式中的一個話題,信息交互的頻道,后者是tf中的一個坐標系,map_frame需要和其他的frame相連通。
## 10.3.2 amcl
Adaptive Mentcarto Localization(AMCL),蒙特卡洛自適應定位是一種很常用的定位算法,它通過比較檢測到的障礙物和已知地圖來進行定位。
AMCL上的通信架構如上圖所示,與之前SLAM的框架很像,最主要的區別是`/map`作為了輸入,而不是輸出,因為AMCL算法只負責定位,而不管建圖。

同時還有一點需要注意,AMCl定位會對里程計誤差進行修正,修正的方法是把里程計誤差加到`map_frame`和`odom_frame`之間,而`odom_frame`和`base_frame`之間是里程計的測量值,這個測量值并不會被修正。這一工程實現與之前gmapping、karto的做法是相同的。

### 演示截圖
amcl算法演示效果圖如下:

- 前言
- 第一章 ROS簡介
- 機器人時代的到來
- ROS發展歷程
- 什么是ROS
- 安裝ROS
- 安裝ROS-Academy-for-Beginners教學包
- 二進制與源碼包
- 安裝RoboWare Studio
- 單元測試一
- 第二章 ROS文件系統
- Catkin編譯系統
- Catkin工作空間
- Package軟件包
- CMakeLists.txt
- package.xml
- Metapacakge軟件元包
- 其他常見文件類型
- 單元測試二
- 第三章 ROS通信架構(一)
- Node & Master
- Launch文件
- Topic
- Msg
- 常見msg類型
- 單元測試三
- 第四章 ROS通信架構(二)
- Service
- Srv
- Parameter server
- Action
- 常見srv類型
- 常見action類型
- 單元測試四
- 第五章 常用工具
- Gazebo
- RViz
- Rqt
- Rosbag
- Rosbridge
- moveit!
- 單元測試五
- 第六章 roscpp
- Client Library與roscpp
- 節點初始、關閉與NodeHandle
- Topic in roscpp
- Service in roscpp
- Param in roscpp
- 時鐘
- 日志與異常
- 第七章 rospy
- Rospy與主要接口
- Topic in rospy
- Service in rospy
- Param與Time
- 第八章 TF與URDF
- 認識TF
- TF消息
- tf in c++
- tf in python
- 統一機器人描述格式
- 附錄:TF數學基礎
- 三維空間剛體運動---旋轉矩陣
- 三維空間剛體運動---歐拉角
- 三維空間剛體運動---四元數
- 第九章 SLAM
- 地圖
- Gmapping
- Karto
- Hector
- 第十章 Navigation
- Navigation Stack
- move_base
- costmap
- Map_server & Amcl
- 附錄:Navigation工具包說明
- amcl
- local_base_planner
- carrot_planner
- clear_costmap_recovery
- costmap_2d
- dwa_local_planner
- fake_localization
- global_planner
- map_server
- move_base_msg
- move_base
- move_slow_and_clear
- navfn
- nav_core
- robot_pose_ekf
- rotate_recovery