Implementing PID to follow wall
My problem is 2-fold.
1 :
I am using move_base and successfully getting my robot model to autonomously navigate from one pose to another in a gazebo world. However, I am looking for a way to finetune the robots' path. Specifically, I want the model to travel close to the left or right wall, depending on which side I specify, maintaining a consistent predefined gap between the wall and robot.
I minimised my gazebo world to the following :
The laser currently has a distnce of 194.374211311 between the wall and the left side of the robot. I need the robot to travel alongside the wall with a seperating distance of 25. I tried accomplishing this with the following code :
#!/usr/bin/env python
import rospy
import math
from sensor_msgs.msg import LaserScan
from geometry_msgs.msg import Twist
import sys
class WallTracker :
data_left = 0
cdm_vel_publisher = ''
def __init__(self):
rospy.init_node('laser_ranging', anonymous=False)
self.cdm_vel_publisher = rospy.Publisher('/cmd_vel', Twist, queue_size=10)
rospy.Subscriber('scan_left', LaserScan, self.sample)
rospy.Subscriber("cmd_vel_original", Twist, self.move)
rospy.spin()
def sample(self, data):
cleanedData = filter(lambda x: not math.isinf(x), data.ranges)
self.data_left = sum(cleanedData)
def move(self, twist):
rospy.loginfo('RANGING LEFT : ' + str(self.data_left))
rospy.loginfo(twist)
new_twist = Twist()
new_twist = twist
rospy.loginfo(new_twist)
limit = 20
# Also tried ...
new_twist.linear.x = twist.linear.x
new_twist.linear.y = twist.linear.y
new_twist.linear.z = twist.linear.z
new_twist.angular.x = twist.angular.x
new_twist.angular.y = twist.angular.y
# new_twist.angular.z = twist.angular.z
if(self.data_left > limit):
new_twist.angular.z = 1
rospy.loginfo('Data-Left['+str(self.data_left)+'] > ' + str(limit))
else:
new_twist.angular.z = 0
rospy.loginfo('Data-Left['+str(self.data_left)+'] < ' + str(limit))
self.cdm_vel_publisher.publish(new_twist)
if __name__ == "__main__":
WallTracker()
I am basically trying to amend the angular.z value of the twist from cmd_vel. The idea is to allow the robot to continue it's movement while turning it to the left and bringing it closer to the wall.
BUT, I find the robot only turns in place.
From the terminal output, it seems my attempt to duplicate the twist data as generated by move_base has failed and only my angular.z data is in my newly created and published twist data.
Echoing out the cmd_vel topic bears me out. When I commentout the entire if-statement, I have linear.x data coming from move_base. But with the if-statement that linear.x value is absent.
2 :
How can I implement a PID to get the robot model to accurately drive alongside the wall ?
Are you updating
data_left
? If it's always spinning then it seems to be always greater thanlimit
. Is this the entirety of the code that you're using? If not, please update your question with all of the code that you're using@jayess:
data_left
is the total of all the numbers on thescan_left
topic having removed all inf occurances. The closer the robot moves towards the wall, the smaller data_left becomes.The twist messages in the GIF seem to be constant and have
angular.z = 1
--even at the end, when the robot stops turning. It seems that value isn't coming from your code. Do you know what's generating it?On a side note, you should probably not create the
Publisher()
inmove()
if you're calling it often. Usually, one would create thePublisher()
as a member of a class when initializing the node. Then other class methods can publish as needed.@tryan: Thanks. I refactored my code into a class so the publisher object is created as the instance of my class is being initiated. As for the
angular.z=1
issue, I noticed it but I honestly don't know where it coming from. It does seem to be coming from the same code however. If I commen out my if-statement and the preceeding twist assignement code, I don't get angular.z = 1Run
to see what other nodes are publishing to that topic
@jayess: Only my node is publishing to
cmd_vel
. This is VERY strange because the else section of my if statement should be settingangular.z
to 0. But I am now getting -1 or 1 as observered by @tryan.I see now.
rospy.loginfo(new_twist)
is printingnew_twist = twist
before you modify it, so it seems that's just the value coming from/cmd_vel
. You can echo/cmd_vel
directly to confirm. If that is the case, then there's no non-zero components besidesangular.z
, so I would expect your robot to spin like it's doing. Further, in the GIF, the robot does stop when the limit is reached, so it's probably getting the correct message (angular.z = 0
). All that's left then is to figure out why/cmd_vel
isn't what you think it should be.