我刚刚开始使用ROS,而我正在尝试编写一个在主题中发布密钥的节点。
我使用ncurses在Linux Ubuntu 16.04.4上创建了一个节点。
这是我的代码:
#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;
}
我使用ncurses来避免终端缓冲。
主题出现,但如果在另一个终端中我运行此命令,则无法获得任何内容:
rostopic echo /keys
调试它我发现getch()总是返回-1。
如何才能让它发挥作用?
更新
我尝试过这个小程序,并没有打印任何东西:
#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;
}
答案 0 :(得分:3)
您已设置nodelay
,因此如果终端没有准备好数据,则getch
将立即返回ERR
。这就是getch返回-1(ERR)的原因。你没有设置cbreak或raw来禁用终端缓冲,所以你仍然得到了 - 在 Enter 被击中之前,终端不会有任何数据。
所以在开始时(在调用cbreak()
之前或之后)添加对nodelay()
的调用,它应该按预期工作。
答案 1 :(得分:0)
要使用getch()
,您必须执行以下操作:
#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;
}
我忘记在开头添加initscr();
来电,在节目结束时添加endwin();
。
有关如何使用ncurses库here的更多信息。