0

I've just started to work with ROS and I'm trying to write a node that publish keys in a topic.

I have created a node on a Linux Ubuntu 16.04.4 using ncurses.

This is my code:

#include <curses.h>

#include "ros/ros.h"
#include "std_msgs/String.h"

#include <sstream>

int main(int argc, char **argv)
{
    int ch;
    nodelay(stdscr, TRUE);

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

    ros::NodeHandle n;

    ros::Publisher key_pub = n.advertise<std_msgs::String>("keys", 1);

    ros::Rate loop_rate(100);

    while (ros::ok())
    {
        std_msgs::String msg;
        std::stringstream ss;

        if ((ch = getch()) != ERR)
        {
            ss << ch;
            std::cout << ch;
            msg.data = ss.str();

            ROS_INFO("%s", msg.data.c_str());

            key_pub.publish(msg);
        }

        ros::spinOnce();
        loop_rate.sleep();
    }

    return 0;
}

I'm using ncurses to avoid terminal buffer.

The topic appears, but I don't get anything if, in another terminal, I run this command:

rostopic echo /keys

Debugging it I have found that getch() always return -1.

How can I do to make it work?

UPDATE

I have tried this small program, and it doesn't print anything:

#include <iostream>
#include <curses.h>

int main(int argc, char **argv)
{
    int ch;
    cbreak();
    nodelay(stdscr, TRUE);

    for(;;)
    {
        if ((ch = getch()) != ERR)
        {
            std::cout << ch;
        }
    }

    return 0;
}
VansFannel
  • 45,055
  • 107
  • 359
  • 626

2 Answers2

3

You've set nodelay so getch will return immediately with ERR if there's no data ready from the terminal. That's why getch is returning -1 (ERR). You haven't set cbreak or raw to disable terminal buffering, so you're still getting that -- no data will come from the terminal until Enter is hit.

So add a call to cbreak() at the start (just before or after the call to nodelay()) and it should work as you expect.

Chris Dodd
  • 119,907
  • 13
  • 134
  • 226
  • Thanks for your answer but I have tried it and it doesn't work. I have updated my question with a small program to test `getch()` and it doesn't output anything with the statement `std::cout << ch;`. – VansFannel May 20 '18 at 19:00
  • I forget to add `initscr();` – VansFannel May 20 '18 at 19:14
1

To use getch() you have to do the following:

#include <iostream>
#include <curses.h>
#include <signal.h>
#include <stdlib.h>

void quit(int sig)
{
    endwin();
    exit(0);
}

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

    signal(SIGINT,quit);

    initscr();
    cbreak();
    nodelay(stdscr, TRUE);

    for(;;)
    {
        if ((ch = getch()) != ERR)
        {
            std::cout << ch;
        }
    }

    return 0;
}

I forget to add initscr(); call at the beginning and endwin(); at the end of the program.

More info about how to use ncurses library here.

VansFannel
  • 45,055
  • 107
  • 359
  • 626