How to read the laserscan,store and display it simultaneously (Topics_quiz)

I have written a Piece of code to subscribe /Kobuki/laser/scan and publish some twist message to bot and ahead is a wall(obstacle) , I want to get laser data while bot is moving.
But I am getting a ‘Segmentation fault (core dumped)’. Why is it so?

Code:

#include<ros/ros.h>
#include<sensor_msgs/LaserScan.h>
#include<geometry_msgs/Twist.h>

ros::Publisher pub;
ros::Subscriber sub;

sensor_msgs::LaserScan lsvalue;
geometry_msgs::Twist vel;

void laser_callback(const sensor_msgs::LaserScan::ConstPtr& msg){
int range=msg->ranges.size();
for(int i=0;i<range;i++){
lsvalue.ranges[i]=msg->ranges[i]+1;

}

}
int main(int argc,char** argv){
ros::init(argc, argv, “topics_quiz_node”);
ros::NodeHandle nh;
pub=nh.advertise<geometry_msgs::Twist>("/cmd_vel", 1000);
sub=nh.subscribe("/kobuki/laser/scan",1000, laser_callback);
ros::Rate loop(1);
for( int i=0; i<5;i++){
vel.linear.x=0.2;
pub.publish(vel);
}
vel.linear.x=0;
pub.publish(vel);
while(ros::ok()){
for (int i=0;i<lsvalue.ranges.size();i++){
ROS_INFO(“Data %f”, lsvalue.ranges[i]);
loop.sleep();
}
ros::spinOnce();
loop.sleep();
}

return 0;

}

Hi @adityasrichandan3098,
please post the whole error message

I have added a code to check if i am getting the laser call back, it seems my laser.ranges seems to be empty. i.e I am not receiving the laserscan data. How do I wait for the data? My program if exiting once executed with segmentation fault due to empty range.

float laser(sensor_msgs::LaserScan& Laser){
if(!(Laser.ranges.empty())){
return Laser.ranges[(Laser.ranges.size())/2];
}
else{
ROS_INFO(“waiting”);
return 0;
}
}

Thanks for the clarification.
This is a perfect exercise for troubleshooting. I’m not too familiar with c++, but here are 2 links that might help:
https://www.cprogramming.com/debugging/segfaults.html
https://jvns.ca/blog/2018/04/28/debugging-a-segfault-on-linux/

How I would troubleshoot this:

  1. remove your whole if-then-else part of the functions and see if that is what causes the error
  2. add ROS_INFO() on different steps of the way, to print info you need. For example you can print
    ROS_INFO(Laser.ranges.size()) before your check, in the if and in the else loop. See what your program does. Perhaps a command or syntax you use, does something different to what you think
  3. check the core dump (perhaps do this first)

Hi @adityasrichandan3098,

Looking at your code, I can see the following:

  • You are trying to put your LaserScan message into lsvalue, but it seems it’s not being done rightly. But…you don’t even need to do that! In your laser_callback, just print the messages you are printing in main() by accessing msg directly.

  • Your are missing ros::spin() in main(), so your subscriber is not working properly (spinOnce() is not enough for this case, as you need to keep subscribing to the laser scan. See the difference between spin() and spinOnce() in the post below:
    What is rospy.spin(), ros::spin(), ros::spinOnce(), and what are they for?

  • Don’t stop the robot in main(), like you’re doing here:

vel.linear.x=0;
pub.publish(vel);
  • You don’t need the Rate object here:
    Proper use of rospy.Rate or ros::Rate

  • You don’t need to do any publishing in the main function - do them in the laser_callback, based on the sensor reading. If you must do any publication in main(), let it be the initial one and then do the rest in the callback. Your main should be something like:

int main(int argc,char** argv){
   ros::init(argc, argv, “topics_quiz_node”);
   ros::NodeHandle nh;
   pub=nh.advertise<geometry_msgs::Twist>("/cmd_vel", 1000);
   sub=nh.subscribe("/kobuki/laser/scan",1000, laser_callback);
   // Do just the initial publication here; do the rest in the callback
   // Not really necessary though
   for(int i=0; i<5;i++){
     vel.linear.x=0.2;
     pub.publish(vel);
   }
   // This is necessary for the LaserScan message to keep arriving 
   // and for the program to keep running
   ros::spin();
}

Your laser_callback() could be something like:

void laser_callback(const sensor_msgs::LaserScan::ConstPtr& msg){
  // print your ranges array for debugging.
  // the middle values represent the front-center of the robot
  // the first and last represent the extreme sides
  if (/*robot is not too close for comfort*/) {
    vel.linear.x = 0.2; // move forward
    vel.anguar.z = 0; // no turning for now
  }
  else {
    vel.angular.z = -0.2 // or 0.2, turn
    vel.angular.x = 0; // no forward movement for now
  }
  pub.publish(vel);
}

Yup! thanks @bayodesegun Now I have a good Idea on how to use ros::spin, ros::spinOnce and ros::rate.

Yet my sensor message seems to get lost somewhere! I have written the code again, and yet again I am not able to receive the laser scan data.

 #include<ros/ros.h>
 #include<sensor_msgs/LaserScan.h>
 #include<geometry_msgs/Twist.h>

class AvoidWall{
private:
    ros::NodeHandle _n;
    ros::Publisher _pub;
    ros::Subscriber _sub;
    geometry_msgs::Twist _vel;
    sensor_msgs::LaserScan _lsval;

public:

    AvoidWall(){
        _pub=_n.advertise<geometry_msgs::Twist>("/cmd_vel", 1000);
        _sub=_n.subscribe("/kobuki/Laser/scan",1000,&AvoidWall::laser_callback,this);


    }
    void move(){
        ros::Rate rate(20);
        for(int i=0;i<10;i++){
            _vel.linear.x=0.5;
            _pub.publish(_vel);
            rate.sleep();
            ROS_INFO("MOVING");
        }
        _vel.linear.x=0;
        _pub.publish(_vel);
        ROS_INFO("DONE!");
    }
    void laser_callback(const sensor_msgs::LaserScan::ConstPtr& msg){

        for(int i=0;i<(msg->ranges.size());i++){
            //_lsval.ranges[i]=msg->ranges[i];
            if(!(msg->ranges.empty()))
            ROS_INFO("data %f",msg->ranges[i]);
            else{
                ROS_INFO("NO VALUE");
            }
        }
    }
};
int main(int argc, char** argv)
{
         ros::init(argc, argv,"topics_quiz_node");
         AvoidWall obj;

obj.move();

ros::spin();
return 0;

}

After “MOVING” is displayed, I am not getting the callback function called.

I’m not good with c++. but try to remove the obj.move() , just have

AvoidWall obj;
ros::spin();

call the move function from within your callback.

Thanks! for mentioning @simon.steinmann91 @bayodesegun, btw I found the problem,I mispelled
/kobuki/laser/scan topic.

2 Likes