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

How to make a c++ node Listen and Publish

asked 2013-10-10 17:30:45 -0600

Alkaros gravatar image

updated 2013-10-10 17:56:22 -0600

I feel like this should be a simple problem.

The listening callback function is working and it is printing in terminal but the publishing doesn't seem to be working. The node shows up in rostopic list but it does not echo anything.

The script is getting an observation from an APPL node and gets an action back. I then want to pass the action to the action node.

Ideally, I want to get something like this working as the published attribute:

void sendAction(int action) 
{
    printf("SENDING ACTION\n");
    ros::NodeHandle nh;
    ros::Publisher vel_pub = nh.advertise<geometry_msgs::Twist>("cmd_vel", 1);
    geometry_msgs::Twist vel;
    vel.angular.z = 0;
    vel.linear.x = 1;
    vel_pub.publish(vel); 
}

This is the whole script at the moment

using namespace std;

// Messege recieved callback
void chatterCallback(const std_msgs::String::ConstPtr& msg)
{ 
    // Variables
    std_msgs::String actionstr;
    std::stringstream ss;

    // Set up
    ros::NodeHandle n;

    // Publish and advertise
    ros::Publisher chatter_pubs = n.advertise<std_msgs::String>("actionstr", 1000);
    ros::Rate loop_rate(10);

    // APPL NODE SHIZ
    appl::appl_request srv;
    ros::ServiceClient client = n.serviceClient<appl::appl_request>("appl_request");

    //Send to POMDP Node
    srv.request.cmd=2;
    srv.request.obs=msg->data.c_str();
    client.call(srv);
    int action=srv.response.action;

    // Get action string
    if (action == 0) {ss << "Listen";}
    if (action == 1) {ss << "OpenRight";}
    if (action == 2) {ss << "OpenLeft";}

    // Publish String
    actionstr.data = ss.str();

    chatter_pubs.publish(actionstr);

    printf("Sent\n");

    printf("Obs: %s  Action: %d - %s\n", msg->data.c_str(), action, actionstr.data.c_str());    

}

    /* ------------------------------------------------ */
    /* ---------------------******--------------------- */
    /* ---------------------*MAIN*--------------------- */
    /* ---------------------******--------------------- */
    /* ------------------------------------------------ */

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

    // Set to Appl client
    ros::ServiceClient client = n.serviceClient<appl::appl_request>("appl_request");

    srand((unsigned)time(0));
    int tiger;//0=left 1=right
    tiger=rand()%2;

    // Reset Appl Controller.
    appl::appl_request srv;
    srv.request.cmd=1;  //reset the controller first
    client.call(srv);
    int action=srv.response.action;
    ROS_INFO("I Listen");
    ros::Subscriber sub = n.subscribe("chatter", 1000, chatterCallback);
    ros::spin();

  return 0;
}
edit retag flag offensive close merge delete

1 Answer

Sort by ยป oldest newest most voted
3

answered 2013-10-10 20:38:13 -0600

I didn't pay much attention to your code, not really sure of what you are trying to accomplish, but I don't think it is a good idea to declare the publishers inside a subscriber callback. As you will be creating the publisher every time you get data on the subscriber, I don't know how this would behave.

Try something like this:

using namespace std;

//REMEMBER! EVERY TIME YOU USE A GLOBAL VARIABLE... GOD KILLS A KITTEN!!! 
ros::Publisher chatter_pubs;
ros::ServiceClient client;

// Messege recieved callback
void chatterCallback(const std_msgs::String::ConstPtr& msg)
{ 
    // Variables
    std_msgs::String actionstr;
    std::stringstream ss;

    // APPL NODE SHIZ
    appl::appl_request srv;


    //Send to POMDP Node
    srv.request.cmd=2;
    srv.request.obs=msg->data.c_str();
    client.call(srv);
    int action=srv.response.action;

    // Get action string
    if (action == 0) {ss << "Listen";}
    if (action == 1) {ss << "OpenRight";}
    if (action == 2) {ss << "OpenLeft";}

    // Publish String
    actionstr.data = ss.str();

    chatter_pubs.publish(actionstr);

    printf("Sent\n");

    printf("Obs: %s  Action: %d - %s\n", msg->data.c_str(), action, actionstr.data.c_str());    

}

    /* ------------------------------------------------ */
    /* ---------------------******--------------------- */
    /* ---------------------*MAIN*--------------------- */
    /* ---------------------******--------------------- */
    /* ------------------------------------------------ */

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

    chatter_pubs = n.advertise<std_msgs::String>("actionstr", 1000);

    // Set to Appl client
    client = n.serviceClient<appl::appl_request>("appl_request");

    srand((unsigned)time(0));
    int tiger;//0=left 1=right
    tiger=rand()%2;

    // Reset Appl Controller.
    appl::appl_request srv;
    srv.request.cmd=1;  //reset the controller first
    client.call(srv);
    int action=srv.response.action;
    ROS_INFO("I Listen");
    ros::Subscriber sub = n.subscribe("chatter", 1000, chatterCallback);
    ros::spin();

   return 0;
}
edit flag offensive delete link more

Comments

2

In short: It will behave badly. The publisher will very probably not yet be connected to another node when the publish call comes and then goes out of scope. So, no data is ever sent.

dornhege gravatar image dornhege  ( 2013-10-10 23:56:17 -0600 )edit

Thanks guys, This worked a treat. Sorry about the kittens :(

Alkaros gravatar image Alkaros  ( 2013-10-11 16:23:57 -0600 )edit

Please mark your question as answered (click the check sign to the left of the answer you like).

bit-pirate gravatar image bit-pirate  ( 2013-10-13 21:37:23 -0600 )edit

Question Tools

1 follower

Stats

Asked: 2013-10-10 17:30:45 -0600

Seen: 2,481 times

Last updated: Oct 10 '13