简介:编写一个node,实现通过该node进行barrett机械手的初始化。bhand_controller提供很多关于机械手操作的服务,如我们可以通过终端运行下面命令:
$ rosservice call /bhand_node/actions "action: 1",实现机械手初始化,恢复到手指初始展开位姿,并进入到ready状态。本文将初始化等系列操作集成到一个node中,可以实现机械初始化和如开合等基本动作。
效果:运行 rosrun beginner_tutorials bhand_test 后,机械手自动初始化,然后等待3s后手指闭合。
环境:ubuntu 14.04 +indigo.
[正文]
1 获取调用服务需要的相关信息。通过roslaunch bhand_controller bhand_controller.launch运行barrett机械手控制主节点,通过service list可以查询到当前节点中服务如下图所示,本次要用到是/bhand_node/actions服务。
为了能够在测试node中使用该服务,通过rosservice type查询其服务类型为bhand_controller/Actions,后文调用该服务是需要引用的一个头文件来自于这里。
此外通过rossrv show指令可以查询到actions的类型为int32,wiki barrett页面事实上没有说明我们最终调用的action的取值范围,但示例给的init hand的action为1,通过rosmsg show bhand_controller/Service可以查询到相关action的取值,推测调用取值是如文件所示。
2 实现节点对于服务的调用。传统client.call()调用的步骤如下,
(1)引入所要调用的服务类型的头文件。
本文中通过type查询到的类型为bhand_controller/Actions,故引入bhand_controller/Actions.h头文件。
(2)定义NodeHandle,client。并将client定义为 NodeHandle对象的serviceClient链接到的目标服务。其中bhand_node/actions为service list里的服务名称,bhand_controller::Actions为服务类型。
client=nh.serviceClient<bhand_controller::Actions>("bhand_node/actions");
(3)通过目标服务类型定义测试服务对象。并根据服务request实现服务对象的数据填充。
文中已通过rossrv show 知道目标服务只有一个int32参数,所以填充如下。
bhand_controller::Actions test_action;
test_action.request.action=1;
(4)将填充好数据的服务对象代入client.call()实现调用。
client.call()函数调用成功会返回True因此可通过if判读是否调用成功,文中实现如下:
if(client.call(test_action))
{
ROS_INFO("Init the robotic hand successfully!");
......
}
else
ROS_INFO("Failed to Init the robotic hand!");
完整实现程序如下:
#include <ros/ros.h> #include "bhand_controller/Service.h" #include "bhand_controller/Actions.h" int main(int argc,char **argv) { ros::init(argc,argv,"example_srv_bhand"); ros::NodeHandle nh; ros::ServiceClient client; client=nh.serviceClient<bhand_controller::Actions>("bhand_node/actions"); bhand_controller::Actions test_action; test_action.request.action=1; if(client.call(test_action)) { ROS_INFO("Init the robotic hand successfully!"); ros::Duration(3).sleep(); test_action.request.action=2; if(client.call(test_action)) ROS_INFO("Closed the robotic hand successfully!"); else ROS_INFO("Failed to close robotic hand!"); } else ROS_INFO("Failed to Init the robotic hand!"); ros::spinOnce(); return 0; }
备注:
1.由于此处引用了bhand_controller/Service.h,因此在test_action.request.action=1初始化是也可以采用下面方案:
test_action.request.action=bhand_controller::Service::INIT_HAND;
效果相同。
2.原计划通过ros::service::call()实现调用,但总是调用不成功,机械手动作执行了但不能打印调用成功信息。调用代码如下:
if(ros::service::call("bhand_node/actions",test_action))
ROS_INFO("Init the robotic hand successfully!");
else
ROS_INFO("Failed to call action service!");
怀疑为第一个参数给的不正确,可能是名称问题,之前使用该函数名称使用的base name,此处为global name,不知道是不是相关,如果有相关研究者知道,还烦请告知,此处该如何调用。