编写本书的原因

        本书整理总结了2020年底到2021年底关于上海应用技术大学机器人爱好者协会的所有机器人技术成果,考虑后续的传承,故编写本书。希望后人的经验与成果也记录在本书中。本书将能够永远地保持更新下去,使传承不断,社团发展能够越来越好。

Rust

        由于本书基于由Rust编写的mdbook静态页面生成框架生成而成,故需要安装Rust编译环境。

https://rustup.rs/

mdbook

        mdbook的安装教程

Installation - mdBook Documentation

Git工具

        直接sudo apt install git

Marktext

        所见即所得的markdown文档编辑器,以前推荐Typora,后来Typora收费了,推荐大家使用开源的markdown编辑器

VSCode

        虽然为本书贡献基本不需要写代码,但是通过vscode管理mdbook的配置文件,作为可视化的git工具还是很好用的。

这里总结了一系列开发须知与经验

运行环境

操作系统: Ubuntu20.04

ROS版本: 使用与 Ubuntu 20.04 配套的 ROS 的 Noetic 版本。

        ROS Noetic与之前的版本最大的一个不同就是其Python环境的变更,在ROS melodic,kinetic 及更早的版本,使用的是 Python2.7 的运行环境,而 Noetic 原生完美支持 Python3.8 的运行环境,给我们的机器人开发带来了非常先进的 Python 开发体验。而 C++ 层面的变更到不大,基本可以兼容以前的代码。

考古: 曾经19年之前,本社团机器人运行环境为更古老的 Ubuntu14.04 下的 ROS Indigo,远古代码的备份已存放至github。https://github.com/SIT-Robot/achieved2019。后来,本人使用melodic环境重写了机器人的ros代码,经过数次迭代更新,最终迁移到最新的noetic环境,代码即如今现有的代码。

开发工具

VSCode

        推荐开发工具VSCode,安装ROS插件后即可愉快地开发。插件市场搜索相应插件,还可补全launch,urdf,xacro等ros下基于xml的描述配置的语言。可以直接支持打开整个工作空间,也可以只打开单个功能包,智能补全的配置大多装完插件后就自动完成了。

CLion

        CLion在开发真正的C++项目时是一个很好的选择,其智能补全与各种工程化的工具都相当好用,但是对ros而言,经常需要在多个功能包下跳转,以及需要同时编写C++和Python代码。 故推荐还是对纯C++功能包使用CLion,对混合语言功能包或多个功能包需要来回跳转编写及联合调试时使用vscode。

Qt

        Qt是一套能够编写GUI程序的框架,如果需要机器人的操作体验更好,可借助Qt实现一套图形界面的机器人控制台。我们经常使用一些rqt开头的ros工具命令,这些工具基本都是通过Qt编写的,包括Rviz及其插件也是需要通过Qt编写,有能力的同学可以编写rviz插件就可以定制出一个方便好用的图形化的机器人控制台界面。Qt底层虽然是C++编写,但其上层可不限定语言,如Python中你可以通过PyQt5编写图形程序。本人由于时间原因,未大量实现机器人的Qt图形程序,基本都是通过终端命令调用。

学习资源推荐

文章资料

【奥特学园--赵虚左】《ROS理论与实践》零基础教程

        这篇文档与下面的奥特学院的ROS机器人入门教程是配套的,文档很详细,图也非常多,相当适合入门,其中也包含了实体机器人的部分。

【古月居】《ROS 机器人开发实践》

这是一个实体书籍,大家可以去学校图书馆免费借阅到。当初2020年11月的比赛全靠下面的ROS入门21讲+啃这本书完成的。书中使用的是Ubuntu20.04 ROS kinetic版本,目前已知的是其中的语音识别部分,smach状态机无法在 noetic 中使用,因为两者都需要依赖Python2.7的代码和库。

【古月居】ROS入门21讲 视频补充资料

视频学习

【奥特学园--赵虚左】ROS机器人入门课程《ROS理论与实践》零基础教程(ROS基础与仿真环境下的导航实现)

        这个视频是本人在2021年初发现的关于ROS的视频学习资料,可以说是相当完美的学习资源。总共361集,可以说是相当详细的一部视频教程了。这个教程只要你肯花时间慢慢去学,一定能够学会ROS机器人开发入门。

【奥特学园--赵虚左】《ROS理论与实践》第8、9章--ROS机器人操作系统(实体机器人的软硬件开发与导航实现)

        这个视频是针对上一个361集视频资源的补充,原视频教程只包含了ROS的理论部分和仿真环境下的实践部分。本视频共91集,包含了上一个视频残缺的实体机器人的开发。其中涵盖了Arduino单片机开发,PID控制理论与实践,电机控制,串口协议开发,ROS实体机器人导航等知识点。

【古月居】ROS入门21讲

        这个视频是本人2020年底第一次学习机器人时看的第一个入门视频,当时在国内ROS的资料很少,尤其是视频教程。这个教程适合快速入门,快速了解上手机器人开发,但是讲的不够深入,不够细节,也不太适合零基础的小白。

经验之谈

调试

        ROS的 C++ 功能包本质就是一个 cmake 工程,可以直接通过 CLion/VSCode 这样的支持 cmake 工程的 ide 打开,这在调试 c++ 功能包时是及其有用的。

        ROS的 Python 功能包与一般的 Python 项目无异,可以直接通过 Pycharm/VSCode 打开,不过如果你电脑上安装有 Anaconda 一类的Python环境,一定要注意切换使用 System Python 即可索引到相关依赖,开启智能补全。

        当然 Anaconda 这样的工具也是很有用的,但是不能直接在 conda 的虚拟环境中使用 ros 的功能包,需要单独配置。

其他

        尽量熟悉 Git工具的使用,能够记录你代码的变动,也可以方便地多人协同,更能使我们的代码能够保留传承下去。

        善于利用 Github 上一些诸如 Github Action(CI工具) 这样提高效率的工具。

推荐小工具

这里推荐一些其他提高开发效率的工具

  • fish
  • zsh
  • ...未完待续

虚拟机安装

如果你仍在学习过程中,建议使用虚拟机的方式安装,虚拟机方式的安装与实体机安装大同小异 建议参考如下文章进行安装 http://www.autolabor.com.cn/book/ROSTutorials/chapter1/12-roskai-fa-gong-ju-an-zhuang.html

实体机安装

一个真正的机器人运行时需要在实体机安装。 可以参考如下文字 https://blog.csdn.net/m0_60190682/article/details/118723468 也可以使用搜索引擎搜索"u盘安装 ubuntu20.04"

安装建议

安装界面大概如下图所示,

  1. 建议安装之前先断网,否则安装过程可能会自动更新,而未换源之前更新将直接连接国外服务器,会导致安装进度巨慢无比。建议断网安装结束后,进系统后手动换源后手动更新。

  2. 建议安装使用英文界面,不过Linux下中文不会像Windows那样轻易出现乱码情况(统一UTF-8编码),但是在纯终端界面下将会出现中文方块的情况。

虚拟机增强工具

PS: 该内容仅虚拟机安装的用户需要关注。

当我们安装完虚拟机后,通过安装虚拟机增强工具可以使得虚拟机与物理机进行方便地交互。

如果我们使用的是VMware虚拟机,那么我们可进行如下操作,

然后我们发现出现了一个光盘设备,在此处打开终端

在 Linux 虚拟机中手动安装 VMware Tools

当提示上述信息时,增强工具便安装成功,然后可以输入reboot命令重启电脑。

重启之后你会发现虚拟机的分辨率将会随着虚拟机窗口而进行缩放,剪切板也可相互共享,大大提高的虚拟机的便捷性。

系统更新

断网安装完系统之后,就可以联网了。

由于现在Ubuntu 22.04已发布,可能会弹窗提示升级Ubuntu 22.04,请不要升级,因为后面我们需要安装的ROS1 的noetic发行版是需要绑定Ubuntu 20.04的发行版的。

需要先更换国内源,可以参考以下清华源或科大源的文档。

ubuntu | 镜像站使用帮助 | 清华大学开源软件镜像站 | Tsinghua Open Source Mirror

Ubuntu 源使用帮助 — USTC Mirror Help 文档

更换国内源后便可通过以下命令更新apt源

sudo apt update

再运行以下命令执行系统软件包更新

sudo apt upgrade -y

更新完毕

中文输入法

中文输入法很有用,不管是写代码注释还是上网搜索均需要使用到中午输入。

如果你安装的是中文ubuntu,则已经会自带一个中文输入法;如果你安装的是英文ubuntu,则不会自带中文输入法。

不过,系统自带的中文输入法个人感觉较为难用。在此推荐安装使用搜狗输入法。

搜狗输入法linux-首页

官网已有详细的安装说明,再次不展开赘述。(需要严格执行官方帮助中的每一条命令,如果输入法还是无法正常使用,请再次重复执行)

将搜狗输入法加入输入法列表中。

此时已经能够输入中文了

参考文章

ROS的安装参考如下文章,

ROS官方wiki

noetic/Installation/Ubuntu - ROS Wiki

奥特学园

1.2.4 安装 ROS · Autolabor-ROS机器人入门课程《ROS理论与实践》零基础教程

ROS安装

配置完ROS源之后,使用

sudo apt install ros-noetic-desktop-full

即可开始漫长的安装过程。

PS: Linux 绝大多数命令行输入都可以按键盘上的Tab键来自动补全,擅于使用补全有利于提高工作效率。

如下图将开始漫长的ROS安装过程(此时你可以把电脑放一边去吃个饭什么的),

下图便是下载完毕开始安装的步骤

ROS配置

最终ROS将会被安装到/opt/ros/noetic目录下,此时还无法运行ros相关命令,我们可以在ros安装目录下发现setup.bash文件,该文件为ros环境的初始化文件。

使用命令

source /opt/ros/noetic/setup.bash

即可完成当前终端下的ros环境变量的配置。

此时运行roscore便可以启动ros master节点

为了方便使用不用每次启动终端都需要source,可将环境变量配置到.bashrc文件中

ROS测试

开三个终端,每个终端分别运行如下命令

roscore

rosrun turtlesim turtlesim_node

rosrun turtlesim turtle_teleop_key

即可在第三个终端窗口下通过方向键操作第二个终端打开的小海龟窗口中的海龟了。

参考文献

1.4 ROS集成开发环境搭建 · Autolabor-ROS机器人入门课程《ROS理论与实践》零基础教程

根据文章中的指示去安装Terminator与VSCode

VSCode插件安装

直接在插件市场搜索ros,安装排名第一的插件即可

此时可以看到安装完ROS插件后已经会自动帮我们安装C/C++和Python相关的插件。

服务机器人上的激光雷达的ROS驱动程序可直接通过apt进行安装。

sudo apt install ros-noetic-urg-node

然后使用命令

rosrun urg_node urg_node

便可以启动激光雷达节点

通过rostopic list即可查看所有的话题列表中包含了激光雷达节点发布的话题/scan了

使用rostopic echo /scan即可查看/scan话题下发布的数据流。

也可在rviz的可视化工具中,添加LaserScan可视化组件

设置该可视化组件绑定的话题为/scan,然后便可在右侧三维空间中显示当前的激光雷达点云信息。(可能还需要设置全局坐标系为激光雷达的坐标系,默认为地图坐标系,但是地图此时还未加载)

ROS工作目录

如果还没有创建自己的ROS工作目录,请先创建一个自己的ROS工作目录。

请先完成如下章节实验

1.3 ROS快速体验 · Autolabor-ROS机器人入门课程《ROS理论与实践》零基础教程

下载代码

进入工作目录的src目录下,

从github上clone仓库(这一步之前请先安装git, sudo apt install git

git clone https://github.com/SIT-Robot/sit-robot-hardware.git

注意从github上clone代码可能需要配置代理服务器。

如果虚拟机中,已安装clash环境,则可直接使用以下命令配置git代理

git config --global http.proxy http://127.0.0.1:7890
git config --global https.proxy http://127.0.0.1:7890

然后代码便下载成功

然后返回catkin_ws即可运行catkin_make编译硬件层代码。

如果我们没有安装ros的串口包,可能会报错如下

此时只需运行sudo apt install ros-noetic-serial即可完成ros串口驱动包的安装。

再次执行编译,即可完成硬件层代码的编译

此时连接下位机串口,运行命令

rosrun sit_protocol protocol_forwarder_node即可运行上下位机之间通信的节点。

通过ls命令可以查看机器人硬件层的功能包如下,

其中,

  1. sit_protocol便为上下位机通信包,主要负责数据包解析,发送,crc校验等工作

  2. sit_protocol_msgs为上下位机通信的消息文件,主要提供给其他硬件节点用于收发消息

  3. sit_chassis为底盘运动节点,高层模块可向该节点发送vx,vy方向的线速度与vw方向的角速度,该节点用于将速度按照具体的机器人物理结构分解为各个轮子的角速度并转换为相应的控制指令发送至sit_protocol节点,sit_protocol节点再进一步通过串口消息发送到下位机。同时,上位机还可发送实际轮速信息的询问消息,下位机将需要反馈实时的轮速。

  4. sit_chassis_imu为底盘imu节点,用于接收imu角度消息,其不断向sit_protocol节点发送询问imu的消息,sit_protocol节点也在不断反馈imu消息给sit_chassis_imu,并由sit_chassis_imu对外广播imu消息。

  5. sit_odom为里程计节点,其接受sit_chassis反馈回的实时速度信息与

  6. sit_chassis_imu反馈回的角度信息,通过积分后得到里程计信息。

下载代码

git clone https://github.com/SIT-Robot/sit-robot-tools.git

编译代码

catkin_make

启动机器人键盘控制器

运行命令

rosrun sit_teleop teleop.py

即可启动控制器如下,

建议

还是建议在完成了下面文章和视频的学习之后再进行本章的学习,如果能完整的学习完该视频与文档,那么本篇文章可能很快就能完成甚至发现文章中的疏漏。

第 7 章 机器人导航(仿真) · Autolabor-ROS机器人入门课程《ROS理论与实践》零基础教程

还有配套视频

https://www.bilibili.com/video/BV1Ci4y1L7ZZ

P229-P328章节

本人当时学习完这些章节且搭建出自己的机器人仅需一天时间即可完成

克隆代码

git clone https://github.com/SIT-Robot/sit-service-robot.git
git clone https://github.com/SIT-Robot/sit-basketball-robot.git

编译代码

catkin_make

有可能报错如下,

sudo apt install ros-noetic-navigation
sudo apt install ros-noetic-gmapping

启动环境

此时启动机器人仿真环境

可能报错如下,我们需要安装urdf的python插件

sudo apt install ros-noetic-urdfdom-py

再次启动仍可能报错如下,我们需要安装realsense2_description包

sudo apt install ros-noetic-realsense2-description

此时已经成功启动机器人仿真环境,但是可能效果如下,显示异常

使用roslaunch sit_service_description service_robot_viz.launch打开rviz查看

发现似乎是tf全部失效。

根据以下文章,查看tf树

5.1.5 坐标系关系查看 · Autolabor-ROS机器人入门课程《ROS理论与实践》零基础教程

发现目前仅存在上述tf变换。

重开几次,有一定几率建立完整tf

此时继续启动service_robot_viz.launch,可发现机器人已经成功加载,并且显示出模型,雷达线等。

如果电脑性能较好,还可尝试订阅深度相机发布的点云消息,

启动键盘控制器

启动键盘控制器

rosrun sit_teleop teleop.py

即可使用键盘控制rviz中的机器人了。

PS: Gazebo中的场景贴图还是无法正常加载,我也不清楚为何,或许是虚拟机的问题。但是rviz中已经实现了机器人的可视化,并显示周围的环境感知。

SLAM建图

roslaunch sit_nav gmapping_slam.launch 即可启动slam建图,使用键盘控制机器人运动,即可逐步建立环境地图。

上海应用技术大学机器人爱好者协会机器人基本硬件层代码详解

代码仓库

https://github.com/SIT-Robot/sit-robot-hardware

概要

我们在通过ros控制实体机器人时,免不了要跟真实的硬件打交道,这里的代码存放了与下位机通信的协议,对下位机的imu封装,对下位机底盘的运动学封装,对下位机里程计的封装。

这些功能包的依赖关系如下,

graph TD;
    A[sit_protocol_msgs]
    B[sit_protocol]
    C[sit_chassis]
    D[sit_chassis_imu]
    E[sit_odom]

    A-->B
    B-->C
    B-->D
    C-->E
    D-->E

sit_protocol_msgs

该功能包为一切与硬件通信的协议消息基石

规定机器人下位机与上位机之间任何消息传递均以数据帧为单位,对于任何ros层封装的硬件驱动,必须遵循此协议消息包进行封装。

消息定义

CmdDataFrame.msg

该消息规定了一帧消息协议

# 机器人的串口数据帧

# 地址域 8位的单字节地址(禁止是0号地址)
uint8 address

# 命令域 8位的单字节指令
uint8 cmd

# 数据域 可变长的字节数组
uint8[] data

每个设备自身都有对应的一个8位的地址,存于address字段。

如果一个address确定,那么目标通讯设备将确定。

下位机设备收到消息后,读取8位的cmd字段确定需要执行什么操作,通过解析data数组中的内容,执行相应的操作。

服务定义

RequestDataFrame.srv

# 发送请求数据帧
sit_protocol_msgs/CmdDataFrame request

# 等待响应的数据帧指令值
uint8 waitCmd

# 超时时间(单位ms) 默认值100ms
uint16 timeout = 100

---

# 接收响应数据帧
sit_protocol_msgs/CmdDataFrame response

上位机与下位机的通讯为同步的请求响应模型,上位机发送一个request数据帧,下位机收到后必须返回一个response数据帧,其中waitCmd为上位机期望的response中的cmd字段,若上位机在timeout时间内未收到response字段或response中的cmd与waitCmd不匹配,则视为请求超时,本次请求执行失败。

sit_protocol

本功能包为与硬件通信的网关,所有的CmdDataFrame数据帧均传递到本功能包中

代码

CmdDataFrame结构体

include/sit_protocol/CmdDataFrame.h

该头文件定义了与ros解耦的数据帧定义

其成员函数generateBytes实现了该帧数据帧消息的二进制序列化操作,主要添加包头包尾,添加地址,命令,数据长度,数据域,校验和等字节信息。

toByteString,toString这俩函数主要是调试时输出数据帧信息的调试专用函数。

这里节选generateBytes函数实现,可以看出其实现还是比较简单的

    std::vector<uint8_t> generateBytes(){
        std::vector<uint8_t> bytes;
        bytes.push_back(0x55);
        bytes.push_back(0xAA);
        bytes.push_back(address);
        bytes.push_back(cmd);
        bytes.push_back(data.size());
        for(uint8_t i : data){
            bytes.push_back(i);
        }

//        uint8_t sum = std::accumulate(bytes.begin()+2,bytes.end(),0);
        uint8_t sum = crc8(bytes.begin()+2,bytes.end());
        bytes.push_back(sum);
        bytes.push_back(0xBB);
        bytes.push_back(0xCC);
        return bytes;
    }

DataFrameParser类

include/sit_protocol/DataFrameParser.h

该头文件定义了数据帧解析类,同样与ros解耦

可以想象该类为一台机器,向其中扔一个个字节,当能够组合出一组合法的二进制串为DataFrame时,你便可通过popFrame拿到其加工好的DataFrame

该类的职责便是反序列化出一个个DataFrame对象,它有两个public的成员函数。

  • pushByte(uint8_t byte)

    • 放入一个字节
  • pushBytes(uint8_t *byte, int len)

    • 放入一堆字节
  • CmdDataFrame popFrame()

    • 取出一个数据帧
  • bool empty()

    • 是否为空,如果不为空,则代表可以popFrame取出一个数据帧

SerialCommunicator类

include/sit_protocol/SerialCommunicator.h

该文件实现了基于串口面向字节流数据传输协议的通讯工具,其基于DataFrameParser类实现了在不可靠的串口通信下提供了基于帧数据传输,带有了错误校验的相对可靠的数据传输服务。

该类的构造函数需要传入一个Serial对象(本类依赖了serial串口通信库),然后其便提供了异步通信的如下函数

  • void sendFrame(CmdDataFrame& frame)

    • 发送一个数据帧
  • bool receivable()

    • 是否存在可接收的数据帧
  • CmdDataFrame receive()

    • 接收一帧数据

还提供了更方便的同步通信函数

  • bool requestFrame(CmdDataFrame req_frame, CmdDataFrame& resp_frame, uint16_t timeout = 40)

    • 该函数需传入请求数据帧信息,用于响应的接收数据帧(其需要接收数据,故使用引用传递),最大超时时间,同步请求必须设置超时时间,否则程序通信失败时本函数将卡死

    • 该函数返回值表示是否接收到响应帧信息,只有接收到响应,本次请求才视为成功请求。

ProtocolNode类

include/sit_protocol/ProtocolNode.h

该类将SerialCommunicator类中的同步通信函数通过ros的服务通信机制封装了一层。

本类需要传入一个device_pool,这是一个map,其中key为uint8_t的整数,代表了设备地址,所有ros服务接收到的消息均通过其request数据帧中的地址查询device_pool分发到不同的设备。

utils.h

include/sit_protocol/utils.h

该头文件定义了一些常用工具,如crc8校验

入口文件

sit_protocol/src/sit_protocol_serial.cpp 最后,该文件为主入口文件,main函数便定义在此,它完成了根据特定协议进行下位机自动发现,串口初始化,启动ProtocolNode类等操作。

AChassis接口

sit_chassis/include/sit_chassis/AChassis.h

该文件定义了二维平面机器人的抽象接口,该接口存在两个待实现的纯虚函数。

    /**
     * @brief 对底盘设置一个期望速度
     * 
     * @param vx x轴方向的期望速度
     * @param vy y轴方向上的期望速度
     * @param vw 环绕z轴方向的转速
     */
    virtual void setSpeed(double vx,double vy,double vw) = 0;

    /**
     * @brief 获取底盘当前时刻的速度
     * 
     * @param vx x轴方向的实际速度
     * @param vy y轴方向上的实际速度
     * @param vw 环绕z轴方向的转速
     */
    virtual void getSpeed(double& vx,double& vy,double& vw) = 0;

AThreeChassis抽象类

sit_chassis/include/sit_chassis/AThreeChassis.h

该类定义了一个抽象的三轮全向底盘的运动学实现的抽象类,它提供了两个纯虚函数,

    /**
     * @brief 设置车轮的期望线速度,具体通过怎样的方式下发速度指令,继续由子类实现,
     * 车轮线速度单位为 m/s
     * 
     * @param v1 1号车轮的线速度
     * @param v2 2号车轮的线速度
     * @param v3 3号车轮的线速度
     */
    virtual void setWheelSpeed(double v1, double v2, double v3) = 0;

    /**
     * @brief 获取当前时刻车轮速度
     * 
     * @param v1 1号车轮的线速度
     * @param v2 2号车轮的线速度
     * @param v3 3号车轮的线速度
     */
    virtual void getWheelSpeed(double& v1,double& v2,double& v3) = 0;

在本类中,我们假设调用这些纯虚函数即可实现设置轮速与获取轮速。

根据运动学公式,即可实现如下底盘的速度获取与设置的成员函数。

    void setSpeed(double vx, double vy, double vw) override
    {
        const double M_PI_6 = M_PI / 6;
        //ROS_INFO("Speed:[%f, %f, %f]", vx, vy, vw);
        //需要将速度进行分解到三个轮子上
        double vb = -vy + vw * L;
        double vl = -vx * cos(M_PI_6) + vy * sin(M_PI_6) + vw * L;
        double vr = vx * cos(M_PI_6) + vy * sin(M_PI_6) + vw * L;

        //设置轮速
        setWheelSpeed(vb, vr, vl);
    }

    void getSpeed(double& vx,double& vy,double& vw) override
    {
        //需要获取三个轮子的轮速,合成出轮子速度

        //获取三个轮子速度
        double v1,v2,v3;
        getWheelSpeed(v1,v2,v3);

        //速度合成
        vx = (v2 - v3) * (sqrt(3) / 3);
        vy = (-2 * v1+ v2+ v3) / 3;
        vw = (v1 + v2 + v3) / (3 * L);
    }

ThreeChassis实现类

sit_chassis/include/sit_chassis/ThreeChassis.h

该类通过sit_protocol功能包实现向下位机获取与设置原始轮速,本类继续通过引入比例系数K,结合原始轮速实现了AThreeChassis抽象类中的设置与获取轮速的纯虚函数。

ChassisNode类

sit_chassis/include/sit_chassis/ChassisNode.h

该类实现了AChassis接口与ros的发布订阅机制的结合,前面之所以划分出较为复杂的抽象层次结构,最精彩的便是在本类中体现,观察本类发现,其并不依赖于任何具体实现类,而仅依赖了AChassis接口。

熟悉设计模式的同学可以看出,这里实现了依赖倒置原则。它的好处就是,借助c++的动态多态性,我们可以实现更多的运动模型底盘实现类,其均可作为AChassis传入本类的构造函数,从而将底盘接入整个ros生态,这大大提高了软件的可复用性,降低了耦合度。

主入口类

sit_chassis/src/three_chassis_node.cpp

该类为主入口类,其实现较为简单,代码如下,

#include <ros/ros.h>
#include <sit_chassis/ThreeChassis.h>
#include <sit_chassis/ChassisNode.h>

int main(int argc, char **argv)
{
    setlocale(LC_ALL, "");
    ros::init(argc, argv, "three_chassis"); //初始化三轮底盘节点
    ros::NodeHandle nh("~");
    ThreeChassis chassis(nh);

    ChassisNode cn(nh,&chassis);
    for (ros::Rate rate(20); ros::ok(); rate.sleep())
    {
        cn.spinOnce();
        ros::spinOnce();
    }
    return 0;
}

launch文件

sit_chassis/launch/chassis.launch

<?xml version="1.0"?>
<launch>
    <arg name="k" default="-4772.44"/>
    <arg name="radius" default="0.1900"/>
    <node pkg="sit_chassis" type="three_chassis_node" name="chassis_node" output="screen">
        <param name="k" value="$(arg k)"/>
        <param name="radius" value="$(arg radius)"/>
    </node>
</launch>

该文件启动一个三轮底盘节点,需要传入两个标定系数k与底盘半径radius。

底盘半径radius一般为手动测量得出。

标定系数k可由脚本自动标定得出。

script脚本

sit_chassis/scripts/calibrator.py

本脚本用于标定出底盘系数k。