You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

NCurses getch始终返回ERR(-1),ROS键盘节点无法发布消息求助

嘿,我之前在ROS节点里用ncurses时也踩过这个坑!getch()一直返回ERR(-1),大概率和终端控制权、ncurses的初始化流程或者ROS的终端重定向有关,咱们一步步来排查解决:

1. 先确保ncurses的基础流程完全正确

很多时候问题出在初始化步骤漏了关键配置,ncurses默认是行缓冲模式,必须按回车才会传递输入,而且需要明确开启按键的即时读取:

#include <ncurses.h>
#include <ros/ros.h>
#include <std_msgs/String.h>

int main(int argc, char** argv) {
    // 先初始化ROS,再初始化ncurses(顺序很重要!)
    ros::init(argc, argv, "key_publisher");
    ros::NodeHandle nh;
    ros::Publisher key_pub = nh.advertise<std_msgs::String>("/keys", 10);

    // 初始化ncurses核心配置
    initscr();          // 启动ncurses环境
    cbreak();           // 禁用行缓冲,按键立即被读取
    noecho();           // 不回显按下的按键
    keypad(stdscr, TRUE); // 支持功能键(方向键、F键等)
    // 如果需要非阻塞读取(不卡主ROS循环),加上这句;如果要阻塞等按键就注释掉
    // nodelay(stdscr, TRUE);

    printw("Press keys to publish to /keys (press 'q' to exit)\n");
    refresh(); // 刷新屏幕,让输出显示

    ros::Rate loop_rate(10);
    while (ros::ok()) {
        int ch = getch();
        if (ch != ERR) {
            std_msgs::String msg;
            msg.data = std::string(1, static_cast<char>(ch));
            key_pub.publish(msg);
            printw("Published key: %c\n", ch);
            refresh();

            if (ch == 'q') break;
        }
        ros::spinOnce();
        loop_rate.sleep();
    }

    // 退出前必须清理ncurses
    endwin();
    return 0;
}

重点检查:有没有调用cbreak()?有没有在输出后调用refresh()?退出时有没有endwin()?

2. 确保ROS节点关联到正确的终端

用rosrun运行节点时,ROS有时候会悄悄修改终端的输入输出关联,导致ncurses拿不到终端控制权:

  • 先试试直接运行节点的可执行文件:cd到devel/lib/你的包名,然后执行./你的节点名,如果这时候getch()正常,那就是rosrun的锅。
  • 解决rosrun的问题:用--prefix "exec"参数强制节点直接关联当前终端:
    rosrun --prefix "exec" 你的包名 你的节点名
    
3. 区分“无按键”和“读取失败”

如果你用了nodelay(stdscr, TRUE)开启非阻塞模式,getch()在没有按键时会返回ERR(-1),这是正常现象!你需要在代码里判断:只有当ch不等于ERR时,才处理按键并发布消息,否则继续循环即可(别把ERR当成错误)。

4. 先修复纯ncurses程序的问题

你说简化的ncurses小程序也无输出,先解决这个基础问题:

  • 写一个最极简的测试程序,编译时一定要链接ncurses库:g++ test.cpp -o test -lncurses
  • 如果运行还是没反应,重置终端设置:执行stty sane后再运行测试程序
  • 再不行就重新安装ncurses依赖:
    sudo apt-get install libncurses5-dev libncursesw5-dev
    
  • 另外,别用IDE的内置终端(比如CLion、VS Code的终端),换原生的gnome-terminal或xterm试试,很多IDE终端对ncurses支持不好。
最后再整合到ROS节点

等纯ncurses程序能正常读取按键后,再把代码整合到ROS节点里,注意ROS初始化和ncurses初始化的顺序(先ROS,后ncurses),确保退出时调用endwin()清理终端。

内容的提问来源于stack exchange,提问作者VansFannel

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 07:14:54