simple_mover 只发布关节角度命令 simple_arm 。
在了解用Python编写的ROS节点的一般结构之后,现在要编写另一个名为 arm_mover 的节点。
arm_mover 提供一种叫做 safe_move 的服务,它允许机械臂移动到其工作区内被认为是“安全”的任何位置。安全区域由最小和最大关节角度限制,可通过ROS参数服务器进行配置。
最后一个节点是 look_away 节点。此节点订阅正在发布摄像机数据的主题。当相机检测到具有均匀颜色的图像时,意味着它正在观察天空,节点将调用 safe_move 服务将手臂移动到新位置。
发布者允许节点向主题发送消息,以便来自节点的数据可以用在ROS系统的其他部分中。在Python中,ROS发布者通常具有以下定义格式,尽管其他参数和参数也是可能的:
pub1 = rospy.Publisher("/topic_name", message_type, queue_size=size)
该" /topic_name "指示发布者将被发布到该话题。 message_type 是在“ / topic_name ”上发布的消息类型。
ROS发布可以是同步的也可以是异步的:
pub1.publish(message)
有关ROS发布者的更多信息,请参阅此处的文档。
调用此节点 simple_mover 。顾名思义,这个节点只有一个任务,那就是命令联合运动 simple_arm 节点。
为此,它必须将关节角度命令消息发布到以下主题:
Topic Name | /simple_arm/joint_1_position_controller/command |
---|---|
Message Type | std_msgs/Float64 |
Description | Commands joint 1 to move counter-clockwise, units in radians |
Topic Name | /simple_arm/joint_2_position_controller/command |
- | - |
Message Type | std_msgs/Float64 |
Description | Commands joint 2 to move counter-clockwise, units in radians |
翻译如下:
主题名称 | / simple_arm / joint_1_position_controller / command |
---|---|
消息类型 | std_msgs / Float64 |
说明 | 命令关节1逆时针移动,单位为弧度 |
主题名称 | / simple_arm / joint_2_position_controller / command |
- | - |
消息类型 | std_msgs / Float64 |
说明 | 命令关节2逆时针移动,单位为弧度 |
要在python中创建新节点,必须首先在 simple_arm 包中创建 scripts 目录,因为它尚不存在。
$ cd ~/catkin_ws/src/simple_arm/
$ mkdir scripts
创建脚本目录后,可以将可执行脚本添加到包中。但是,为了rosrun找到它们,必须更改其权限以允许执行。让我们添加一个简单的bash脚本,将“Hello World”打印到控制台。
$ cd scripts
$ echo '#!/bin/bash' >> hello
$ echo 'echo Hello World' >> hello
没有权限,而且在我使用sudo命令后还是无法解决问题。
解决办法:
使用 touch 命令新建 hello.sh 文件:
sudo touch hello.sh
更改文件的权限
chmod 777 hello,sh
如图所示:
在对文件设置适当的执行权限,重建工作空间以及获取新创建的环境之后,将能够运行该脚本。
$ cd ~/catkin_ws
$ catkin_make
$ source devel/setup.bash
$ rosrun simple_arm hello.sh
如图现在已添加了一个名为 hello.sh 脚本
创建 simple_mover 节点脚本,就按照刚才介绍的例子来完成就可以了。
$ cd ~/catkin_ws/src/simple_arm/scripts
$ sudo touch simple_mover
$ sudo chmod 777 simple_mover
这样我们就有了空的 simple_mover 节点脚本,然后我们就可以来编写这个脚本了。
使用命令
$ cd ~/catkin_ws/src/simple_arm/scripts/
$ nano simple_mover
打开文本编辑器,然后我们就可以在其中编写python代码了。
代码如下:
#!/usr/bin/env pythonimport math
# rospy是ROS的官方Python客户端库。它提供了通过Python与ROS连接所需的大部分基本功能。
import rospy
# 从std_msgs包中,我们导入Float64,这是ROS中的原始消息类型之一。
from std_msgs.msg import Float64def mover():pub_j1 = rospy.Publisher('/simple_arm/joint_1_position_controller/command',Float64, queue_size=10)pub_j2 = rospy.Publisher('/simple_arm/joint_2_position_controller/command',Float64, queue_size=10)rospy.init_node('arm_mover')rate = rospy.Rate(10)start_time = 0while not start_time:start_time = rospy.Time.now().to_sec()while not rospy.is_shutdown():elapsed = rospy.Time.now().to_sec() - start_timepub_j1.publish(math.sin(2*math.pi*0.1*elapsed)*(math.pi/2))pub_j2.publish(math.sin(2*math.pi*0.1*elapsed)*(math.pi/2))rate.sleep()if __name__ == '__main__':try:mover()except rospy.ROSInterruptException:pass
import rospy
rospy是ROS的官方Python客户端库。它提供了通过Python与ROS连接所需的大部分基本功能。它具有用于创建节点,与主题,服务,参数等接口的接口。
from std_msgs.msg import Float64
从std_msgs包中,我们导入Float64,这是ROS中的原始消息类型之一。该std_msgs包还包含所有其他基本类型。在本脚本中,我们将向每个关节的位置命令主题发布Float64消息。
def mover():pub_j1 = rospy.Publisher('/simple_arm/joint_1_position_controller/command',Float64, queue_size= 10)pub_j2 = rospy.Publisher('/simple_arm/joint_2_position_controller/command',Float64, queue_size=10)
在mover功能的顶部,声明了两个发布者,一个用于关节1命令,一个用于关节2命令。此处,该 queue_size 参数用于确定在删除 messages 之前可能存储在发布者队列中的最大 messages 数。
rospy.init_node('arm_mover')
初始化客户端节点并将其注册到主节点。这里“ arm_mover ”是节点的名称。 init_node() 必须在调用任何其他rospy包函数之前调用。该参数 anonymous=True 确保节点始终拥有的唯一名称
rate = rospy.Rate(10)
rate 此处创建的对象的值为10Hz。速率用于限制某些循环在ROS中旋转的频率。选择过高的速率可能会导致不必要的高CPU使用率,而选择过低的值可能会导致较高的整体系统延迟。为ROS系统中的所有节点选择合理的值是一门艺术。
start_time = 0while not start_time:start_time = rospy.Time.now().to_sec()
start_time 用于确定已经过了多长时间。当使用带模拟时间的ROS时(正如这个例子), rospy.Time.now() 最初将返回0,直到收到关于 /clock 主题的第一条消息。 这就是为什么要设置 start_time 并连续轮询,直到返回一个非零值。
while not rospy.is_shutdown():elapsed = rospy.Time.now().to_sec() - start_timepub_j1.publish(math.sin(2*math.pi*0.1*elapsed)*(math.pi/2))pub_j2.publish(math.sin(2*math.pi*0.1*elapsed)*(math.pi/2))rate.sleep()
这是主循环。由于调用 ***rate.sleep()***,循环以大约10赫兹的速度运行。通过循环体的每次旅行将导致发布两个联合命令消息。关节角度采用正弦波采样,周期为10秒,幅度为[−π/2,+π/2][- π / 2 ,+ π / 2 ][−π/2,+π/2]。当节点收到要关闭的信号时(从主控制器或通过控制台窗口中的SIGINT信号),将退出循环。
if __name__ == '__main__':try:mover()except rospy.ROSInterruptException:pass
如果name变量设置为“ main ”,表示正在直接执行此脚本,mover()则将调用该函数。这里的 try / except 模块很重要,因为rospy广泛使用异常。这里捕到的特殊例外是 ROSInterruptException 。当节点已发出关闭信号时,会引发此异常。如果在节点关闭之前可能需要进行某种清理,那就可以在这里完成。
更多信息请参考这里。
这样我们已经完成了一个使机械手简单运行的脚本,接下来便使用 ctrl+x ,选择yes, 然后按Enter保存文件。
确保的工作区已经构建,并且它setup.bash已经被提取,因此可以使 simple_arm 按如下方式启动:
$ cd ~/catkin_ws
$ roslaunch simple_arm robot_spawn.launch
一旦ROS Master,Gazebo和我们所有相关节点启动并运行,我们才可以启动 simple_mover 。
打开一个新终端并键入以下命令:
$ cd ~/catkin_ws
$ source devel/setup.bash
$ rosrun simple_arm simple_mover
我们已经编写了第一个ROS节点,也知道了如何发布主题,并且可以通过发布到**/simple_arm/joint_2_position_controller/command**主题来控制机械臂。接下来使另一个被调用的节点 arm_mover ,它实现了 safe_move 服务以允许通过服务调用来控制机械臂。
ROS服务允许节点之间存在请求/响应通信。在提供服务的节点内,请求消息由函数或方法处理。成功处理请求后,提供服务的节点会将消息发送回请求者节点。在Python中,可以使用以下定义格式创建ROS服务:
service = rospy.Service('service_name', serviceClassName, handler)
这里 service_name 是给服务的名称。其他节点将使用此名称来指定他们向其发送请求的服务。
它 serviceClassName 来自存在服务定义的文件名。每个服务都有一个 .srv 文件中提供的定义; 这是一个文本文件,为请求和响应提供正确的消息类型。
handler 是处理传入服务消息的函数或方法的名称。每次调用服务时都会调用此函数,并将来自服务调用的消息 handler 作为参数传递给它。 handler 应返回相应的服务响应消息。
可以直接从命令行调用服务,或者在另一个节点内使用ROS服务。
定义一个 ServiceProxy ,它提供了向服务发送消息的接口:
service_proxy = rospy.ServiceProxy('service_name', serviceClassName)
ServiceProxy 然后可以使用一种方式发送请求, 如下:
msg = serviceClassNameRequest()
# update msg attributes here to have correct data
response = service_proxy(msg)
在上面的代码中,通过调用 serviceClassNameRequest() 方法创建新的服务消息。此方法由rospy提供,其名称通过附加 Request() 用于的名称给出 serviceClassName 。
由于消息是新的,因此应更新消息属性以获得适当的数据。接下来, service_proxy 可以使用消息调用,并存储响应。
有关传递数据的其他方法service_proxy,请参阅此处的ROS文档。
当一个IT组织开始走到需要实施网络边缘的旅程时,他们很快意识到面对的挑战与他们在传统数据中心内所经历的挑战不同。 第一个挑战是空间。与更大的核心或区域数据中心同类产品相比,许多边缘站点的物理尺寸更小,因此,需要仔细计划好,尝试在未为其专门设计的空间中安装硬件。 第二个挑战是运行环境。还必须解决的可能面对的冷热温度变化 ,天气,无...
单向循环链表单链表的一个变形是单向循环链表, 链表的最后一个节点的next域不再为None, 而是指向链表的头节点.单向循环链表如图所示:单向循环链表同样单向循环链表也是要使用python来对它的基本功能进行一个封装. 总体大致的功能如下:is_empty() 判断链表是否为空length() 返回链表的长度travel() 遍历ad...
题目: 二叉搜索树与双向链表 输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的循环双向链表。要求不能创建任何新的节点,只能调整树中节点指针的指向。 为了让您更好地理解问题,以下面的二叉搜索树为例: 我们希望将这个二叉搜索树转化为双向循环链表。链表中的每个节点都有一个前驱和后继指针。对于双向循环链表,第一个节点的前驱是最后一...
题目:删除链表的节点 给定单向链表的头指针和一个要删除的节点的值,定义一个函数删除该节点。 返回删除后的链表的头节点。 注意:此题对比原题有改动 示例 1: 输入: head = [4,5,1,9], val = 5 输出: [4,1,9] 解释: 给定你链表中值为 5 的第二个节点,那么在调用了你的函数之后,该链表应变为...
【从零开始的ROS四轴机械臂控制】(一)- 实际模型制作、Solidworks文件转urdf与rviz仿真 一、模型制作 1.实际模型制作 2.Solidworks模型制作 二、Solidworks文件转urdf 1.sw_urdf_exporter插件 2.添加坐标系和转轴 3.导出urdf文件 三、rivz仿真...
首先对微擎的工作原理做简单描述, 微擎使用规则和模块的机制来处理公众平台的请求数据并返回响应的结果.执行流程描述为: 粉丝用户与公众号码进行对话或交互, 而后公众平台将粉丝用户的请求消息(当前包括: 文本, 图片, 位置, 链接, 事件. 请参阅消息类型)传递给微擎系统, 微擎系统按照消息类型和对应的公众号所设定的规则列表匹配到合适的...
消息队列的使用场景以下介绍消息队列在实际应用常用的使用场景。异步处理、应用解耦、流量削锋和消息通讯四个场景。1】异步处理:场景说明:用户注册后,需要发注册邮件和注册短信。引入消息队列后架构如下:用户的响应时间=注册信息写入数据库的时间,例如50毫秒。发注册邮箱、发注册短信写入消息队列后,直接返回客户端,因写入消息队列的速度很快,基...
下面是我凭记忆想到的几个题目,有需要的同学就拿去吧,我也算做了点善事.
中体骏彩C++笔试题 2013-11-18 1.指针的含义是:B A.名字 B.地址 C.名称 D.符号 2.给出下面的程序输出: #include
双端通信描述 利用消息队列针对发送接受消息的类型唯一性 进行多个客户端之间消息传递,而不需要server端进行消息转发。 同时消息队列的读阻塞和写阻塞特性(消息队列中已经写入数据,如果再不读出来,则无法再次写入)让消息队列的实现过程只能如下: 客户端1的父进程用来处理类型1的消息写,子进程处理类型2的消息读客户端2的父进程处理类型...
文章目录基本介绍编程接口代码实例消息队列的发送和接收消息队列中的消息对象的属性控制 基本介绍 支持不同进程之间以消息(messages)的形式进行数据交换,消息能够拥有自己的标识,且内核使用链表方式进行消息管理。进程之间的通信角色为:发送者和接受者 发送者: a. 获取消息队列的ID(key或者msgid) b. 将数据放入...