前回の記事では、ROS環境をインストールしました。この記事では、内ROSのコンセプト(概念)のいくつかに精通している、と出版社(パブリッシャ)と加入者(加入者)を実装するために、C ++を使用しようとします。
この記事ROSレコードを学習者の個人過程で、参考書は、中国版である「ROSロボットプログラミング:原理と応用」、英語版があるROSと学習ロボットプログラミングに体系的なアプローチ、書籍コードがホストされている著者wsnewman GitHubの上、著者の支払いが困難に感謝。
記事は、次のセクションに分かれています。
- ROSのコンセプト
- ROSで出版社を実装
- あなたの出版を実行します
1. ROS
私はちょうどこの記事は、派生これらの概念の定義に関係しますいくつかの概念の名前にROSウィキを、さらなる洞察に興味を持っています。
1.1 ROSファイルシステム
これは、組織の文書のPythonのパッケージ(パッケージ)の形に似たROSのファイルを、整理の方法で導入することです。
- パッケージ:ROSのパッケージは、パッケージは、関連するノード(ノード)のシリーズ、ROS依存ライブラリ、プロファイルなどを含んでいてもよい、ROSのメインプログラムの組織単位です。ROSパッケージには、コンパイルして、問題ができる最小単位であり、あなたが運転をコンパイル時間のほとんどは、パッケージをコンパイルすることです。
- package.xmlの:主にパッケージ名、バージョン、簡単に、著作権情報、およびその依存を含むパッケージについての情報を提供し、パッケージを記述するために使用されます。
- メッセージタイプ:パブリッシャ/サブスクライバが正しく/復号化されたバイト・ストリームを符号化することができるようにトピック(トピック)には、メッセージに定義されています。
1.2 ROSのコンセプト
ノード(ノード):ノードは、あなたが使用することの実行可能ファイル、実行可能ファイルである
roscpp
かrospy
作成します。マスター:私たちは、コマンドを介して実行前回の記事では
roscore
、コマンドの役割のいずれかを起動することでROS Master
、各ノードは名前で別のノードを見つけることができるように、名前の登録と解決を提供するために、主に、マスター。メッセージ(メッセージ):ノードが相互にメッセージを交換することによって達成されるが、メッセージは同様である
struct
いくつかのフィールドを含むことができるデータ構造。例:パスに/opt/share/melodic/share/std_msgs/msg
(インストールされ、あなたが私の最後の記事のようなものであれば)、あなたは定義されたメッセージの多くを見ることができ、例えば次のように、ColorRGBA.msgを開いて、読み取ります。float32 r; float32 g; float32 b; float32 a;
トピック(トピック):トピックはトピック名(トピック名)に代表される、メールボックスと考えることができ、発行者は、私はちょうどライン上のメールボックスにメッセージを置く必要があると思うし、加入者は、私はちょうどこのメールボックスを取得する必要があると思います交換ノードの性質がメッセージを通過させることであるので、ライン上のメッセージは、ちょうど2つの側面が良いパスを交換することに合意したトピックを指定します。全体のプロセスは、図のように表すことができます。
2. ROSで出版社を実装
ワークスペースとパッケージを作成するために2.1
ROSプログラムを書き込む前に、ROSのワークスペースを提案する最初の、すべての後に準備が作業領域になり、作業領域が特定の形式を持っている、あなたは選ぶことができますhome
作成したディレクトリを、順番に次のコマンドを入力します。
mkdir -p ~/catkin_ws/src # 创建工作区
cd ~/catkin_ws/src # 进入工作区
# catkin_create_pkg package_name(包名称) dependencies(依赖)
catkin_create_pkg my_minimal_node roscpp std_msgs #新建一个ROS包
作成が完了したら、我々はカタログで見ることができますmy_minimal_node
つ以上のファイル(package.xml
、CMakeLists.txt
)および2つのフォルダ(src
、include
)。
これはpackage.xml
前述したROSのパッケージ構成ファイル、パッケージについての記述情報です。CMakeLists.txt
コンパイルプロセスを設定するために使用され、これらは、この記事で使用される主な文書の2つです。
2.2変更package.xml
首先我们来修改package.xml
,在编辑器中打开该文件,可以看到文件中包含了大量的注释,这些注释都是来指导你该如何书写该文件。
一般说来我们应该包括<name>
,<version>
,<description>
,<maintanner>
,<license>
,<author>
,<build_depend>
,<build_export_depend>
, <exec_depend>
便可以了,这部分大家可以按照自己的信息进行修改。
修改后的package.xml
类似于下面的内容,当然你也可以不修改,对于这一篇内容来说,这无关紧要。
<?xml version="1.0"?>
<package format="2">
<name>my_minimal_node</name>
<version>0.1.0</version>
<description>The my_minimal_node package</description>
<maintainer email="[email protected]">gnc</maintainer>
<license>MIT</license>
<author email="sharku">Jane Doe</author>
<buildtool_depend>catkin</buildtool_depend>
<build_depend>roscpp</build_depend>
<build_depend>std_msgs</build_depend>
<build_export_depend>roscpp</build_export_depend>
<build_export_depend>std_msgs</build_export_depend>
<exec_depend>roscpp</exec_depend>
<exec_depend>std_msgs</exec_depend>
</package>
2.3 编写第一个简单的ROS程序-发布器
进入到目录~/catkin_ws/src/my_minimal_node/
下,在该目录下的src
文件夹创建minimal_publisher.cpp
,内容如下,代码内容也可以在文章最开始给出的github中找到。
#include <ros/ros.h>
#include <std_msgs/Float64.h>
int main(int argc, char **argv) {
ros::init(argc, argv, "minimal_publisher"); // 初始化节点名
ros::NodeHandle n; //
ros::Publisher my_publisher_object = n.advertise<std_msgs::Float64>("topic1", 1); // 创建一个发布器,调用advertise通知ROS Master话题名称以及话题类型
//"topic1" 是话题名
// 参数 "1" 是queue_size,表示缓冲区大小
std_msgs::Float64 input_float; // 创建一个发布器将要使用的消息变量
// 该消息定义在: /opt/ros/indigo/share/std_msgs
// 在ROS中发布的消息都应该提前定义,以便订阅者接收到消息后该如何解读
// Float64消息的定义如下,其中包含一个数据字段data:
// float64 data
input_float.data = 0.0; // 设置数据字段
// 程序所要做的工作将在下面的循环里完成
while (ros::ok())
{
// 该循环没有sleep,因此将一直处于运行状态,不断消耗CPU资源
input_float.data = input_float.data + 0.001; //每循环一次+0.01
my_publisher_object.publish(input_float); // 发布消息到对应的话题
}
}
代码中,#include <ros/ros.h>
表示包含ROS头文件,#include <std_msgs/Float64.h>
表示包含标准消息类型中的Float64
,它的具体类型是float64
。
在上述代码中,在main
函数中,首先对ROS进行初始化,调用ros::init
定义了节点名称。然后定义了ros::NodeHandle
该变量用来创建一个发布者,通过调用函数.advertise
,表示向Master声明我要注册一个话题名为topic1
,然后我将会向该话题发布消息,然后返回一个发布器对象。随后我们便可以调用该发布器的.publish
来进行消息的发布。
其余部分的解释可以看代码中的注释。
2.4 修改CMakeLists.txt
文件
在编写了发布器的程序以后,我们还必须在CMakeLists
文件中进行声明,以便让编译器知道应该编译新增的文件。
在CMakeLists文件的最后一行加入下面两行代码:
add_executable(my_minimal_publisher src/minimal_publisher.cpp) # 第一个参数是生成后的可执行文件名 第二个参数
# 是源文件路径名
target_link_libraries(my_minimal_publisher ${catkin_LIBRARIES}) # 链接库
然后关闭文件,打开终端,导航到目录~/catkin_ws/
下,运行命令catkin_make
即可编译我们刚刚创建的文件。
有可能你的输出结果和我这里显示的不同,因为我已经编译过了,所以编译器没有执行任何动作。
3. 运行你的发布器
在上面的编译过程没有出现问题的情况下,那么你的编译就成功了,接下来我们来运行我们刚刚编写的发布器。
3.1 将工作区路径加入你的终端
类似于$PATH
变量,ROS也有自己的路径变量,用来搜索所有的ROS包,因为到这里我们还没有将我们的ROS包加入到ROS路径中去,因此在运行的时候会找不到我们的ROS包。
不过幸运的是,ROS帮我们生成了一个方便的编译脚本,位于路径~/catkin_ws/devel/setup.bash
下。如果我们直接运行source ~/catkin_ws/devel/setup.bash
那么只会在当前的终端下生效,当你重新打开一个终端,又会无效。因此,我们需要将上面的命令加入到启动脚本中,运行下面的命令完成:
echo "source ~/catkin_ws/devel/setup.bash" >> ~/.bashrc
之后你的终端在启动时都将首先运行该命令,然后ROS就可以找到你的程序了。
3.2 启动发布器
打开终端,运行命令:
roscore # 启动ROS Master
然后运行:
rosrun my_minimal_node my_minimal_publisher # 启动发布器
启动以后,尽管看起来什么都没有发生,但是事实上发布器已经在不断发布消息了。下面我们用ros工具来查看该发布器。
运行命令:
rosnode list # rosnode list 用来列出当前ROS中运行的节点名
我们可以得到当前ROS系统运行的节点名称,可以看到我们初始化的节点名称出现在了该列表中,证明我们的发布器的确在运行中。
然后运行命令:
rostopic list # rostopic list 用来列出当前ROS中所有的话题名
同样可以看到我们注册的话题名称topic1
。
然后运行命令:
rostopic hz /topic1 # rostopic hz 用来检查话题的发布频率
可以看到发布平均频率是3.3kHz,发布频率比较高,因此造成的问题是长时间占用CPU。如下图所示:
这一问题在之后我们将使用sleep
方法来设置一个合适的发布频率。
然后运行命令:
rostopic echo -n1 /topic1 # rostopic echo 用来显示话题的消息 -n1代表只接收一次
可以看出输出值为192239.12749
,因此通过简单的计算便可以得出程序已经循环了19223912
次左右。
视频
上記のプロセスのすべては、私はあなたが問題を持っている場合、あなたは私がやっていたかを確認するためにビデオを見ることができます記事を閲覧する過程で、映像を記録しました。