Ros basics in 5 days project

why the reading from left and right laser are always very close in value and does not represent the true distance that i see in the gazebo simulation as iam sure they should be very different


import rospy
import time
from project.srv import FindWall , FindWallResponse
from geometry_msgs.msg import Twist
from sensor_msgs.msg import LaserScan

 
class my_node(object):

    def __init__(self):
        self.move_2 = Twist()
        self.left = 0 
        self.right = 0  
        self.front = 0 
        self.ready_point = 0 

    def callback_msg(self,msg):
        self.left = msg.ranges[715]
        self.right = msg.ranges[5]
        self.front = msg.ranges[360]
        self.ready_point = msg.ranges[270]
    
    
    def callback(self,request):

        r = rospy.Rate(4)
        rospy.loginfo("left distance"+str(self.left))
        rospy.loginfo("right distance"+str(self.right))
        rospy.loginfo("front distnace"+str(self.front))
        
        while ((self.left == 0) and (self.right == 0) and (self.front == 0)):
            rospy.sleep(1)

        rospy.loginfo('findwall service started...')
    
        if ((self.left < self.right) and (self.left < self.front)):

            rospy.loginfo("first case")
            left_1 = round(self.left , 1)
            front_1  = round(self.front , 1)
            while front_1 != left_1:
                rospy.loginfo('rotating left..')
                self.move_2.linear.x = 0
                self.move_2.angular.z = 0.5 #rotate to the left
                pub_s.publish(self.move_2)
                front_1  = round(self.front , 1)
                rospy.loginfo("current left distance"+str(left_1))
                rospy.loginfo("current front distance"+str(front_1))
                r.sleep()
    
                
            while self.front >= 0.3:
                rospy.loginfo("moving forward")
                self.move_2.linear.x = 0.1
                self.move_2.angular.z = 0
                pub_s.publish(self.move_2)
                r.sleep()

            while self.ready_point > 0.3:
                rospy.loginfo("trying to reach the start state (ready_point)")
                self.move_2.linear.x = 0
                self.move_2.angular.z = 0.5 #rotate to the left
                pub_s.publish(self.move_2)
                r.sleep()

    
        elif ((self.right < self.left) and (self.right < self.front)):

            rospy.loginfo("second case")
            right_1 = round(self.right , 1)
            front_1 = round(self.front , 1)

            while front_1 != right_1:

                rospy.loginfo("rotating right ..")
                self.move_2.linear.x = 0
                self.move_2.angular.z = -0.5 #rotate to the  right
                pub_s.publish(self.move_2)
                front_1 = round(self.front , 1)
                rospy.loginfo("current right distance"+str(right_1))
                rospy.loginfo("current front distance"+str(front_1))
                r.sleep()
            while self.front >= 0.3:

                rospy.loginfo("moving forward")
                self.move_2.linear.x = 0.08
                self.move_2.angular.z = 0
                pub_s.publish(self.move_2)
                r.sleep()
            while self.ready_point > 0.3:
                rospy.loginfo("trying to reach the start state (ready_point)")
                self.move_2.linear.x = 0
                self.move_2.angular.z = 0.5 #rotate to the left
                pub_s.publish(self.move_2)
                r.sleep()
    
        else:
            rospy.loginfo("third case")
    
            while self.front >= 0.3:
                rospy.loginfo("moving forward")
                self.move_2.linear.x = 0.1
                self.move_2.angular.z = 0
                pub_s.publish(self.move_2)
                r.sleep()

            while self.ready_point > 0.3:
                rospy.loginfo("trying to reach the start state (ready_point)")
                self.move_2.linear.x = 0
                self.move_2.angular.z = 0.5 #rotate to the left
                pub_s.publish(self.move_2)
                r.sleep()
                
        self.move_2.linear.x = 0
        self.move_2.angular.z = 0
        pub_s.publish(self.move_2)
    
        rospy.loginfo('findwall service finished..')
        message = FindWallResponse()
        message.wallfound = True
        return message
    


if __name__ == '__main__':
    rospy.init_node('service_node')
    my_object = my_node()
    sub_s = rospy.Subscriber("/scan" , LaserScan ,my_object.callback_msg)
    rospy.wait_for_message("/scan" , LaserScan)
    pub_s = rospy.Publisher('/cmd_vel' ,Twist , queue_size= 1 )
    FindWall_service = rospy.Service('/find_wall' , FindWall , my_object.callback)
    rospy.spin()




    

Hi @80601 ,

That is because, unlike in the robot that you used in the course that used 180 degree laser scanner with 0 - right, 360 - front and 719 - left, the turtlebot in rosject uses a 360 degree laser scanner that gives 0/719 - back, 180 - right, 360 - front and 540 - left.

Refer this post for more info: Incorrect Robot Scan Values in ROS Basics Course - Wall Follower Robot / TurtleBot3

Regards,
Girish

2 Likes

actually i do not know why but the front readings at 360 are totally wrong are you sure ?

Hi @80601 ,

I think I exactly know why you have this problem!

When I worked on this rosject, I found out that the 360 degree laser has 360 readings instead of 720, whereas the real robot TurtleBot has 720 readings for the laser.

You can verify this by doing ros2 topic echo /scan and cancel after you get at least one reading.
You will need to see three fields:

For a 360 degree laser with 0.5 degree angle increment you will have 720 values:

angle_min: -3.141590118408203
angle_max: 3.141590118408203
angle_increment: 0.008738775737583637   # equals 0.5 degrees

For a 360 degree laser with 1.0 degree angle increment you will have 360 values:

angle_min: -3.141590118408203
angle_max: 3.141590118408203
angle_increment: 0.017477551   # equals 1.0 degrees

So now you have two options (choose one, not both):

  1. Use a parameter setting in your program (launch file) to use laser scan ranges as 720 values for real robot and 360 values for simulation.
  2. Change the value of samples to 720 and resolution to 1 in the turtlebot3_burger.gazebo.xacro file that is located in the turtlebot3_description package. This will permanently change simulation robot’s laser scan values from 360 to 720.

I am certain this will solve your problem.

Regards,
Girish

i got this the readings seam to be 720 my service code act as expected but i think the problem starts with the wall following function :man_shrugging:

header:
  seq: 15
  stamp:
    secs: 13
    nsecs: 233000000
  frame_id: "base_scan"
angle_min: -3.1415998935699463
angle_max: 3.1415998935699463
angle_increment: 0.008738803677260876
time_increment: 0.0
scan_time: 0.0
range_min: 0.11999999731779099
range_max: 3.5

code for service

#! /usr/bin/env python

import rospy
import time
from project.srv import FindWall, FindWallResponse
from geometry_msgs.msg import Twist
from sensor_msgs.msg import LaserScan


class my_node(object):

    def __init__(self):
        self.move_2 = Twist()
        self.left = 0
        self.right = 0
        self.front = 0
        self.ready_point = 0

    def callback_msg(self, msg):
        self.left = msg.ranges[540]
        self.right = msg.ranges[180]
        self.front = msg.ranges[360]
        self.ready_point = msg.ranges[270]

    def callback(self, request):

        r = rospy.Rate(6)
        rospy.loginfo("left distance"+str(self.left))
        rospy.loginfo("right distance"+str(self.right))
        rospy.loginfo("front distnace"+str(self.front))

        while ((self.left == 0) and (self.right == 0) and (self.front == 0)):
            rospy.sleep(1)

        rospy.loginfo('findwall service started...')

        if ((self.left < self.right) and (self.left < self.front)):

            rospy.loginfo("first case")
            left_1 = round(self.left, 1)
            front_1 = round(self.front, 1)
            while front_1 != left_1:
                rospy.loginfo('rotating left..')
                self.move_2.linear.x = 0
                self.move_2.angular.z = 0.45  # rotate to the left
                pub_s.publish(self.move_2)
                front_1 = round(self.front, 1)
                rospy.loginfo("current left distance"+str(left_1))
                rospy.loginfo("current front distance"+str(front_1))
                r.sleep()

            while self.front >= 0.3:
                rospy.loginfo("moving forward")
                self.move_2.linear.x = 0.1
                self.move_2.angular.z = 0
                pub_s.publish(self.move_2)
                r.sleep()

            while self.ready_point > 0.3:
                rospy.loginfo("trying to reach the start state (ready_point)")
                self.move_2.linear.x = 0
                self.move_2.angular.z = 0.45  # rotate to the left
                pub_s.publish(self.move_2)
                r.sleep()

        elif ((self.right < self.left) and (self.right < self.front)):

            rospy.loginfo("second case")
            right_1 = round(self.right, 1)
            front_1 = round(self.front, 1)

            while front_1 != right_1:

                rospy.loginfo("rotating right ..")
                self.move_2.linear.x = 0
                self.move_2.angular.z = -0.45  # rotate to the  right
                pub_s.publish(self.move_2)
                front_1 = round(self.front, 1)
                rospy.loginfo("current right distance"+str(right_1))
                rospy.loginfo("current front distance"+str(front_1))
                r.sleep()
            while self.front >= 0.3:

                rospy.loginfo("moving forward")
                self.move_2.linear.x = 0.08
                self.move_2.angular.z = 0
                pub_s.publish(self.move_2)
                r.sleep()
            while self.ready_point > 0.3:
                rospy.loginfo("trying to reach the start state (ready_point)")
                self.move_2.linear.x = 0
                self.move_2.angular.z = 0.45  # rotate to the left
                pub_s.publish(self.move_2)
                r.sleep()

        else:
            rospy.loginfo("third case")

            while self.front >= 0.3:
                rospy.loginfo("moving forward")
                self.move_2.linear.x = 0.1
                self.move_2.angular.z = 0
                pub_s.publish(self.move_2)
                r.sleep()

            while self.ready_point > 0.3:
                rospy.loginfo("trying to reach the start state (ready_point)")
                self.move_2.linear.x = 0
                self.move_2.angular.z = 0.45  # rotate to the left
                pub_s.publish(self.move_2)
                r.sleep()

        self.move_2.linear.x = 0
        self.move_2.angular.z = 0
        pub_s.publish(self.move_2)

        rospy.loginfo('findwall service finished..')
        message = FindWallResponse()
        message.wallfound = True
        return message


if __name__ == '__main__':
    rospy.init_node('service_node')
    my_object = my_node()
    sub_s = rospy.Subscriber("/scan", LaserScan, my_object.callback_msg)
    rospy.wait_for_message("/scan", LaserScan)
    pub_s = rospy.Publisher('/cmd_vel', Twist, queue_size=1)
    FindWall_service = rospy.Service(
        '/find_wall', FindWall, my_object.callback)
    rospy.spin()
            rospy.loginfo("action successd")
            self.server.set_succeeded(self._result)


if __name__ == '__main__':
    rospy.init_node('action_node')
    record_odomClass()
    rospy.spin()

main code

#! /usr/bin/env python

import time
import rospy
from geometry_msgs.msg import Twist
from sensor_msgs.msg import LaserScan
from project.srv import FindWall, FindWallRequest
import actionlib
from project.msg import OdomRecordAction, OdomRecordGoal
from std_msgs.msg import Empty


####service####
rospy.init_node("project_node")
rospy.wait_for_service('/find_wall')
FindWall_service = rospy.ServiceProxy('/find_wall', FindWall)
result = FindWall_service(FindWallRequest())
print(result)

####acttion####
PENDING = 0
ACTIVE = 1
DONE = 2
WARN = 3
ERROR = 4
nImage = 1


def feedback_callback(feedback):
    print("feedback from action server totall distance moved so far\n"+str(feedback))


action_server_name = 'record_odom'
action_client = actionlib.SimpleActionClient(
    action_server_name, OdomRecordAction)
rospy.loginfo('Waiting for action Server '+action_server_name)
action_client.wait_for_server()
rospy.loginfo('Action Server Found...'+action_server_name)
action_client.send_goal(Empty(), feedback_cb=feedback_callback)
state_result = action_client.get_state()

rate = rospy.Rate(1)

rospy.loginfo("state_result: "+str(state_result))

####wall_following####

pub = rospy.Publisher("/cmd_vel", Twist, queue_size=1)
move = Twist()
rospy.loginfo("start wall fllowing")


def callback(msg):
    rospy.loginfo(msg.ranges[360])
    # perform wallfollower programm
    if msg.ranges[180] > 0.3 :
        # approach the wall slowly
        move.linear.x = 0.06
        move.angular.z = -0.09
        pub.publish(move)

    elif msg.ranges[180] < 0.2 :
        # get away from the wall slowly
        move.linear.x = 0.06
        move.angular.z = 0.09
        pub.publish(move)

    elif (2 > msg.ranges[180] > 0.3) and msg.ranges[360] > 0.5  :
        # keep moving forward
        move.linear.x = 0.06
        move.angular.z = 0
        pub.publish(move)

    elif msg.ranges[360] < 0.5:
        # turn left while moving forward
        move.linear.x = 0.06
        move.angular.z = 0.6
        pub.publish(move)
    
    state_result = action_client.get_state()
    if state_result == DONE:
        rospy.loginfo("the action is done succesfully")
        rospy.loginfo(action_client.get_result())


sub = rospy.Subscriber("/scan", LaserScan, callback)
rospy.wait_for_message("/scan", LaserScan)



rospy.spin()

Hi @80601 ,

I just went through your “Service” code. Long story short, your code will not work. You have some issues in your program, especially in the OOPS concept.
You must define Subscriber, Publisher and Service inside your my_node() object.
You have two if __name__ == "__main__": lines in your program.
The first one should be just def main(...). The second main function is correct.

Your “ServiceClient” code is fine, but it needs mode “beautification”, that is, rearranging of codes. It would be better if you can implement this as another class.

Regards,
Girish

This topic was automatically closed 5 days after the last reply. New replies are no longer allowed.