ROS Resources: Documentation | Support | Discussion Forum | Index | Service Status | ros @ Robotics Stack Exchange
Ask Your Question
0

ROS python script for Kangaroo x2 sabertooth 2x32 configuration . Accepts cmd_vel and publishes /odom

asked 2018-02-05 01:45:33 -0500

updated 2018-02-07 01:15:09 -0500

Below is the code which will accept (cmd_vel ) and publish (odom). I am using a Sabertooth 2x32 + Kangaroo x2 configuration . My robot is a differential drive robot .

I am communicating to Kangaroo vai an Arduino .

The below command will drive all the wheels in through 1 full rotation (clockwise 360 degrees)

D:100

The below command will turn the robot 90degrees from the stand still position .

T:100

How would i publish the odom for such a robot .

PS :- I have gone through the http://wiki.ros.org/differential_drive . kangaroo works like a servo motor , it accepts the command and sets the wheels to that particular position , i am not currently getting the real time encoder feedback .

I have the basic python skeleton ready ,below is the code .

#!/usr/bin/env python
from time import sleep
import serial
import rospy
import tf
from nav_msgs.msg import Odometry
from geometry_msgs.msg import Point, Pose, Quaternion, Twist, Vector3
import serial.tools.list_ports as port
from math import sin, cos, pi

class Kangaroo:
def __init__(self, debug=False, ser=None):
    self.debug = debug
    self.source = None
    self.status = True
    self.ser = ser
    self.Drive = "&T:10!"
    self.drive_sum = 0
    self.Turn = "&S:10!"
    self.turn_sum = 0
    self.speed = 200
    self.angle = 100
    self.changed = True
    self.x = 0.0
    self.y = 0.0
    self.th = 0.0
    self.vx = 0.1
    self.vy = -0.1
    self.vth = 0.1
    self.r = 0
    print "\nInit kangaroo x2....\n"
    print "\nDetecting kangaroo x2....\n"
    portlist = list(port.comports())
    #print portlist
    address = ''
    for p in portlist:
        print p
        if ' USB2.0-Serial' in str(p):
            self.address = str(p).split(" ")
            print "\nAddress found @"
            print self.address[0]
    self.ser = serial.Serial(self.address[0], 115200, timeout=2,writeTimeout=5)
    print self.ser.readline()

def callback(self, data ):
   order = True
   drive = data.linear.x * 50
   turn = -data.angular.z * 50
   self.drive_sum =  drive
   self.Drive = "&D:" + str(int(self.drive_sum)) +"!"
   self.turn_sum =  turn
   self.Turn = "&T:" + str(int(self.turn_sum))+ "!"
   if((int(drive) or int(turn) )):
      print data
      self.send_cmd_to_arduino(self.Drive, self.Turn ,self.drive_sum , self.turn_sum)

# translate x, and angular velocity to PWM signal of each wheels, and send to arduino
def send_cmd_to_arduino(self, x, angular , drive ,turn):
    message = "{}  {}".format(x,angular)
    print message
    if (abs(drive) > abs(turn)):
        self.ser.write(x )
    else:
        self.ser.write(angular )
            last_time = rospy.Time.now()
            self.Odom(last_time)

def get_arduino_message(self):
    pub = rospy.Publisher('arduino', String, queue_size=10)
    r = rospy.Rate(10)
    while not rospy.is_shutdown():
        message = self.ser.readline()
        pub.publish(message)
        r.sleep()   



def Odom(self,last_time ):
    x = self.x
    y = self.y
    th = self.th
    vx = self.vx
    vy = self.vy
    vth = self.vth
    current_time = rospy.Time.now()
    dt = (current_time - last_time).to_sec()
    delta_x = (vx * cos(th) - vy * sin(th)) * dt
    delta_y = (vx * sin(th) + vy * cos(th)) * dt
    delta_th = vth * dt
    x += delta_x
    y += delta_y
    th += delta_th
    odom_quat = tf.transformations.quaternion_from_euler(0, 0, th)
    self.odom_broadcaster.sendTransform(
        (x, y, 0.),
        odom_quat,
        current_time,
        "base_link",
        "odom"
    )
    odom = Odometry ...
(more)
edit retag flag offensive close merge delete

Comments

I see an Odometry publisher in your code, does it not work?

lucasw gravatar image lucasw  ( 2018-02-05 11:51:53 -0500 )edit

Nope its not publishing anything , i tried "rostopic echo /odom" , but its empty .

chris_sunny gravatar image chris_sunny  ( 2018-02-05 21:36:24 -0500 )edit

Thanks , clock was not published , that was the issue.

chris_sunny gravatar image chris_sunny  ( 2018-02-07 01:16:11 -0500 )edit

1 Answer

Sort by ยป oldest newest most voted
1

answered 2018-02-06 09:23:23 -0500

lucasw gravatar image

It's possible your indents didn't cut and paste properly because the following should generate an unexpected indent error:

def send_cmd_to_arduino(self, x, angular , drive ,turn):
    message = "{}  {}".format(x,angular)
    print message
    if (abs(drive) > abs(turn)):
        self.ser.write(x )
    else:
        self.ser.write(angular )
            last_time = rospy.Time.now()
            self.Odom(last_time)

But if corrected to

    if (abs(drive) > abs(turn)):
        self.ser.write(x )
    else:
        self.ser.write(angular )
    last_time = rospy.Time.now()
    self.Odom(last_time)

then the odom publisher works.

There might be a couple other indent issues also, I corrected them and tried it out with socat:

socat -d -d pty,raw,b115200,link=$HOME/tmp/ttyUSB0,echo=0 pty,raw,b115200,link=$HOME/tmp/ttyUSB1,echo=0

and hardcoded self.address to tmp/ttyUSB0 to make it run, and the odom publisher worked when I published a Twist to cmd_vel.

edit flag offensive delete link more

Question Tools

1 follower

Stats

Asked: 2018-02-05 01:45:33 -0500

Seen: 987 times

Last updated: Feb 07 '18