我尝试从终端读取箭头键字符并使用String
类型的消息通过ROS
。为此,我使用termios
read()
函数。
首先,我做了一个在C
下使用gcc
编译的小测试。这是代码:
#include <unistd.h>
#include <stdlib.h>
#include <termios.h> // for keyboard input
#include <string.h>
#include <stdio.h>
bool quit_requested = false;
void processKeyboardInput (char c)
{
switch (c)
{
case 68:// Left arrow pressed
{
puts("Left pressed");
break;
}
case 67://Right arrow pressed
{
puts("Right pressed");
break;
}
case 65://Up arrow pressed
{
puts("Up pressed");
break;
}
case 66://Down arrow pressed
{
puts("Down pressed");
break;
}
case 'q'://Quit arrow pressed
{
quit_requested = true;
puts("q pressed, quitting...");
}
default:
{
break;
}
}
}
int main(int argc, char const *argv[]) {
int key_file_descriptor;
struct termios raw;
struct termios original_terminal_state;
tcgetattr(key_file_descriptor, &original_terminal_state); // get terminal properties
memcpy(&raw, &original_terminal_state, sizeof(struct termios));
raw.c_lflag &= ~(ICANON | ECHO);//local modes, enable canonical mode and echo
// Setting a new line, then end of file
raw.c_cc[VEOL] = 1;//special characters
raw.c_cc[VEOF] = 2;
tcsetattr(key_file_descriptor, TCSANOW, &raw);
puts("Reading from keyboard");
puts("---------------------------");
puts("Press the arrow keys to move and q to quit");
char c;
while (!quit_requested)
{
if (read(key_file_descriptor, &c, 1) < 0)
{
perror("read char failed():");
exit(-1);
}
processKeyboardInput(c);
}
tcsetattr(key_file_descriptor, TCSANOW, &original_terminal_state);
puts("Exit");
return 0;
}
完成此操作后,我添加了ROS
内容以使用String
消息发送密钥:
#include <unistd.h>
#include <termios.h> // for keyboard input
#include <cstring>
#include <stdio.h>
#include "ros/ros.h"
#include "std_msgs/String.h"
bool quit_requested = false;
std::string processKeyboardInput (char c)
{
switch (c)
{
case 68:// Left arrow pressed
{
puts("Left pressed");
return ("left");
}
case 67://Right arrow pressed
{
puts("Right pressed");
return ("right");
}
case 65://Up arrow pressed
{
puts("Up pressed");
return ("forward");
}
case 66://Down arrow pressed
{
puts("Down pressed");
return ("backward");
}
case 'q'://Quit arrow pressed
{
quit_requested = true;
puts("q pressed, quitting...");
}
default:
{
return ("");
}
}
}
int main(int argc, char **argv) {
std::string cmd;
int key_file_descriptor;
char c;
int error;
struct termios raw;
struct termios original_terminal_state;
//std::string name = "key_teleop";
/**** INIT ROS STUFFS *****/
ros::init(argc, argv, "key_teleop");
std_msgs::String msg;
ros::NodeHandle n;
ros::Publisher key_pub = n.advertise<std_msgs::String>("key_teleop", 1000);
ros::Rate loop_rate(1);
/***************************/
tcgetattr(key_file_descriptor, &original_terminal_state); // get terminal properties
memcpy(&raw, &original_terminal_state, sizeof(struct termios));
raw.c_lflag &= ~(ICANON | ECHO);//local modes, enable canonical mode and echo
// Setting a new line, then end of file
raw.c_cc[VEOL] = 1;//special characters
raw.c_cc[VEOF] = 2;
tcsetattr(key_file_descriptor, TCSANOW, &raw);
puts("Reading from keyboard");
puts("---------------------------");
puts("Press the arrow keys to move and q to quit");
while (ros::ok() & (!quit_requested))
{
//if (read(key_file_descriptor, &c, 1) < 0)
error = read(key_file_descriptor, &c, 1);
if ( error < 0)//Process the error
{//TODO I get errors, not ROSify code doesn't, C / C++ code mixture issue??
if (error == EAGAIN)
puts ("EAGAIN");
else if (error == EBADF)
puts ("EBADF");
else if (error == EFAULT)
puts ("EFAULT");
else if (error == EINTR)
puts ("EINTR");
else if (error == EINVAL)
puts ("EINVAL");
else if (error == EIO)
puts ("EIO");
else if (error = EISDIR)
puts ("EISDIR");
perror("read char failed():");
exit(-1);
}
cmd = processKeyboardInput(c);
if (!cmd.empty())
{
msg.data = cmd;
key_pub.publish(msg);
ros::spinOnce();
//loop_rate.sleep();
}
}
tcsetattr(key_file_descriptor, TCSANOW, &original_terminal_state);
puts("Exit");
return 0;
}
创建CMakeLists.txt
和package.xml
后,我使用catkin_make
进行了编译。测试它现在不起作用,大多数时候我在read()
收到错误返回,它进入EISDIR
案例并打印出来。知道为什么现在我收到这个错误,而前一个c
例子正常工作?
提前致谢!
答案 0 :(得分:0)
在@Jonathan的推荐之后,我将标志-Wall -Werror -Wextra
添加到CMake
编译标志中,并发现了编译器抛出的下一条消息:
error: ‘key_file_descriptor’ may be used uninitialized in this function [-Werror=maybe-uninitialized]
我找到了此nice article并更改了我int key_file_descriptor
使用的STDIN_FILENO
。所以我已经将它全部替换为代码,现在正在工作!我也删除了比较拼写错误。谢谢你们!