Part two of the ros basics project

Hello
I am doing my first project of ROS basics in 5 days,
My problem is that I can not figure that what part of the code for section 2 should change, anyway my code does not call service properly.
following is my python and lunch file

#! /usr/bin/env python

import rospy
from turtlebot3_move.srv import MoveInSquare, MoveInSquareResponse
from geometry_msgs.msg import Twist
from sensor_msgs.msg import LaserScan
import time


class RobotClass():
    def __init__(self):
        rospy.init_node('move_in_square_server', anonymous=True)
        cmd_vel_topic = '/cmd_vel'
        self.vel_publisher = rospy.Publisher(
            cmd_vel_topic, Twist, queue_size=1)
        self.cmd = Twist()
        self.laser_subscriber = rospy.Subscriber(
            '/scan', LaserScan, self.laser_callback)

        self.ctrl_c = False
        self.rate = rospy.Rate(1)
        rospy.on_shutdown(self.shutdownhook)


    def publish_once_in_cmd_vel(self):
        while not self.ctrl_c:
            connections = self.vel_publisher.get_num_connections()
            if connections > 0:
                self.vel_publisher.publish(self.cmd)
                #rospy.loginfo("Cmd Published")
                break
            else:
                self.rate.sleep()

    def shutdownhook(self):
        # works better than the rospy.is_shutdown()
        self.ctrl_c = True

    def laser_callback(self, msg):
        self.laser_msg = msg

    def get_front_laser(self):
        time.sleep(1)
        d = int((len(self.laser_msg.ranges))/2)
        return self.laser_msg.ranges[d]

    def stop_robot(self):
        self.cmd.linear.x = 0.0
        self.cmd.angular.z = 0.0
        self.publish_once_in_cmd_vel()

    def move_straight_time(self, motion, speed, time):
        self.cmd.linear.y = 0
        self.cmd.linear.z = 0
        self.cmd.angular.x = 0
        self.cmd.angular.y = 0
        self.cmd.angular.z = 0

        if motion == "forward":
            self.cmd.linear.x = speed
        elif motion == "backward":
            self.cmd.linear.x = - speed

        i = 0
        while (i <= time):
            self.vel_publisher.publish(self.cmd)
            i += 1
            self.rate.sleep()
        self.stop_robot()

        s = "Moved robot " + motion + " for " + str(time) + " seconds"
        return s

    def turn(self, clockwise, speed, time):
        self.cmd.linear.x = 0
        self.cmd.linear.y = 0
        self.cmd.linear.z = 0
        self.cmd.angular.x = 0
        self.cmd.angular.y = 0

        if clockwise == "clockwise":
            self.cmd.angular.z = -speed
        else:
            self.cmd.angular.z = speed

        i = 0
        while (i <= time):
            self.vel_publisher.publish(self.cmd)
            i += 1
            self.rate.sleep()

        self.stop_robot()
        s = "Turned robot " + clockwise + " for " + str(time) + " seconds"
        return s

    def my_callback(self, request):
        print("callback called")
        i = 0
        while i < 4:
            print("callback called")
            self.move_straight_time("forward", 0.15/5, 5)
            self.turn("clockwise", 0.33, 5)

            if (self.get_front_laser()) < 0.2:
                self.stop_robot()
                print("obstcle")
                raise Exception
                
            i += 1
        self.stop_robot()
        
        response = MoveInSquareResponse()
        response.complete = True
        return response  # the service Response class, in this case EmptyResponse

    

if __name__ == '__main__':

    robotcontrol_object = RobotClass()
    try:
        robotcontrol_object.move_straight()

    except rospy.ROSInterruptException:
        pass

obj = RobotClass()
my_service = rospy.Service('/move_in_square', MoveInSquare, obj.my_callback)
rospy.spin()


Launch file

<launch>
    <!-- Start Service Server for move_in_square service -->
    <node pkg="turtlebot3_move" type="Service_server.py" name="move_in_square_server" output="screen">
    </node>
</launch>

It looks like you have an indentation issue in your __main__ when you include the service server, and that is probably why you don’t see the service being offered after running the node. You are also calling the object RobotClass() twice which may cause problems

You should try to add the service server into the _init_ function and try it like that. Remember to start as simple as possible (i.e. a node with only a service server) and move on from then. Otherwise it becomes hard to spot errors

Hey, actually I changed it but I am totally confused with different parts of the project, regarding the first and second part I wrote following codes.
when I launch the launch file related to service and then call the service it works properly,
but when I launch the same launch file and then start launch file of the client (related to part 1 of the quiz) it does not work.
could you please take a look and help me out.

<launch>
    <node pkg="turtlebot3_move" type="turtlebot3_sub_pub.py" name="topics_node" output="screen" />
</launch>
#!/usr/bin/env python

import rospy
from geometry_msgs.msg import Twist
from sensor_msgs.msg import LaserScan
import time    
from turtlebot3_move.srv import MoveInSquare, MoveInSquareRequest

rospy.init_node('topics_node')   
rospy.wait_for_service('/move_in_square') 
service_client = rospy.ServiceProxy('/execute_move_in_square', MoveInSquare) 
request_object = MoveInSquareRequest() 
res=service_client(request_object)

def laser_callback(msg):
    print(len(msg.ranges))
    d=int((len(msg.ranges))/2)

    if msg.ranges[d]>0.2:
        cmd.linear.x=0.1 
        cmd.angular.z=0
        pub.publish(cmd)

    if msg.ranges[d]<0.2:
        cmd.linear.x=0
        cmd.angular.z=0
        pub.publish(cmd)
        print("Oops there is an obstacle in front...")


pub = rospy.Publisher('/cmd_vel', Twist, queue_size=1) 
cmd=Twist()
pub.publish(cmd)
rate=rospy.Rate(2)  

sub= rospy.Subscriber('/scan', LaserScan, laser_callback)
ls=LaserScan() 
rospy.spin()

<launch>

    <!-- Start Service Server for move_in_square service -->

    <node pkg="turtlebot3_move" type="service.py" name="move_in_square_server" output="screen">

    </node>

</launch>
#! /usr/bin/env python

from turtlebot3_move.srv import MoveInSquare, MoveInSquareResponse
import rospy
import time
from geometry_msgs.msg import Twist
from sensor_msgs.msg import LaserScan
#from Service_server import RobotClass

# obj=RobotClass()

def laser_callback(msg):
    print(len(msg.ranges))
    d = int((len(msg.ranges))/2)

    if msg.ranges[d] < 0.2:
        cmd.linear.x = 0
        cmd.angular.z = 0
        pub.publish(cmd)
        print("there is an obstacle in front...")
        rospy.ROSInterruptException()


def my_callback(request):
    i = 0
    while i < 4:
        print("this is stage ", i)
        print("forward")
        cmd.linear.x = (0.15)/5
        cmd.angular.z = 0
        pub.publish(cmd)
        rospy.sleep(5)

        print("Rotate")
        cmd.linear.x = 0
        cmd.angular.z = 0.33
        pub.publish(cmd)
        rospy.sleep(5)
        i += 1
    print("stop")
    cmd.linear.x = 0
    cmd.angular.z = 0
    pub.publish(cmd)
    rospy.sleep(5)

    response = MoveInSquareResponse()
    response.complete = True
    return response


rospy.init_node('move_in_square_server')
myservice = rospy.Service('/move_in_square', MoveInSquare, my_callback)

pub = rospy.Publisher('/cmd_vel', Twist, queue_size=1)
while pub.get_num_connections() < 1:
    pass
cmd = Twist()
sub = rospy.Subscriber('/scan', LaserScan, laser_callback)
ls = LaserScan()
rate = rospy.Rate(2)
rospy.spin()

Hi, again, I don’t know if you are not sharing the whole program but you don’t have a main function (in neither of your scripts), and you are declaring your client right in the beginning. I would recommend putting it into a function (like the laser callback) and call that function in your main.