]> git.leonardobizzoni.com Git - pioneer-stm32/commitdiff
add serial node which is both transmitter and receiver
authorfdila <federicadilauro1998@gmail.com>
Tue, 14 Apr 2020 14:04:49 +0000 (16:04 +0200)
committerfdila <federicadilauro1998@gmail.com>
Tue, 14 Apr 2020 14:04:49 +0000 (16:04 +0200)
utils/catkin_ws/src/serial_bridge/scripts/serial_control.py [new file with mode: 0755]

diff --git a/utils/catkin_ws/src/serial_bridge/scripts/serial_control.py b/utils/catkin_ws/src/serial_bridge/scripts/serial_control.py
new file mode 100755 (executable)
index 0000000..fbff262
--- /dev/null
@@ -0,0 +1,138 @@
+#!/usr/bin/env python
+
+import time
+
+import serial
+from serial import SerialException
+
+import otto_communication_pb2
+from google.protobuf.message import DecodeError
+
+import math
+from math import sin, cos, pi
+
+import rospy
+from nav_msgs.msg import Odometry
+from geometry_msgs.msg import Point, Pose, Quaternion, Twist, Vector3
+import tf
+
+import numpy
+
+ser = serial.Serial(
+        baudrate=9600,
+        parity=serial.PARITY_NONE,
+        stopbits=serial.STOPBITS_ONE,
+        bytesize=serial.EIGHTBITS,
+        rtscts=True,
+        exclusive=None)
+
+def callback(data):
+    linear = data.linear.x
+    angular = data.angular.z
+    my_velocity = otto_communication_pb2.VelocityCommand()
+    my_velocity.linear_velocity = linear
+    my_velocity.angular_velocity = angular
+    rospy.logdebug('Cmd vel transmitted %f %f', linear, angular)
+    out_buffer = my_velocity.SerializeToString()
+    if(ser.cts == True):
+        ser.write(out_buffer)
+    else:
+        rospy.logwarn('ST not ready to receive velocity cmd')
+    ser.reset_output_buffer()
+    
+def controller():
+    rospy.init_node('serial_control', anonymous=True, log_level=rospy.DEBUG)
+    
+    serial_port = rospy.get_param("serial_port", "/dev/ttyUSB0")
+    #dtr is connected to RST, on opening dtr is high by default so it resets the st board
+    #after opening the serial port we set it low so the board can boot
+    ser.dtr = 0 
+    while(ser.is_open == False and not rospy.is_shutdown()):
+        try:
+            ser.port = serial_port
+            ser.open()
+        except SerialException:
+            rospy.logerr('Couldn\'t open ' + serial_port)
+            time.sleep(2)
+    
+    rospy.loginfo(serial_port + ' opened')
+
+    rospy.Subscriber('/cmd_vel', Twist, callback)
+
+    odom_pub = rospy.Publisher('/odom', Odometry, queue_size=10)
+    odom_broadcaster = tf.TransformBroadcaster()
+
+    otto_status = otto_communication_pb2.StatusMessage()
+    otto_status.linear_velocity = 0
+    otto_status.angular_velocity = 0
+    otto_status.delta_millis = 0
+    otto_status.status = 0
+
+    encoded_buffer = otto_status.SerializeToString()
+
+    status_length = len(encoded_buffer)
+
+    odom_values = numpy.array([0,0,0]) #x, y, th
+    icc_x = 0
+    icc_y = 0
+    radius = 0
+    current_time = rospy.Time.now()
+    
+    ser.reset_input_buffer()
+    while (not rospy.is_shutdown()):
+        encoded_buffer = ser.read(status_length)
+        try:
+            otto_status.ParseFromString(encoded_buffer)
+            rospy.logdebug(otto_status)
+            
+            # 3 = RUNNING
+            if (otto_status.status == 3):
+                lin_vel = otto_status.linear_velocity
+                ang_vel = otto_status.angular_velocity
+                d_time = otto_status.delta_millis
+                d_time = d_time / 1000.0
+                if(ang_vel != 0 and d_time > 0):
+                    radius = lin_vel / ang_vel
+                    icc_x = (odom_values[0] -radius*sin(odom_values[2]))
+                    icc_y = (odom_values[1] + radius*cos(odom_values[2]))
+                
+                    rotation_matrix = numpy.array([[cos(ang_vel*d_time), -sin(ang_vel*d_time), 0], 
+                                                    [sin(ang_vel*d_time), cos(ang_vel*d_time), 0], 
+                                                    [0, 0, 1]])
+                                                
+                    translate_icc_matrix = numpy.array([odom_values[0] - icc_x, 
+                                                        odom_values[1] - icc_y, 
+                                                        odom_values[2]])
+                
+                    translate_back_matrix = numpy.array([icc_x, 
+                                                        icc_y, 
+                                                        ang_vel*d_time])
+                
+                    odom_values = rotation_matrix.dot(translate_icc_matrix) + translate_back_matrix
+                    
+                elif(d_time > 0):
+                    odom_values = numpy.array([odom_values[0]+(cos(odom_values[2])*(lin_vel*d_time)), 
+                                                odom_values[1]+(sin(odom_values[2])*(lin_vel*d_time)), 
+                                                odom_values[2]])
+              
+                current_time = rospy.Time.now()
+                odom_quat = tf.transformations.quaternion_from_euler(0, 0, odom_values[2])
+                odom_broadcaster.sendTransform((odom_values[0], odom_values[1], 0.), odom_quat, current_time, "base_link", "odom")
+                odom = Odometry()
+                odom.header.stamp = current_time
+                odom.header.frame_id = "odom"
+
+                odom.pose.pose = Pose(Point(odom_values[0], odom_values[1], 0.), Quaternion(*odom_quat))
+
+                odom.child_frame_id = "base_link"
+                odom.twist.twist = Twist(Vector3(lin_vel, 0, 0), Vector3(0, 0, ang_vel))
+
+                odom_pub.publish(odom)
+
+        except DecodeError:
+            rospy.logerr("Decode Error")
+            ser.reset_input_buffer()
+
+
+if __name__ == '__main__':
+    controller()