源代码
有点长,放文末链接里了。

服务描述及代码
现在的服务是:请求时携带要前进的距离,然后底盘前进相应距离。代码如下,改动很小:

#!/usr/bin/env python

import rospy
from geometry_msgs.msg import Twist, Point
from math import copysign, sqrt, pow
import tf
from carry.srv import MoveTowards

class CalibrateLinear():
def __init__(self):
rospy.init_node('move_towards_server', anonymous=False)
service= rospy.Service('move_towards', MoveTowards, self.move)
def move(self,distanse_you_want):
print distanse_you_want.a
# Set rospy to execute a shutdown function when terminating the script
rospy.on_shutdown(self.shutdown)

# How fast will we check the odometry values?
self.rate = rospy.get_param('~rate', 20)
r = rospy.Rate(self.rate)

# Set the distance to travel
self.test_distance = rospy.get_param('~test_distance', distanse_you_want.a) # meters
self.speed = rospy.get_param('~speed', 0.15) # meters per second
self.tolerance = rospy.get_param('~tolerance', 0.01) # meters
self.odom_linear_scale_correction = rospy.get_param('~odom_linear_scale_correction', 1.0)
self.start_test = rospy.get_param('~start_test', True)

# Publisher to control the robot's speed
self.cmd_vel = rospy.Publisher('/cmd_vel', Twist, queue_size=5)

# The base frame is base_footprint for the TurtleBot but base_link for Pi Robot
self.base_frame = rospy.get_param('~base_frame', '/base_footprint')

# The odom frame is usually just /odom
#self.odom_frame = rospy.get_param('~odom_frame', '/odom')
self.odom_frame = rospy.get_param('~odom_frame', '/odom_combined')

# Initialize the tf listener
self.tf_listener = tf.TransformListener()

# Give tf some time to fill its buffer
rospy.sleep(2)

# Make sure we see the odom and base frames
self.tf_listener.waitForTransform(self.odom_frame, self.base_frame, rospy.Time(), rospy.Duration(60.0))

rospy.loginfo("Bring up rqt_reconfigure to control the test.")

self.position = Point()

# Get the starting position from the tf transform between the odom and base frames
self.position = self.get_position()

x_start = self.position.x
y_start = self.position.y

move_cmd = Twist()

while not rospy.is_shutdown():
# Stop the robot by default
move_cmd = Twist()

if self.start_test:
# Get the current position from the tf transform between the odom and base frames
self.position = self.get_position()

# Compute the Euclidean distance from the target point
distance = sqrt(pow((self.position.x - x_start), 2) +
pow((self.position.y - y_start), 2))

# Correct the estimated distance by the correction factor
distance *= self.odom_linear_scale_correction

# How close are we?
error = distance - self.test_distance

# Are we close enough?
if not self.start_test or abs(error) < self.tolerance:
self.start_test = False
params = {'start_test': False}
rospy.loginfo(params)
else:
# If not, move in the appropriate direction
move_cmd.linear.x = copysign(self.speed, -1 * error)
else:
self.position = self.get_position()
x_start = self.position.x
y_start = self.position.y
break

self.cmd_vel.publish(move_cmd)
r.sleep()

# Stop the robot
self.cmd_vel.publish(Twist(http://www.my516.com))
print 'finish moving'
return []

def get_position(self):
# Get the current transform between the odom and base frames
try:
(trans, rot) = self.tf_listener.lookupTransform(self.odom_frame, self.base_frame, rospy.Time(0))
except (tf.Exception, tf.ConnectivityException, tf.LookupException):
rospy.loginfo("TF Exception")
return

return Point(*trans)

def shutdown(self):
# Always stop the robot when shutting down the node
rospy.loginfo("Stopping the robot...")
self.cmd_vel.publish(Twist())
rospy.sleep(1)

if __name__ == '__main__':
try:
CalibrateLinear()
rospy.spin()
except:
rospy.loginfo("Calibration terminated.")
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
需要做的修改
1.添加一个srv
由于需要递交“向前移动的距离”,所以需要一个srv,类型是:请求是浮点数(前进的距离),相应可以为空。下面是我新建的MoveTowards.srv,很简单的两行,第一行是请求,第二行是分隔线,响应为空。

float32 a
---
1
2
至于如何创建一个srv,我就不写了,参考ROS wiki的链接。创建ROS消息和ROS服务.

2.对源程序进行的修改
首先import服务,注意格式:from “包名.srv” import “srv的名称”。虽然文件名为MoveTowards.srv但下面填import MoveTowards

from carry.srv import MoveTowards
1
然后是这一部分:

def __init__(self):
rospy.init_node('move_towards_server', anonymous=False)
service= rospy.Service('move_towards', MoveTowards, self.move)
def move(self,distanse_you_want):
1
2
3
4
以前“向前移动一米的代码段”在初始化内,我将其移动到了函数move内,而初始化只包含定义节点和service的语句。一旦有服务请求,将执行回调函数“move”。
注意以下一句话:

#self.odom_frame = rospy.get_param('~odom_frame', '/odom')
self.odom_frame = rospy.get_param('~odom_frame', '/odom_combined')
1
2
由于我们的底盘由robot_pose_ekf这个功能包做了传感器信息融合,发布的frame是/odom_combined而不是/odom,所以需要非常注意。可以使用rosrun rqt_tf_tree rqt_tf_tree 来查看tf树,看到底是哪一个。这一行错了,机器人是肯定不能动的。
然后还改了两个小地方,一些小细节:(标注了两个#的两行)

else:
self.position = self.get_position()
x_start = self.position.x
y_start = self.position.y
break ##

self.cmd_vel.publish(move_cmd)
r.sleep()

# Stop the robot
self.cmd_vel.publish(Twist())
print 'finish moving'
return [] ##
1
2
3
4
5
6
7
8
9
10
11
12
13
在底盘到达指定位置后,break跳出循环,源程序没有break,执行完后一直在while内,但我需要这个server返回一些信息,不然我的客户端程序一直在等待相应,程序一直阻塞没有往下执行。最后加了一行return,虽然返回的为“空”,但是你必须return一个东西,不然客户端不知道service是否执行完毕,导致程序阻塞。
---------------------

一个ROS的服务,使机器人向前移动指定距离的更多相关文章

  1. 重新封装了一下NODE-MONGO 使其成为一个独立的服务.可以直接通过get/post来操作

    # 重新封装了一下NODE-MONGO 使其成为一个独立的服务.可以直接通过get/post来操作 # consts.js 配置用的数据,用于全局参数配置 # log.js 自己写的一个简单的存储本地 ...

  2. ROS学习笔记三:编写第一个ROS节点程序

    在编写第一个ROS节点程序之前需要创建工作空间(workspace)和功能包(package).   1 创建工作空间(workspace) 创建一个catkin_ws: #注意:如果使用sudo一次 ...

  3. ROS和Gazebo进行机器人仿真(二)

    一.在Gazebo中使用ROS控制器 在本节中,我们将讨论如何在Gazebo中让机器人的每个关节运动. 为了让关节动起来,我们需要分配一个ROS控制器,尤其是,我们需要为每个关节连上一个与transm ...

  4. ROS和Gazebo进行机器人仿真(一)

    Gazebo是一种多机器人仿真器,可用于室内外机器人仿真.Gazebo在ROS中有良好的接口,包含ROS和Gazebo的所有控制. 若要实现ROS到Gazebo的通信,我们必须安装ROS-Gazebo ...

  5. ROS之服务

    服务(service)是另一种在节点之间传递数据的方法,服务其实就是同步的跨进程函数调用,它能够让一个节点调用运行在另一个节点中的函数. 我们就像之前消息类型一样定义这个函数的输入/输出.服务端(提供 ...

  6. 利用TCP 客户端---->服务端 传送文件到指定路径,并返回一个友好的回馈

    首先盲写的一个传输文件的方法,但测试发现了一个非常不容易发现的问题,这里先说明一下. 错误的代码如下: package com.TCP.java; import java.io.File; impor ...

  7. 创建一个ROS包

    先前笔者不知道catkin到底是个什么东东,后来终于在官方网站上找到了答案,原来catkin是ROS的一个官方的编译构建系统,是原本的ROS的编译构建系统rosbuild的后继者.catkin的来源有 ...

  8. ROS 创建服务和请求

    教程 维基 http://wiki.ros.org/cn/ROS/Tutorials 快速过程 创建包 $ cd ~/catkin_ws $ mkdir ~/catkin_ws/src $ cd ~/ ...

  9. [译]Spring Boot 构建一个RESTful Web服务

    翻译地址:https://spring.io/guides/gs/rest-service/ 构建一个RESTful Web服务 本指南将指导您完成使用spring创建一个“hello world”R ...

随机推荐

  1. Mysql net start mysql启动,提示发生系统错误 5 拒绝訪问 解决之道

    当前用户的操作权限太低了,出了问题 出错问题截屏例如以下: watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/4 ...

  2. struts2国际化---配置国际化全局资源文件并输出国际化资源信息

    我们首先学习怎么配置国际化全局资源文件.并输出资源文件信息 1.首先struts2项目搭建完毕后,我们在src文件夹下.即struts2.xml同级文件夹下创建资源文件.资源文件的名称格式为: XXX ...

  3. Oracle 闪回区满解决的方法

    闪回区满: OS: rm -rf [archivelog  autobackup  backupset  controlfile  flashback  onlinelog] eg : archive ...

  4. 性能测试实战-XYB项目-外网访问

    压测业务选择 跟产品.开发负责人评估系统中需要压测的重要业务接口 考虑到考勤业务是每天老师都需要做的且可多次考勤,列入压测重要业务中 值日检查也是每天老师都需要操作的业务,最终选择了考勤业务及值日检查 ...

  5. 从一个小demo开始,体验“API经济”的大魅力

    写在前面 “API经济”这个词是越来越火了,但是"API经济"具体指的是什么,相信很多人还没有个明确的认识.不过今天我可不打算长篇大论的去讲解一些概念,我们就以“电话号码归属地查询 ...

  6. cgi程序读取post发送的特殊字符,尤其适合于微信公众平台开发中发送被动消息

    [问题]用c编写cgi程序怎样取出html表单post来的数据? [分析]html表单post来的数据形如username="zhang"&&password=&q ...

  7. YTU 2734: 国家排序

    2734: 国家排序 时间限制: 1 Sec  内存限制: 128 MB 提交: 133  解决: 84 题目描述 世界格局动荡不安,10国紧急召开会议磋商对策.有些国家斤斤计较,参会代表的座位如何排 ...

  8. bzoj 1822 冷冻波

    题目大意: 在游戏中,巫妖是一种强大的英雄,它的技能Frozen Nova每次可以杀死一个小精灵 我们认为,巫妖和小精灵都可以看成是平面上的点. 当巫妖和小精灵之间的直线距离不超过R,且巫妖和小精灵的 ...

  9. bzoj 2333 [SCOI2011]棘手的操作 —— 可并堆

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2333 稍微复杂,参考了博客:http://hzwer.com/5780.html 用 set ...

  10. Coursera Algorithms Programming Assignment 4: 8 Puzzle (100分)

    题目原文:http://coursera.cs.princeton.edu/algs4/assignments/8puzzle.html 题目要求:设计一个程序解决8 puzzle问题以及该问题的推广 ...