How to write a good program in C++: Referencing a value from another function

Hello .
I would like to ask a basic C++ question.
I am currently working on the final project of ROS Basics in 5 Days (C++), which is a maze search.
I am currently creating a service server for collision detection.
I would like to adjust the subscriber to get the laser values and run the assignment, but I am stumped on the assignment.
I would like to read the values from a callback function called laser_callback in a callback function called obstacle_callback for collision as shown in the following code, but I can’t think of a good way to do it.
I’ve tried using pointers, declaring it as a global variable, etc., but I get an error when compiling.

If you could give me some advice on how to solve this problem, I would appreciate it.

#include “ros/ros.h”

    #include "std_srvs/Trigger.h"

    #include "sensor_msgs/LaserScan.h"

    #include "my_turtlebot_topics/laser_turtle_sub.h"

    laser_turtle_sub::laser_turtle_sub()

    {

        sub = nh.subscribe("/kobuki/laser/scan",1000,&laser_turtle_sub::laser_callback,this);

        my_service = nh.advertiseService("/move_bb8_in_circle", &laser_turtle_sub::obstacle_callback,this);

    }

    void laser_turtle_sub::laser_callback(const sensor_msgs::LaserScan::ConstPtr& laser_msg)

    {

        float laser_range_c = laser_msg->ranges[360];

        float laser_range_r = laser_msg->ranges[0];

        float laser_range_l = laser_msg->ranges[719];

        //ROS_INFO("LaserData Center:%f Right:%f Left:%f\n",laser_range_c,laser_range_r,laser_range_l);

    }

    bool laser_turtle_sub::obstacle_callback(std_srvs::Trigger::Request  &req, std_srvs::Trigger::Response &res)

    {

        //サービス要請を受けたとき各方向のレーザーの値を取得する

        res.message = laser_range_c;

        ROS_INFO("%f",res.message);

        return true;

    }

    int main(int argc, char **argv)

    {

    ros::init(argc, argv, "service_move_bb8_in_circle_server");

    ros::NodeHandle nh;

    laser_turtle_sub *lasersub = new laser_turtle_sub();

    //vel_pub = nh.advertise<geometry_msgs::Twist>("cmd_vel", 1000);

    ROS_INFO("Service /move_bb8_in_circle_custom Ready");

    ros::spin();

    return 0;

    }

thank you.

Translated with www.DeepL.com/Translator (free version)

Hi, can you share the error message you are receiving while compiling?

Hello.

If you run the above program, you will get the following error because the variable is not declared in obstacle_callback().

As a workaround for this, I implemented declaring the variables as follows. Compilation was successful, but I could not get the proper laser_msg as shown in the following image.
(I’m sorry, sir. The name of the service server has been changed from /move_bb8_in_circle to /turtle_custom.)


I don’t think I understand pointers correctly, but I thought I could use pointers to read the data in laser_range_c if it is from an address. (I’m probably wrong.)
I’ve tried this with * and & everywhere, but none of them worked (I got an error that it was not declared).

So I’m looking for a simple way to read the value of laser_range_c declared in another function like this, but I’ve hit a wall.

I would be grateful for any advice.

Have you tried simplifying your code? For example, advertising the service inside main() instead of inside a callback function? I see that calling the service fails, do you have it available/created correctly?

Thank you for the advice.
I was reviewing my code again after your advice, and I realized my mistake.

In my previous code, I had given a float laser message to the response string type “message” in trigger.srv!
So when I ran “rosservice call ~” as shown in the image above ,
This is why when you run “rosservice call ~” as shown in the image above, you get an unintended display.
(After displaying the value of the laser, a mysterious ? is displayed after displaying the laser value…)

As a solution, I created the following code and ran it to get the following result.

laser_turtle_sub.h

    #ifndef LASER_TURTLE_SUB_H
    #define LASER_TURTLE_SUB_H
    #include <ros/ros.h>
    #include "sensor_msgs/LaserScan.h"
    #include "std_srvs/Trigger.h"



    class laser_turtle_sub{
        protected:
            ros::NodeHandle nh;
            ros::Subscriber sub;
            ros::ServiceServer my_service;
            sensor_msgs::LaserScan laser;

        public:
            laser_turtle_sub();
            float laser_range_c;
            void laser_callback(const sensor_msgs::LaserScan::ConstPtr& laser_msg);
            bool obstacle_callback(std_srvs::Trigger::Request  &req, std_srvs::Trigger::Response &res);
    };

    #endif

laser_turtle_service_server.cpp

    #include "ros/ros.h"
    #include "std_srvs/Trigger.h"
    #include "sensor_msgs/LaserScan.h"
    #include "my_turtlebot_topics/laser_turtle_sub.h"

    static float laser_range_c;
    static float laser_range_r;
    static float laser_range_l;

    laser_turtle_sub::laser_turtle_sub(){
        sub = nh.subscribe("/kobuki/laser/scan",1000,&laser_turtle_sub::laser_callback,this);
        my_service = nh.advertiseService("/turtle_custom", &laser_turtle_sub::obstacle_callback,this);
    }

    void laser_turtle_sub::laser_callback(const sensor_msgs::LaserScan::ConstPtr& laser_msg)
    {
        laser_range_c = laser_msg->ranges[360];
        laser_range_r = laser_msg->ranges[0];
        laser_range_l = laser_msg->ranges[719];

        //ROS_INFO("LaserData Center:%f Right:%f Left:%f\n",laser_range_c,laser_range_r,laser_range_l);
    }

    bool laser_turtle_sub::obstacle_callback(std_srvs::Trigger::Request  &req, std_srvs::Trigger::Response &res)
    {
        ROS_INFO("recieve a call");
        ROS_INFO("%f",laser_range_c);
        //サービス要請を受けたとき各方向のレーザーの値を取得する
        if(laser_range_c > 2){
            res.message = "safe";
            ROS_INFO("%s",res.message);
        }
        else{
            res.message = "crush";
            ROS_INFO("%s",res.message);
        }

        return res.success = true;
    }

    int main(int argc, char **argv)
    {
        ros::init(argc, argv, "service_turtle_server");
        ros::NodeHandle nh;

        laser_turtle_sub *lasersub = new laser_turtle_sub();
        ros::Rate rate(2);

        ROS_INFO("Service /turtle_custom Ready");
        ros::spin();

        return 0;
    }

image

Anyway, thanks for the advice. Thank you very much for your advice, I was able to review my code calmly.

2 Likes