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

Linux下开发C++ ROS节点:如何实时获取Unix控制台按键输入?

嘿,针对你在Ubuntu 16.04下开发ROS C++节点时需要实时捕获按键输入的需求,咱们直接通过修改终端属性就能搞定——默认终端是规范模式,会把输入缓冲到整行才处理,咱们把它改成非规范模式,就能让按键一按下就被程序读取到。

实现思路

Linux终端的输入行为由termios结构体控制,我们需要修改它的核心参数:关闭规范模式,调整读取的超时和最小字符数,实现单按键实时响应。特别注意:操作完成后一定要恢复原终端设置,不然退出程序后你的终端会变得异常(比如输入不回显、不缓冲)。

完整ROS节点代码示例

下面是一个可直接运行的ROS节点代码,包含终端模式切换、实时按键读取和退出恢复的完整逻辑:

#include <ros/ros.h>
#include <termios.h>
#include <unistd.h>
#include <fcntl.h>

// 保存终端原始属性,用于退出时恢复
struct termios original_termios;

// 将终端设置为非规范模式(实时读取按键)
void set_non_canonical_mode() {
    tcgetattr(STDIN_FILENO, &original_termios);
    struct termios new_termios = original_termios;
    
    // 关闭规范模式(取消整行缓冲),关闭回显(可选,不想看到按键时启用)
    new_termios.c_lflag &= ~(ICANON | ECHO);
    // 设置:至少读取1个字符,超时时间0(阻塞直到有按键按下)
    // 若要非阻塞读取(循环检查不等待),可将VMIN设为0、VTIME设为0,同时打开非阻塞标志(见注释)
    new_termios.c_cc[VMIN] = 1;
    new_termios.c_cc[VTIME] = 0;
    
    tcsetattr(STDIN_FILENO, TCSANOW, &new_termios);
    // 非阻塞读取开关(取消注释启用)
    // int flags = fcntl(STDIN_FILENO, F_GETFL, 0);
    // fcntl(STDIN_FILENO, F_SETFL, flags | O_NONBLOCK);
}

// 恢复终端原始属性
void restore_terminal_mode() {
    tcsetattr(STDIN_FILENO, TCSANOW, &original_termios);
    // 若启用了非阻塞,这里恢复原状态
    // int flags = fcntl(STDIN_FILENO, F_GETFL, 0);
    // fcntl(STDIN_FILENO, F_SETFL, flags & ~O_NONBLOCK);
}

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

    // 设置终端模式,并注册退出时的恢复函数(异常退出也能生效)
    set_non_canonical_mode();
    atexit(restore_terminal_mode);

    ros::Rate loop_rate(100); // 100Hz循环保证实时性
    char key;

    while (ros::ok()) {
        // 读取单个按键
        ssize_t bytes_read = read(STDIN_FILENO, &key, 1);
        if (bytes_read > 0) {
            ROS_INFO("Pressed key: %c (ASCII code: %d)", key, key);
            // 这里可以添加你的业务逻辑,比如发布ROS控制消息
            if (key == 'q') {
                ROS_INFO("Exit command received, quitting...");
                break;
            }
        }

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

    return 0;
}
代码细节说明
  • set_non_canonical_mode:核心是修改termios的c_lflag和c_cc参数,关闭规范模式后,终端不再缓冲整行输入。
  • restore_terminal_mode:通过atexit注册,确保程序无论正常还是异常退出,都能把终端恢复到原来的状态。
  • 主循环:用read读取单个字符,捕获到按键后可直接执行你的ROS节点逻辑(比如发布话题、控制机器人)。
编译配置参考

在你的CMakeLists.txt中添加以下配置,确保能正常编译ROS节点:

cmake_minimum_required(VERSION 2.8.3)
project(keyboard_input_node)

find_package(catkin REQUIRED COMPONENTS
  roscpp
  std_msgs
)

catkin_package(
  CATKIN_DEPENDS roscpp std_msgs
)

include_directories(
  ${catkin_INCLUDE_DIRS}
)

add_executable(keyboard_input_node src/keyboard_input_node.cpp)
target_link_libraries(keyboard_input_node
  ${catkin_LIBRARIES}
)

这样编译运行后,按下任意按键都会被程序立即捕获,完全满足你的课程作业需求~

内容的提问来源于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 06:15:13