forked from tue-robotics/pico_base_controller
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathomnibase.py
executable file
·135 lines (113 loc) · 3.55 KB
/
omnibase.py
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
124
125
126
127
128
129
130
131
132
133
134
135
#!/usr/bin/env python
import rospy
import roslib; #roslib.load_manifest('pico_base_controller')
import serial
from geometry_msgs.msg import Quaternion
from geometry_msgs.msg import Twist
from geometry_msgs.msg import Pose
from nav_msgs.msg import Odometry
from math import sin, cos
import re
#from tf.broadcaster import TransformBroadcaster
import tf
from tf.transformations import vector_norm
from tf.transformations import numpy as np
class OmniBase():
regex = re.compile('(-?\d+\.\d+) (-?\d+\.\d+) (-?\d+\.\d+)')
ser = serial.Serial('/dev/ttyArduino0', 115200)
max_speed_linear = 0.5
max_speed_angular = 1.2
max_speed_error = 0.01 # speed may be 1% greater than the maximum
def velocityCallback(self, vel):
self.vel = vel
def sendReference(self, vel):
# cap linear speed
l = vel.linear
v = np.array([l.x, l.y, l.z])
speed = vector_norm(v)
if speed > self.max_speed_linear * (1 + self.max_speed_error):
rospy.logwarn('maximum linear speed exceeded with %f m/s, capping to %f m/s' % (speed, self.max_speed_linear))
v = v / speed * self.max_speed_linear
# cap angular speed
a = vel.angular.z
if np.abs(a) > self.max_speed_angular * (1+ self.max_speed_error):
rospy.logwarn('maximum angular speed exceeded with %f rad/s, capping to %f rad/s' % (a, self.max_speed_angular))
a = a / abs(a) * self.max_speed_angular
self.ser.write("<%f,%f,%f>\n"%(v[0], v[1], a))
def __init__(self):
rospy.init_node("omni_base");
rospy.Subscriber("cmd_vel", Twist, self.velocityCallback)
r = rospy.Rate(200.0) # 200hz
odomPub = rospy.Publisher('/pico/odom', Odometry)
odomBroadcaster = tf.TransformBroadcaster()
#print "vel callback"
now = rospy.Time.now()
x = 0.0
y = 0.0
th = 0.0
x_robot_last = 0.0
x_robot = 0.0
y_robot_last = 0.0
y_robot = 0.0
th_robot_last = 0.0
th_robot = 0.0
self.vel = None
ref_freq = 10
ref_dt = rospy.Duration(1.0 / ref_freq)
ref_t = rospy.Time.now()
while not rospy.is_shutdown():
just = now
now = rospy.Time.now()
dt = (now - just).to_sec()
if self.vel and ref_t + ref_dt < now:
self.sendReference(self.vel)
self.vel = None
ref_t = now
#print dt
s = self.ser.readline()
result = self.regex.match(s)
if result and dt > 0.0:
x_robot_last = x_robot
y_robot_last = y_robot
th_robot_last = th_robot
x_robot = float(result.group(1))
y_robot = float(result.group(2))
th_robot = float(result.group(3))
vx = (x_robot - x_robot_last)/dt
vy = (y_robot - y_robot_last)/dt
vth = (th_robot - th_robot_last)/dt
dx = (vx * cos(th) - vy * sin(th)) * dt;
dy = (vx * sin(th) + vy * cos(th)) * dt;
dth = vth * dt;
x += dx;
y += dy;
th += dth;
q = tf.transformations.quaternion_from_euler(0.0, 0.0, th)
quaternion = Quaternion(q[0], q[1], q[2], q[3])
# Create the odometry transform frame broadcaster.
odomBroadcaster.sendTransform(
(x, y, 0.0),
(q[0], q[1], q[2], q[3]),
now,
"/pico/base_link",
"/pico/odom"
)
odom = Odometry()
odom.header.frame_id = "/pico/odom"
odom.child_frame_id = "/pico/base_link"
odom.header.stamp = now
odom.pose.pose.position.x = x
odom.pose.pose.position.y = y
odom.pose.pose.position.z = 0.0
odom.pose.pose.orientation = quaternion
odom.twist.twist.linear.x = vx
odom.twist.twist.linear.y = vy
odom.twist.twist.angular.z = vth
#print 'odom: %f %f %f' % (x, y, th)
#print odom
odomPub.publish(odom)
r.sleep()
if __name__ == '__main__':
try:
OmniBase()
except rospy.ROSInterruptException: pass