栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

【日知录17】ROS初识

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

【日知录17】ROS初识

本文章是根据古月居21讲的笔记
  • 1.关于ROS通信机制的一些理解
      • 话题(Topic)
      • 服务(Service)
      • 两种通讯机制的比较
  • 2.代码实现
    • 2.1话题
      • 发布者publisher
      • 订阅者subscriber
      • 自定义话题
      • 比较
    • 2.2服务
      • client
      • server
      • 自定义
      • 比较
        • rospy
    • 2.3参数使用
    • 2.4 tf

ps:在b站发现另一个学习视频更详细更清楚,且搭建环境也很友好。赵虚左老师

1.关于ROS通信机制的一些理解

ROS wiki


在通信机制方面,有两种通信形式,话题(Topic)和服务(Service)。

话题(Topic)

异步通信,可以理解为给别人发邮件,只能单向传输。


节点在Node

服务(Service)

两种通讯机制的比较

理解层级关系

2.代码实现

2.1话题 发布者publisher

给海龟设定运动速度,角度。Twist()

1.创建功能包 包含依赖项
2.创建发布者代码.cpp
3.配置CMakelist.txt中的编译规则

add_executable(velocity_publisher src/velocity_publisher.cpp)
target_link_libraries(velocity_publisher ${catin_LIBRARIES})

注意:这里的 src/velocity_publisher.cpp 就是在第二步中ubuntu中写入的.cpp文件的文件名。如果此处文件名或者路径不对,会产生CMake相关报错。

4.编译和运行发布者
一共需要运行6个指令。

$ cd ~/catkin_ws //在catkin_ws文件夹内进行操作,也可以直接找到这个文件夹后,右键,在终端打开。
$ catkin_make    //编译,十分重要的一步,也很容易产生错误。

简要分析一下第二步报错的解决,
1.如果是Camke错误,找到报错的对应行,然后看看文件名是否正确。
2.如果是自己手打的.cpp文件,可能存在一些名称错误,要自查。
3.在创建publisher之后,发布的topic的名称不对,如下图,括号内就是 这个topic的名称。
在之前的尝试中,我写成了

(“/turtle/cmd_vel”,10);
这个就是小海龟的对应名称。但是会报错。所以我又改成了
(“/turtle1/cmd_vel”,10); 注此处的修改时加了一个数字1。即第一个小海龟的意思。
这样之后再重新编译,即 $ catkin_make。成功

如果是这种错误:Invoking:"make -j2 -l2"failed 那么建议自查一遍cpp文件是否有格式,拼写错误

接下来继续进行指令运行

 $ source devel/setup.bash 
 $ roscore  
 $ rosrun turtlesim turtlesim_node  
 $ rosrun learning_topic velocity_publisher 

如下图所示就是成功运行的。
如果出现,代码一直跑,但小海龟不动的情况,参考上面我说的修改小海龟的名称这种方法。

订阅者subscriber

遇到过修改输出格式x,y坐标之后,一直没有同时显示两个坐标,之后通过重新catkin_make之后,成功输出x,y两个坐标。
订阅海龟的x.y 坐标并显示,pose()

自定义话题

即自定义话题消息类型。
如何自定义数据,此处以自定义话题消息messages,自定义服务数据services这两种情况为例分析。
1.对编译文件的创建,变成不同的C++,python,完成数据接口定义
messages就新建msg文件夹
services就新建svc文件夹

2.对编译规则的设置,即对添加功能包依赖

################################################
## Declare ROS messages, services and actions ##
################################################

## To declare and build messages, services or actions from within this           //为了声明消息,服务,动作。需要做以下操作
## package, follow these steps:
## * Let MSG_DEP_SET be the set of packages whose message types you use in        //1.确保在创建工作空间时有依赖这些包
##   your messages/services/actions (e.g. std_msgs, actionlib_msgs, ...).
## * In the file package.xml:													//2.在package.xml文件中完成以下操作
##   * add a build_depend tag for "message_generation"    
##   * add a build_depend and a exec_depend tag for each package in MSG_DEP_SET
##   * If MSG_DEP_SET isn't empty the following dependency has been pulled in
##     but can be declared for certainty nonetheless:
##     * add a exec_depend tag for "message_runtime"

//所以有在xml文件中添加的这两行依赖
 message_generation  //编译依赖
  message_runtime ///执行依赖


## * In this file (CMakeLists.txt):                 //3.在Cmakelist文件中,需要做以下操作
##   * add "message_generation" and every package in MSG_DEP_SET to  //添加message_generation和每个在MSG_DEP_SET的包到find_package
##     find_package(catkin REQUIRED COMPONENTS ...)
##   * add "message_runtime" and every package in MSG_DEP_SET to//添加message_runtime和每个在MSG_DEP_SET的包到catkin_package
##     catkin_package(CATKIN_DEPENDS ...)
##   * uncomment the add_*_files sections below as needed//没有在下面add_列出的部分,需要列出每个.msg .srv .action以保证被可以执行
##     and list every .msg/.srv/.action file to be processed
##   * uncomment the generate_messages entry below
##   * add every package in MSG_DEP_SET to generate_messages(DEPENDENCIES ...)

## Generate messages in the 'msg' folder  //列出部分add定义的格式,包括 message,service,action,
# add_message_files(
#   FILES
#   Message1.msg
#   Message2.msg
# )

## Generate services in the 'srv' folder
# add_service_files(
#   FILES
#   Service1.srv
#   Service2.srv
# )

## Generate actions in the 'action' folder
# add_action_files(
#   FILES
#   Action1.action
#   Action2.action
# )

## Generate added messages and services with any dependencies listed here //创建依赖
# generate_messages(
#   DEPENDENCIES
#   geometry_msgs#   std_msgs
# )


add_message_files(
  FILES
  Person.msg
)

generate_messages(
  DEPENDENCIES
  std_msgs
)

//因此在cmakelist中进行这些操作
find_package(... message_generation)

add_message_files( FILES  Person.msg)
generate_messages( DEPENDENCIES std_msgs)
catkin_package(... message_runtime)

理解Cmakelist里面的 Declare ROS messages,services and actions
同理,理解自定义服务数据。

C++

遇到过的编译报错,检查Cmakelist。

add_executable cannot create target"person_publisher" because another target with the same name already exists.
the existing target is an executable created in source directory

原因是重复添加了add_executable(),导致重复编译。

python运行时的报错,暂未解决。应该是和数据输出格式有关系。

比较

不理解这里代码的count=0是什么意思。

//订阅者不知道什么时候会有消息进来,
//所以此处有回调函数poseCallback,一旦有消息进来则通过回调函数打印数据
    ros::Subscriber pose_sub = n.subscribe("/turtle1/pose", 10, poseCallback);

    // 循环等待回调函数,spin()会不断查看消息队列,是否有消息进入,有则调用poseCallback()
    ros::spin();
const turtlesim::Pose::ConstPtr& msg//C++常指针,类型名 turtlesim::Pose

What is ConstPtr&?

int main( argc **argv)的理解

综合以上两点,我看到弹幕里很多在问,为什么输出的时候用的是

ROS_INFO(“Turtle pose: x:%0.6f, y:%0.6f”, msg->x, msg->y);

其中的原因主要于指针有关。
我尝试将输出直接改成 msg.x msg.y,出现报错。

可以看出来应该是与回调函数中的指针输出格式有关系,所以查阅了C书中“指向结构体类型数据的指针”之后,明确输出格式。C++书中解释和这个类似。

this->height 
(*this).height  //.的优先级高于*,因此*this.height 相当于*(this.height)


所以修改了指针

进一步思考,如果发送的是多个人的信息要怎么实现?即topic多发
单节点的多Topic同时收发
使用了数组,字符串

2.2服务

在catkin_make中的错误,一般是Cmakelist里面找。

Could NOT find std_msgs geometry_msgs

百度之后说是缺少包,所以我又重新创建了一遍工作空间,估计是少依赖一个包。重新创建工作空间之后问题解决。成功创建第二个小海龟。

client

对于python版本实现,确实存在一些难度,比如古月居的视频是python2,而我目前是python3,在一些语法上会存在差异,总有这样那样的错误。



如何生成多个小海龟

server

因为本例只对server端进行编译,所以在最后程序实现时,通过rosservice call命令来调用服务
理解服务端的工作流程,初始化ROS节点,创建server实例/turtle_command ,创建publisher,通过发布消息使小海龟运动。显示“Ready to receive turtlr command”。在while循环中通过spinOnce()查看回调函数队列。
此时在终端通过rosservice call命令来调用/turtle_command服务,服务器开始调用回调函数,先将pubCommad标志位取反,显示“publish turtle velocity command [yes/no]”,返回显示“change turtle command state ”“success:true”
if判断,是否将话题消息发布给海龟仿真器,是则小海龟运动,否则小海龟停止。

自定义

理解一下这个客户端与服务端的工作流程。
服务端程序中,先执行创建服务端中的show_person服务,显示“Ready to show person information”之后循环等待回调函数,请求服务调用。
此时客户端程序中,ros::service::waitForService(“/show_person”)发现了/show_person服务,此时创建客户端名为/show_person,对数据进行初始化,之后请求/show_person服务调用,并显示“Call service to show person[name:Tom,age:20,sex=11]”,通过add_turtle.call(srv)将封装好的数据发送出去,并且一直在等待回复。
此时服务端的ros::spin()检查到队列中的数据,调用回调函数personCallback(),显示"Person: name :Tom age:20 sex:1",并将结果res.result=“OK"返回给客户端中的add_turtle.call(srv)。
客户端继续运行,显示"Show person result:OK”

比较

rospy

借鉴某博主对于rospy库的一些理解

rospy创建和初始化一个node,不再需要NodeHandle(rospy没有设计NodeHandle这个句柄),创建topic、service等操作都直接用rospy里对应的方法即可。
rospy节点的初始化补衣服ing必须放在开头,在Publisher建立后再初始化也可以。
消息的创建更加简单,例如gps类型的消息可以直接用类似与构造函数的方式gps(state,x,y)创建。
日志的输出方式不同,C++是ROS_INFO(),Python中为rospy.loginfo()。
判断节点是否关闭的函数不同,C++为ros::ok(),Python为rospy.is_shutdown()。

2.3参数使用

相当于在工作空间内的参数字典

rosparam list
rosparam get param_key
rosparam set param_key param_value
rosparam dump file_name
rosparam load file_name
rosparam delete param_key
2.4 tf

机器人坐标变换的3种可视化方法

rosrun tf view_frames

遇到bug:TypeError: cannot use a string pattern on a bytes-like object
修改办法
显示图表

rosrun tf tf-rcho turtle1 turtle2

rosrun rviz rviz -d`rospack find turtle_tf`/rviz/turtle_rviz.rviz
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/977293.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号