目录
前言&&过程分析
当我们需要使用键盘控制机器人的时候,通常,分为几步。
第一步
首先要会读取键盘事件,并判断哪个键盘按下去了,返回按下的按键键值。
这里有检测键盘按下事件的帖子:C++监听键盘事件(读取键盘输入)_qqliuzhitong的博客-CSDN博客
第二步
然后,我们的上位机(nanopi k2)根据按下去的按键的键值,发布一个指令消息,来广播这个键值。
第三步
接着,我们用下位机,另一台nanopi k2或者是一个arduino板子,来订阅这个指令消息。
第四步
最后,下位机(nanopi k2或者arduino板子)判断指令,根据指令进行相应,控制电机或者舵机,这样就完成了一个从上位机按下键盘按键到最终机器人做出反应的一个流程。
PC端(上位机)代码
#include <ros/ros.h>
#include <std_msgs/UInt16.h>
#include <termio.h>
#include <stdio.h>
#define KEYCODE_W 0x77
#define KEYCODE_A 0x61
#define KEYCODE_S 0x73
#define KEYCODE_D 0x64
#define KEYCODE_I 0x69
#define KEYCODE_J 0x6A
#define KEYCODE_K 0x6B
#define KEYCODE_L 0x6C
#define KEYCODE_SPACE 0x20
#define KEYCODE_A_CAP 0x41
#define KEYCODE_D_CAP 0x44
#define KEYCODE_S_CAP 0x53
#define KEYCODE_W_CAP 0x57
int key_command=0x00;
void scanKeyboard()
{
struct termios new_settings;
struct termios stored_settings;
//设置终端参数
tcgetattr(0,&stored_settings);
new_settings = stored_settings;
new_settings.c_lflag &= (~ICANON);
new_settings.c_cc[VTIME] = 0;
tcgetattr(0,&stored_settings);
new_settings.c_cc[VMIN] = 1;
tcsetattr(0,TCSANOW,&new_settings);
key_command = getchar();
tcsetattr(0,TCSANOW,&stored_settings);
}
int main(int argc, char *argv[])
{
setlocale(LC_ALL,"");
ros::init(argc,argv,"keyboard_control");
ros::NodeHandle nh;
ros::Publisher key_publisher = nh.advertise<std_msgs::UInt16>("key_command",10);
std_msgs::UInt16 key_c;//w:1 a:2 s:3 d:4 i:5 j:6 k:7 l:8
while(1){
scanKeyboard();
switch(key_command)
{
case KEYCODE_W:
key_c.data=1;
key_publisher.publish(key_c);
break;
case KEYCODE_A:
key_c.data=2;
key_publisher.publish(key_c);
break;
case KEYCODE_S:
key_c.data=3;
key_publisher.publish(key_c);
break;
case KEYCODE_D:
key_c.data=4;
key_publisher.publish(key_c);
break;
case KEYCODE_I:
key_c.data=5;
key_publisher.publish(key_c);
break;
case KEYCODE_J:
key_c.data=6;
key_publisher.publish(key_c);
break;
case KEYCODE_K:
key_c.data=7;
key_publisher.publish(key_c);
break;
case KEYCODE_L:
key_c.data=8;
key_publisher.publish(key_c);
break;
default:
key_c.data=1;
key_publisher.publish(key_c);
break;
}
}
}
cmakelists.txt文件:
add_executable(keyboard src/keyboard.cpp)
target_link_libraries(keyboard
${catkin_LIBRARIES}
)
远程机器人(下位机)代码
#include <ros/ros.h>
#include <serial/serial.h>
#include <iostream>
#include <std_msgs/UInt16.h>
//创建一个serial类
serial::Serial sp;
uint8_t hello1[12]={0xfa,0x10,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0xf1};
uint8_t hello2[12]={0xfa,0x10,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0xf2};
uint8_t hello3[12]={0xfa,0x10,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0xf3};
uint8_t hello4[12]={0xfa,0x10,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0xf4};
uint8_t hello5[12]={0xfa,0x10,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0xf5};
uint8_t hello6[12]={0xfa,0x10,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0xf6};
uint8_t hello7[12]={0xfa,0x10,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0xf7};
uint8_t hello8[12]={0xfa,0x10,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0xf8};
uint8_t hello9[12]={0xfa,0x10,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0xf9};
uint8_t hello10[12]={0xfa,0x10,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0xfa};
uint8_t hello11[12]={0xfa,0x10,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0xfb};
void command_Callback(const std_msgs::UInt16& key_c)
{
ros::Rate loop_rate(1);
switch(key_c.data)
{
case 1:
sp.write(hello1, 12);
break;
case 2:
sp.write(hello2, 12);
break;
case 3:
sp.write(hello3, 12);
break;
case 4:
sp.write(hello4, 12);
break;
case 5:
sp.write(hello5, 12);
break;
case 6:
sp.write(hello6, 12);
break;
case 7:
sp.write(hello7, 12);
break;
case 8:
sp.write(hello8, 12);
break;
case 9:
sp.write(hello9, 12);
loop_rate.sleep();
sp.write(hello10, 12);
loop_rate.sleep();
sp.write(hello11, 12);
loop_rate.sleep();
break;
default:;
}
// ROS_INFO("hello");
}
int main(int argc, char** argv)
{
ros::init(argc, argv, "serial_port");
ros::NodeHandle n;
//创建serial timeout
serial::Timeout to = serial::Timeout::simpleTimeout(100);
//设置要打开的串口名称
sp.setPort("/dev/ttyUSB0");
//设置串口通信的波特率
sp.setBaudrate(9600);
//串口设置timeout
sp.setTimeout(to);
try
{
//打开串口
sp.open();
}
catch(serial::IOException& e)
{
ROS_ERROR_STREAM("Unable to open port.");
return -1;
}
//判断串口是否打开成功
if(sp.isOpen())
{
ROS_INFO_STREAM("/dev/ttyUSB0 is opened.");
}
else
{
return -1;
}
ros::Subscriber pose_sub=n.subscribe("key_command",10,command_Callback);
//
// if(ros::ok())
// {
// uint8_t hello1[12]={0xfa,0x10,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0xfb};
//
// uint8_t hello2[12]={0xfa,0x10,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0xfb};
// uint8_t hello3[12]={0xfa,0x10,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0xfb};
//把数据发送
// sp.write(hello1, 12);
// loop_rate.sleep();
// sp.write(hello2, 12);
// loop_rate.sleep();
// sp.write(hello3, 12);
// loop_rate.sleep();
// }
//关闭串口
// sp.close();
ros::spin();
sp.close();
return 0;
}
工程代码链接: