Turtlebot line follower

Date Mon 16 December 2013
 

from scratch. So now the turtlebot is running a version of ROS Fuerte and I have the newest verson of ROS Hydro on a virtual box for my workstation. I put together a simple line following program to test everything out. You can follow along to create your own or just grab the completed project from my github repo.

One new thing I ran into is that creating packages with Hydro is a little different than before. You still use the same arguments but this time create a new package using catkin_create_package. The package we will make is going to use std_msgs, rospy, and the turtlebot_node. To do this move into your working directory and run the following

catkin_create_pkg line_follower std_msgs rospy turtlebot_node

Use roscreate_pkg if you are still on an older version of ROS. You should have a line_follower directory in you workspace now. Move to that directory and create a nodes folder. In the nodes folder we will create the actual python program that will run the robot.

import roslib; roslib.load_manifest('line_follower')
import rospy
from geometry_msgs.msg import Twist
from turtlebot_node.msg import TurtlebotSensorState

#global
turn = 0.0

    def processSensing(TurtlebotSensorState):
    global turn

    # turn right if we set off the left cliff sensor
    if( TurtlebotSensorState.cliff_left_signal > 1100 ):
                turn = 2
    # turn left if we set off the right cliff sensor
    if( TurtlebotSensorState.cliff_right_signal > 900 ):
                turn = -2

def run():

    # publish twist messages to /cmd_vel
    pub = rospy.Publisher('/cmd_vel', Twist)

    #subscribe to the robot sensor state
    rospy.Subscriber('/turtlebot_node/sensor_state', TurtlebotSensorState, processSensing)
    rospy.init_node('Line_Follower')

    global turn
    twist = Twist()

    while not rospy.is_shutdown():

        # turn if we hit the line
        if ( turn != 0.0 ):
            str = "Turning %s"%turn
            rospy.loginfo(str)
            twist.linear.x = 0.2; twist.linear.y = 0; twist.linear.z = 0
            twist.angular.x = 0; twist.angular.y = 0; twist.angular.z = turn
            turn = 0.0

            # straight otherwise
        else:
            str = "Straight %s"%turn
            rospy.loginfo(str)
            twist.linear.x = 0.2; twist.linear.y = 0; twist.linear.z = 0
            twist.angular.x = 0; twist.angular.y = 0; twist.angular.z = 0

            # send the message and delay
        pub.publish(twist)
        rospy.sleep(0.1)

if __name__ == '__main__':
    try:
        run()
    except rospy.ROSInterruptException: pass

It's pretty simple but here's a quick rundown of how it works. First we need the standard line of imports. Be sure to include the twist to send commands to the robot and the robot's sensor state which we will use to read the IR cliff sensors.

import roslib; roslib.load_manifest('line_follower')
import rospy
from geometry_msgs.msg import Twist
from turtlebot_node.msg import TurtlebotSensorState

Then we declare a global variable called "turn". This will store the angular rate that we want the robot to turn at.

The processSensing function checks the left and right cliff sensors against a calibrated number. This just sets the turning variable to a positive or negative number based on which cliff sensor is being triggered.

def processSensing(TurtlebotSensorState):
global turn

    # turn right if we set off the left cliff sensor
if( TurtlebotSensorState.cliff_left_signal > 1100 ):
            turn = 2
    # turn left if we set off the right cliff sensor
if( TurtlebotSensorState.cliff_right_signal > 900 ):
            turn = -2

To get correct value you will have to experiment with the sensors to see what values it give on a carpet or tape surface. To check your sensor values you can use rostopic. In a terminal window first check to see that the robot is running by checking

rostopic list

You should see topics from turtlebot_node in there. After that you can see the sensor states for the robot by running

rostopic list echo /turtlebot_node/TurtlebotSensorState

In the sensor state output look for values for the left and right cliff sensors. Then put the robot on different surfaces and note the change in values. Once we use the processSensing function to check our cliff sensor values and set the appropriate turning value we can actually send the twist message.

if ( turn != 0.0 ):
    str = "Turning %s"%turn
    rospy.loginfo(str)
    twist.linear.x = 0.2; twist.linear.y = 0; twist.linear.z = 0
    twist.angular.x = 0; twist.angular.y = 0; twist.angular.z = turn
    turn = 0.0

This sends the robot a linear twist message or 0.2 and an angular twist based on the turn variable we set earlier.

Here's the final program in action

Comments !

comments powered by Disqus