ROS Basics Section 2 services

Hello sir.

I saw a post where a user asked about multithreading concept.

THE QUERY

I have been struggling since many weeks to solve the Services section of ROS Basics in 5 days course, not able to move ahead in the course since then. Can you please help me out sir? I tried copying the code written by the user and editing it. I replaced rclpy with rospy . I thought rclpy is used for ROS2.

# import the Empty module from std_servs service interface
#from std_srvs.srv import Empty
from topics_section_1.srv import FindWall
# import the Twist module from geometry_msgs messages interface
from geometry_msgs.msg import Twist
# import the ROS2 python client libraries
import rospy
'''import rclpy
from rclpy.node import Node
from rclpy.qos import ReliabilityPolicy, QoSProfile'''
from sensor_msgs.msg import LaserScan
from rospy.callback_groups import MutuallyExclusiveCallbackGroup

class FindwallService(Node):

    def __init__(self):

        # Multithreading 
        self.group1 = MutuallyExclusiveCallbackGroup()
        self.group2 = MutuallyExclusiveCallbackGroup()
# defines the type, name and callback function
        self.srv = self.create_service(FindWall, '/find_wall', self.Empty_callback, callback_group=self.group1)        


class FindwallService(Node):

    def __init__(self):
        # Here we have the class constructor

        # call the class constructor to initialize the node as service_moving
        super().__init__('find_wall')
        # create the service server object
        # defines the type, name and callback function
        self.srv = self.create_service(FindWall, 'find_wall', self.Empty_callback)
        # create the publisher object
        # in this case the publisher will publish on /cmd_vel topic with a queue size of 10 messages.
        # use the Twist module
        self.publisher = self.create_publisher(Twist, 'cmd_vel', 10)
        
        self.subscriber = self.create_subscription(LaserScan,'/scan', self.listener_callback, QoSProfile(depth=10, reliability=ReliabilityPolicy.BEST_EFFORT))
        
        self.subscriber

        self.laser_front = 0
        self.laser_right = 0

            
        

    def Empty_callback(self, request, response):
        # The callback function recives the self class parameter, 
        # received along with two parameters called request and response
        # - receive the data by request
        # - return a result as response


        near_wall = False

        vel = Twist()

        while near_wall == False:
            self.get_logger().info("Front distance %s" %str(self.laser_front))
            self.get_logger().info("Right distance %s" %str(self.laser_right))

            if self.laser_front > 0.5:
                self.get_logger().info("Vel = 0.2")
                vel.linear.x = 0.2
                publisher.publish(vel)

            elif self.laser_front < 0.5 and self.laser_front > 0.1:
                self.get_logger().info("Vel = 0.1")
                vel.linear.x = 0.1
                publisher.publish(vel)

            else:
                vel.linear.x = 0
                publisher.publish(vel)
                near_wall = True
                self.get_logger().info("Near the wall")
                response.wallfound = True
                break

            
            self.get_logger().info("Publishig speed")
        
        # return the response parameter
        return response


    def listener_callback (self, laser):

        self.get_logger().info("Reading")


        self.laser_front = laser.ranges[0]
        self.laser_right = laser.ranges[120]

        #self.get_logger().info("Front distance %s" %str(self.laser_front))
        #self.get_logger().info("Right distance %s" %str(self.laser_right))

        



def main(args=None):
    # initialize the ROS communication
    rospy.init(args=args)

    try:
    # declare the node constructor
        findwall_service = FindwallService()

        executor = MultiThreadedExecutor(num_threads=2)
        executor.add_node(findwall_service)

        try:
            # pause the program execution, waits for a request to kill the node (ctrl+c)
            executor.spin()
        finally:
            executor.shutdown()
            findwall_service.destroy_node()

    finally:
        # shutdown the ROS communication
        rospy.shutdown()

if __name__ == '__main__':
    main()

But still it gives the following errors :

from: can't read /var/mail/geometry_msgs.msg
/home/user/catkin_ws/src/topics_section_1/scripts/find_wall_server.py: line 7: import: command not found
/home/user/catkin_ws/src/topics_section_1/scripts/find_wall_server.py: line 10: $'import rclpy\nfrom rclpy.node import Node\nfrom rclpy.qos import ReliabilityPolicy, QoSProfile': command not found
from: can't read /var/mail/sensor_msgs.msg
from: can't read /var/mail/rospy.callback_groups
/home/user/catkin_ws/src/topics_section_1/scripts/find_wall_server.py: line 14: syntax error near unexpected token `('
/home/user/catkin_ws/src/topics_section_1/scripts/find_wall_server.py: line 14: `class FindwallService(Node):'

I find sometimes a huge gap between what we are taught in the course and what we are expected to do in the project. Maybe my perception is wrong. I donā€™t have any other source where i get to understand ROS. Many days are just wasted when I am stuck at any point. :no_mouth:

Hi @arjun2312 , i have not worked a lot with rclpy, so i think its best if i forward this to people who are better equiped in this. They will surely help you out.

I have forwarded this to @bayodesegun

1 Like

I also found a similar query but in C++.

THE QUERY

The code used here in C++ is this one. But still I donā€™t know how to convert it in python ROS1.

#include <ros/ros.h>
#include <geometry_msgs/Twist.h>
#include
#include <sensor_msgs/LaserScan.h>
#include <server_turtle_wall/FindWall.h>
using namespace std;

ros::Publisher pub;
geometry_msgs::Twist vel;
vector rays;

int count = 0;
int min_ct = 10000;
float min_ray = 10000;
bool is_min = 0;

// Laser scan subscriber
void laserCallback(const sensor_msgs::LaserScan::ConstPtr &msg) {
rays = msg->ranges;
}

// Find wall service
bool my_callback(server_turtle_wall::FindWall::Request &req, server_turtle_wall::FindWall::Response &res) {

ROS_INFO(ā€œFinding Wallā€¦ā€);
ros::Rate rate(1);

while ((min_ct > 185) || (min_ct < 175)) {
min_ray = *min_element(rays.begin(), rays.end());
min_ct = min_element(rays.begin(), rays.end()) - rays.begin();
if (min_ct > 185) {
vel.angular.z = 0.1;
} else if (min_ct < 185) {
vel.angular.z = -0.1;
} else {
vel.angular.z = 0;
}
pub.publish(vel);
rate.sleep();
ROS_INFO(ā€œRunning:ā€);
ROS_INFO(ā€œThe minimum ray occurs at %i and is a distance of %f.ā€, min_ct, min_ray);
}

vel.angular.z = 0;
pub.publish(vel);

ROS_INFO(ā€œThe minimum ray occurs at %i and is a distance of %f.ā€, min_ct, min_ray);
res.wallfound = true;
return true;
}

int main(int argc, char **argv) {

ros::init(argc, argv, ā€œfind_wall_serverā€);
ros::NodeHandle nh;

pub = nh.advertise<geometry_msgs::Twist>(ā€œcmd_velā€, 1000);
ros::ServiceServer my_service = nh.advertiseService("/find_wall", my_callback);
ros::Subscriber sub = nh.subscribe("/scan", 1000, laserCallback);

ros::MultiThreadedSpinner spinner(2);
spinner.spin();

return 0;

}

@arjun2312
Please donā€™t copy other peopleā€™s code and try to make them your own, unless you understand every line of the code and what it does. Especially, do not copy ROS2 code and try to make it work for ROS1 - all you will get are cryptic errors!

Please tell the exact issue you are having with details. What is failing exactly?

If you follow the examples given in the notebook carefully, you would be able to solve the problem. You should focus on understanding the concepts thought vs just ā€œgetting it to workā€ because real life problems demand that you understand the concepts.

PS: I have found mostly that the gap people talk about are mostly in their programming skills. You need strong programming skills in addition to ROS knowledge to be successful with ROS. So focus on improving your programming skills and understanding the ROS concepts - we have a course on Python in case you have not taken it. Ten different programmers can solve the same problem in ten different ways, so looking for a code to copy is usually a sign of weak programming skills. A strong programmer will on the other hand be able to properly adapt existing code.

Hi @bayodesegun,

I also experience a ā€˜gapā€™ between the course lessons and this assignment and I donā€™t think itā€™s caused by a lack of programming skills. Iā€™ve described the gap in this post reply. Could you help us explain?

Please point out the gap on the category of the course itself and tag me there. This category is for ROS1 basics.

When you click on the Get Help while on the simulation screen, it takes you directly to the category of the course.