ROS Resources: Documentation | Support | Discussion Forum | Index | Service Status | ros @ Robotics Stack Exchange
Ask Your Question
0

callback function doesnt printout the subscribe msg

asked 2019-10-07 07:47:39 -0600

sadeksadek gravatar image

updated 2022-04-17 11:03:24 -0600

lucasw gravatar image

hello guys iam new at ROS and iam trying to print the msg and some how it doesnt print it and i cant find where is the problem this is my code

#include <moveit/move_group_interface/move_group_interface.h>
#include <moveit/planning_scene_interface/planning_scene_interface.h>
#include <moveit_msgs/DisplayRobotState.h>
#include <moveit_msgs/DisplayTrajectory.h>
#include <moveit_msgs/AttachedCollisionObject.h>
#include <moveit_msgs/CollisionObject.h>
#include <moveit_visual_tools/moveit_visual_tools.h>
#include <iostream>
#include <moveit/robot_model/robot_model.h>
#include <moveit/robot_state/robot_state.h>
#include <ros/ros.h>
#include "geometry_msgs/PointStamped.h"
#include <geometry_msgs/PoseStamped.h>
#include <geometry_msgs/Quaternion.h>
#include <tf/transform_broadcaster.h>
#include <message_filters/sync_policies/approximate_time.h>
#include <sensor_msgs/PointCloud.h>
#include <sensor_msgs/PointCloud2.h>
#include <sensor_msgs/point_cloud_conversion.h>
#include <tf/LinearMath/Quaternion.h>
#include <tf/transform_datatypes.h>

using namespace message_filters;
using namespace sensor_msgs;
using namespace std;
using namespace geometry_msgs;
namespace rvt = rviz_visual_tools;

class kuka
{

private:
    ros::Subscriber sub;
    ros::NodeHandle nh_;


public:
        kuka(ros::NodeHandle &nh) //constructor 
      {
      nh_=nh;   
      }

        void status() //func showing the actual position (case0)
    {
        sub = nh_.subscribe("/robposi", 1000, &kuka::callback, this); 
        cout<<"status";
    }



        void callback(const geometry_msgs::PointStamped::ConstPtr& rob)
        {
        cout<<"callback  ";
        ROS_INFO_STREAM(endl << "RobCoor.x: "<< rob->point.x << endl << "RobCoor.y: "<< rob->point.y << endl << "RobCoor.z: "<< rob->point.z << endl);
        }


};



int main(int argc, char** argv)
{
    ros::init(argc, argv, "kuka");
        int j;char loop='*';

    ros::NodeHandle nh;

do
    {
     cout<<"-------------------------------------------"<<std::endl;
     cout<<"|0 |check position of robot               |"<<std::endl;
     cout<<"|1 |go to home                            |"<<std::endl;
     cout<<"|2 |go to stored position                 |"<<std::endl;
     cout<<"|3 |enter the position w,x,y,z            |"<<std::endl;
     cout<<"|4 |enter the position of joints          |"<<std::endl;
     cout<<"|5 | exit                                 |"<<std::endl;
     cout<<"-------------------------------------------"<<std::endl;
     cin>>j;
    kuka listen_0(nh);

cout<<"i =   "<<j;

    switch (j){
    case(0):{
cout<<"i hekkddddddddddd   ";
    listen_0.status();
cout<<"i hekk.lj,hk....   ";
    }

    break;

}

    cout <<"would you like to enter new choice y/n?"<<endl;
    cin>> loop;
    }while (loop == 'y');

    return 0;
 }
edit retag flag offensive close merge delete

Comments

1

Hello ! Can you put the whole code ? Because we only this part, it look like you forgot to call ros::spin() or ros::spinOnce().

These 2 functions are used by roscpp to check if any message has been received by your subscribers

lmathieu gravatar image lmathieu  ( 2019-10-07 08:06:13 -0600 )edit

Based on OP's "answer" that indeed looks like the solution.

Delb gravatar image Delb  ( 2019-10-08 01:32:59 -0600 )edit

its the hole program , that my supervisor recommended me to make do while instead of ros spin because it make problems with switch case but i will try to use ros spin and see the result

sadeksadek gravatar image sadeksadek  ( 2019-10-08 02:42:17 -0600 )edit

i tried ros::spinOnce() and also i add do{ /somecode/ }while(loop=='y' && ros::ok()) at the end but the problem still happening callback function doesn't call though when i make rostopic echo i can see the msg that i publish

sadeksadek gravatar image sadeksadek  ( 2019-10-08 06:39:57 -0600 )edit

2 Answers

Sort by ยป oldest newest most voted
1

answered 2019-10-08 08:25:26 -0600

I think I got it :

In your code, you are calling listen_0.status(); when a user press '0', this function is creating a new subscriber. If you added a ros::spinOnce(), the callback is never called if a user never pressed '0' before. But there is another problem, you recreate the class kuka listen_0(nh); at the beginning of the loop, hence destroying the old class instance and losing your subscriber.

When using ROS, you should only create a subscriber (or publisher) once, often in the constructor of a class or in an init() function, and delete it at the end of your program. This allow your rosnode to "tell" the roscore that there is a new node with a subscriber (or publisher), and he should receive (or send) message (this take some times in background, you can't create a publisher or subscriber and instantly receive or publish a message).

I recommend you to take a look at the ros tutorial about Subscribing to have a better understanding of the ROS ecosystem.

Normally, your code should look like this (I added /// comment where I edited your file):

Be carefull, as this is not optimal at all. Since your cin are blocking, i placed the ros::spinOnce() before the code needs the messages values. You may want to take a look at Async Spinner once you have fully grasped the basics

..skipping includes...
class kuka
{

private:
    ros::Subscriber sub;
    ros::NodeHandle nh_;

    ///We save the last robot coordinate here
    geometry_msgs::PointStamped lastCoordinate;

public:
    kuka(ros::NodeHandle &nh) // constructor
    {
        nh_ = nh;

        ///Create the subscriber here
        sub = nh_.subscribe("/robposi", 1000, &kuka::callback, this);
    }

    void status() // func showing the actual position (case0)
    {
        cout << "status";
        ROS_INFO_STREAM(endl
                        << "RobCoor.x: " << lastCoordinate->point.x << endl
                        << "RobCoor.y: " << lastCoordinate->point.y << endl
                        << "RobCoor.z: " << lastCoordinate->point.z << endl);
    }

    void callback(const geometry_msgs::PointStamped::ConstPtr &rob)
    {
        cout << "callback  ";
        lastCoordinate = rob; ///we save the robot position for later
    }
};

int main(int argc, char **argv)
{
    ros::init(argc, argv, "kuka");
    int j;
    char loop = '*';

    ros::NodeHandle nh;

    ///Creation of the class outside the main loop
    kuka listen_0(nh);

    do
    {
        cout << "-------------------------------------------" << std::endl;
        cout << "|0 |check position of robot               |" << std::endl;
        cout << "|1 |go to home                            |" << std::endl;
        cout << "|2 |go to stored position                 |" << std::endl;
        cout << "|3 |enter the position w,x,y,z            |" << std::endl;
        cout << "|4 |enter the position of joints          |" << std::endl;
        cout << "|5 | exit                                 |" << std::endl;
        cout << "-------------------------------------------" << std::endl;
        cin >> j;

        cout << "i =   " << j;

        ros::spinOnce();///we spin here since this is the optimal place

        switch (j)
        {
        case (0):
        {
            cout << "i hekkddddddddddd   ";
            listen_0.status(); ///Display current position if pressed 0
            cout << "i hekk.lj,hk....   ";
        }

        break;
        }

        cout << "would you like to enter new choice y/n?" << endl;
        cin >> loop;
    } while (loop == 'y' && ros::ok()); ///continue until ros is stopped, ctrl+c is ...
(more)
edit flag offensive delete link more

Comments

it works finally thanks very much for your help though the callback function was repeated somehow when i call the 0 option again but at least it worked and now i just should figure out how to make it work once when i call it

sadeksadek gravatar image sadeksadek  ( 2019-10-08 10:31:40 -0600 )edit

The callback function will get called everytime the code pass through ros::spinOnce().

If you add an asyncspinner, the callback function will get called everytime a message is received.

that because ROS keep the message received in a queue, if the queue is not empty, the callback will be called. Your queue can actually keep 1000 messages, so the callback can be called up to 1000 times in a row everytime the user press something (you will see up to 1000 times "callback" written on the screen actually if the user wait to much to choose something), and that probably not what you want ( But I don't know your use case so maybe it is)

Again, do the tutorial, that will keep you away from a lot of cppain in the future :)

lmathieu gravatar image lmathieu  ( 2019-10-08 10:56:50 -0600 )edit

yea i am doing the tutorial again because i just need it to receive the message only once only when i call the case . but really thanks you very much for your help

sadeksadek gravatar image sadeksadek  ( 2019-10-09 04:24:57 -0600 )edit
1

answered 2019-10-08 08:28:48 -0600

Delb gravatar image

There are few things wrong in your code, you should really read the wiki about subscribers, the example match your situation.

First thing to say is : why do you create a class for this ? Eventhough you'll probably go further seeing all the possible inputs, you could separate everything into different functions that would be call in the switch..case instead of a class.

Secondly, the line kuka listen_0(nh); is within the loop which means you create a new object each time you are looping which is bad because you would loose every attributes data (if you had one). There is a similar issue with your function status(), you redefine a subscriber each time you call the function. Knowing that a subscriber takes time to register to a topic if you needed to get messages that are published at high rate you would lose a lot of data.

Finally your loop as it is wouldn't allow to add ros::spinOnce() to be called at some rate because of the cin. Because of cin your program is blocked (meaning the callback too) until you input something. As soon as you do you start again your loop where you create a new obect and also a new subscriber, thus a new callback so the previous message (if there was any) would be lost.

Your code should have this template :

//Global variable to trigger the command input
bool trigger_user_input = false;

void callback()
{
    //Do your stuff
    trigger_user_input = true
}
int main(int argc, char** argv)
{
    //Init the node, subscribers/publishers, main variables here
    while (ros::ok())
    {
        //Call spinOnce to continue the loop
        ros::spinOnce();

        //Do your stuff only when you had the callback
        if (trigger_user_input)
        {
            //Set the flag to false to continue spinning next time
            trigger_user_input = false;
            std::cin << loop;
            //Do your stuff with cin here
        }
    }
    return 0;
 }

And again, you should read the ros tutorials, there are plenty of examples in there.

edit flag offensive delete link more

Comments

thanks for your help you really helped me to understand how it works, for the first question my supervisor wanted the program only in classes though i did all task without it ,

sadeksadek gravatar image sadeksadek  ( 2019-10-08 10:32:58 -0600 )edit

Question Tools

Stats

Asked: 2019-10-07 07:47:39 -0600

Seen: 1,017 times

Last updated: Oct 08 '19