十、键盘控制无人机 · 下(multirotor_keyboard_control.py解读)

2023-10-14 18:40

本文主要是介绍十、键盘控制无人机 · 下(multirotor_keyboard_control.py解读),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

笔记来源于开源项目:基于PX4和ROS的无人机仿真平台

来源于开源项目:GAAS


目录

一、解读启动通信的multirotor_keyboard_control.py脚本

1、库函数以及消息

2、变量及其初始值

3、主函数外的getKey()和print_msg()函数

4、main主函数

(1)、初始值的设立

(2)、while循环监听键盘的输入做出反应

二、打开程序,查看节点话题关系图


 

 

一、解读启动通信的multirotor_keyboard_control.py脚本

import rospy
from geometry_msgs.msg import Twist
import sys, select, os
import tty, termios
from std_msgs.msg import StringMAX_LINEAR = 10
MAX_ANG_VEL = 0.1
LINEAR_STEP_SIZE = 0.01
ANG_VEL_STEP_SIZE = 0.01cmd_vel_mask = False
ctrl_leader = Falsemsg2all = """
Control Your XTDrone!
To all drones  (press g to control the leader)
---------------------------1   2   3   4   5   6   7   8   9   0w       r    t   y        ia    s    d       g       j    k    lx       v    b   n        ,w/x : increase/decrease forward velocity 
a/d : increase/decrease leftward velocity
i/, : increase/decrease upward velocity
j/l : increase/decrease orientation
r   : return home
t/y : arm/disarm
v/n : takeoff/land
b   : offboard
s/k : hover and remove the mask of keyboard control
0~9 : extendable mission(eg.different formation configuration)this will mask the keyboard control
g   : control the leader
CTRL-C to quit
"""msg2leader = """
Control Your XTDrone!
To the leader  (press g to control all drones)
---------------------------1   2   3   4   5   6   7   8   9   0w       r    t   y        ia    s    d       g       j    k    lx       v    b   n        ,w/x : increase/decrease forward velocity
a/d : increase/decrease leftward velocity
i/, : increase/decrease upward velocity
j/l : increase/decrease orientation
r   : return home
t/y : arm/disarm
v/n : takeoff(disenabled now)/land
b   : offboard
s/k : hover and remove the mask of keyboard control
0~9 : extendable mission(eg.different formation configuration)this will mask the keyboard control
g   : control all drones
CTRL-C to quit
"""e = """
Communications Failed
"""def getKey():tty.setraw(sys.stdin.fileno())rlist, _, _ = select.select([sys.stdin], [], [], 0.1)if rlist:key = sys.stdin.read(1)else:key = ''termios.tcsetattr(sys.stdin, termios.TCSADRAIN, settings)return keydef print_msg():if ctrl_leader:print(msg2leader)else:print(msg2all)      if __name__=="__main__":settings = termios.tcgetattr(sys.stdin)multirotor_type = sys.argv[1]multirotor_num = int(sys.argv[2])control_type = sys.argv[3]if multirotor_num == 18:formation_configs = ['waiting', 'cuboid', 'sphere', 'diamond']elif multirotor_num == 9:formation_configs = ['waiting', 'cube', 'pyramid', 'triangle']elif multirotor_num == 6:formation_configs = ['waiting', 'T', 'diamond', 'triangle']cmd= String()twist = Twist()   rospy.init_node('multirotor_keyboard_multi_control')if control_type == 'vel':multi_cmd_vel_flu_pub = [None]*multirotor_nummulti_cmd_pub = [None]*multirotor_numfor i in range(multirotor_num):multi_cmd_vel_flu_pub[i] = rospy.Publisher('/xtdrone/'+multirotor_type+'_'+str(i)+'/cmd_vel_flu', Twist, queue_size=10)multi_cmd_pub[i] = rospy.Publisher('/xtdrone/'+multirotor_type+'_'+str(i)+'/cmd',String,queue_size=10)leader_cmd_vel_flu_pub = rospy.Publisher("/xtdrone/leader/cmd_vel_flu", Twist, queue_size=10)leader_cmd_pub = rospy.Publisher("/xtdrone/leader/cmd", String, queue_size=10)else:multi_cmd_accel_flu_pub = [None]*multirotor_nummulti_cmd_pub = [None]*multirotor_numfor i in range(multirotor_num):multi_cmd_accel_flu_pub[i] = rospy.Publisher('/xtdrone/'+multirotor_type+'_'+str(i)+'/cmd_accel_flu', Twist, queue_size=10)multi_cmd_pub[i] = rospy.Publisher('/xtdrone/'+multirotor_type+'_'+str(i)+'/cmd',String,queue_size=10)leader_cmd_accel_flu_pub = rospy.Publisher("/xtdrone/leader/cmd_accel_flu", Twist, queue_size=10)leader_cmd_pub = rospy.Publisher("/xtdrone/leader/cmd", String, queue_size=10)forward  = 0.0leftward  = 0.0upward  = 0.0angular = 0.0print_msg()while(1):key = getKey()if key == 'w' :forward = forward + LINEAR_STEP_SIZEprint_msg()if control_type == 'vel':print("currently:\t forward vel %.2f\t leftward vel %.2f\t upward vel %.2f\t angular %.2f " % (forward, leftward, upward, angular))else:print("currently:\t forward vel %.2f\t leftward vel %.2f\t upward vel %.2f\t angular %.2f " % (forward, leftward, upward, angular))elif key == 'x' :forward = forward - LINEAR_STEP_SIZEprint_msg()if control_type == 'vel':print("currently:\t forward vel %.2f\t leftward vel %.2f\t upward vel %.2f\t angular %.2f " % (forward, leftward, upward, angular))else:print("currently:\t forward vel %.2f\t leftward vel %.2f\t upward vel %.2f\t angular %.2f " % (forward, leftward, upward, angular))elif key == 'a' :leftward = leftward + LINEAR_STEP_SIZEprint_msg()if control_type == 'vel':print("currently:\t forward vel %.2f\t leftward vel %.2f\t upward vel %.2f\t angular %.2f " % (forward, leftward, upward, angular))else:print("currently:\t forward vel %.2f\t leftward vel %.2f\t upward vel %.2f\t angular %.2f " % (forward, leftward, upward, angular))elif key == 'd' :leftward = leftward - LINEAR_STEP_SIZEprint_msg()if control_type == 'vel':print("currently:\t forward vel %.2f\t leftward vel %.2f\t upward vel %.2f\t angular %.2f " % (forward, leftward, upward, angular))else:print("currently:\t forward vel %.2f\t leftward vel %.2f\t upward vel %.2f\t angular %.2f " % (forward, leftward, upward, angular))elif key == 'i' :upward = upward + LINEAR_STEP_SIZEprint_msg()if control_type == 'vel':print("currently:\t forward vel %.2f\t leftward vel %.2f\t upward vel %.2f\t angular %.2f " % (forward, leftward, upward, angular))else:print("currently:\t forward vel %.2f\t leftward vel %.2f\t upward vel %.2f\t angular %.2f " % (forward, leftward, upward, angular))elif key == ',' :upward = upward - LINEAR_STEP_SIZEprint_msg()if control_type == 'vel':print("currently:\t forward vel %.2f\t leftward vel %.2f\t upward vel %.2f\t angular %.2f " % (forward, leftward, upward, angular))else:print("currently:\t forward vel %.2f\t leftward vel %.2f\t upward vel %.2f\t angular %.2f " % (forward, leftward, upward, angular))elif key == 'j':angular = angular + ANG_VEL_STEP_SIZEprint_msg()print("currently:\t forward vel %.2f\t leftward vel %.2f\t upward vel %.2f\t angular %.2f " % (forward, leftward, upward, angular))elif key == 'l':angular = angular - ANG_VEL_STEP_SIZEprint_msg()print("currently:\t forward vel %.2f\t leftward vel %.2f\t upward vel %.2f\t angular %.2f " % (forward, leftward, upward, angular))elif key == 'r':cmd = 'AUTO.RTL'print_msg()print('Returning home')elif key == 't':cmd = 'ARM'print_msg()print('Arming')elif key == 'y':cmd = 'DISARM'print_msg()print('Disarming')elif key == 'v':cmd = 'AUTO.TAKEOFF'cmd = ''print_msg()#print('Takeoff mode is disenabled now')elif key == 'b':cmd = 'OFFBOARD'print_msg()print('Offboard')elif key == 'n':cmd = 'AUTO.LAND'print_msg()print('Landing')elif key == 'g':ctrl_leader = not ctrl_leaderprint_msg()elif key in ['k', 's']:cmd_vel_mask = Falseforward   = 0.0leftward   = 0.0upward   = 0.0angular  = 0.0cmd = 'HOVER'print_msg()print("currently:\t forward vel %.2f\t leftward vel %.2f\t upward vel %.2f\t angular %.2f " % (forward, leftward, upward, angular))print('Hover')else:for i in range(10):if key == str(i):print(str(i))cmd = formation_configs[i]print_msg()print(cmd)cmd_vel_mask = Trueif (key == '\x03'):breakif forward > MAX_LINEAR:forward = MAX_LINEARelif forward < -MAX_LINEAR:forward = -MAX_LINEARif leftward > MAX_LINEAR:leftward = MAX_LINEARelif leftward < -MAX_LINEAR:leftward = -MAX_LINEARif upward > MAX_LINEAR:upward = MAX_LINEARelif upward < -MAX_LINEAR:upward = -MAX_LINEARif angular > MAX_ANG_VEL:angular = MAX_ANG_VELelif angular < -MAX_ANG_VEL:angular = - MAX_ANG_VELtwist.linear.x = forward; twist.linear.y = leftward ; twist.linear.z = upwardtwist.angular.x = 0.0; twist.angular.y = 0.0;  twist.angular.z = angularfor i in range(multirotor_num):if ctrl_leader:if control_type == 'vel':leader_cmd_vel_flu_pub.publish(twist)else:leader_cmd_aceel_flu_pub.publish(twist)leader_cmd_pub.publish(cmd)else:if not cmd_vel_mask:if control_type == 'vel':multi_cmd_vel_flu_pub[i].publish(twist)   else:multi_cmd_accel_flu_pub[i].publish(twist)multi_cmd_pub[i].publish(cmd)cmd = ''termios.tcsetattr(sys.stdin, termios.TCSADRAIN, settings)

1、库函数以及消息

import rospy
from geometry_msgs.msg import Twist
import sys, select, os
import tty, termios
from std_msgs.msg import String
  • from geometry_msgs.msg import Twist:几何数据类型的功能包里面引入Twist话题消息

  • from std_msgs.msg import String:标准数据类型功能包里面引入String话题消息

  • select模块:专注于I/O多路复用,要理解select.select模块其实主要就是要理解它的参数, 以及其三个返回值

  • tty模块:终端控制功能(tty在linux中就是终端的意思)

  • termios模块:此模块提供了针对tty I/O 控制的 POSIX 调用的接口。此模块中的所有函数均接受一个文件描述符 fd 作为第一个参数。

  • 另外的rospy、sys、os模块就不说了

下面结合具体的函数进行分析

2、变量及其初始值

MAX_LINEAR = 10
MAX_ANG_VEL = 0.1
LINEAR_STEP_SIZE = 0.01
ANG_VEL_STEP_SIZE = 0.01cmd_vel_mask = False
ctrl_leader = Falsemsg2all = """
Control Your XTDrone!
To all drones  (press g to control the leader)
---------------------------1   2   3   4   5   6   7   8   9   0w       r    t   y        ia    s    d       g       j    k    lx       v    b   n        ,w/x : increase/decrease forward velocity 
a/d : increase/decrease leftward velocity
i/, : increase/decrease upward velocity
j/l : increase/decrease orientation
r   : return home
t/y : arm/disarm
v/n : takeoff/land
b   : offboard
s/k : hover and remove the mask of keyboard control
0~9 : extendable mission(eg.different formation configuration)this will mask the keyboard control
g   : control the leader
CTRL-C to quit
"""msg2leader = """
Control Your XTDrone!
To the leader  (press g to control all drones)
---------------------------1   2   3   4   5   6   7   8   9   0w       r    t   y        ia    s    d       g       j    k    lx       v    b   n        ,w/x : increase/decrease forward velocity
a/d : increase/decrease leftward velocity
i/, : increase/decrease upward velocity
j/l : increase/decrease orientation
r   : return home
t/y : arm/disarm
v/n : takeoff(disenabled now)/land
b   : offboard
s/k : hover and remove the mask of keyboard control
0~9 : extendable mission(eg.different formation configuration)this will mask the keyboard control
g   : control all drones
CTRL-C to quit
"""e = """
Communications Failed
"""
  • MAX_LINEAR=10:表示飞机最大的线速度是10
  • MAX_ANG_VEL=0.1:表示飞机最大的角速度是0.1
  • LINEAR_STEP_SIZE=0.01:表示飞机改变线速度的时候每次改变0.01
  • ANG_STEP_SIZE=0.01:表示飞机改变角速度的时候每次改变0.01
  • cmd_vel_mask=False:
  • ctrl_leader=False:用来切换控制领导者模式
  • msg2all=“......”:To all drones,由于这个控制飞机的程序是基于多机的,因此这个控制模式是所有飞机一起动的控制模式
  • msg2leader=“......”:To the leader,这个控制模式是只控制领头的飞机
  • e=Communications Failed:出现错误后返回的信息

3、主函数外的getKey()和print_msg()函数

getKey()函数主要涉及监听键盘的按键输入(这个整的看不懂写的是啥意思)

大概就是键盘上按了什么按键,它就读出来是是什么按键

def getKey():tty.setraw(sys.stdin.fileno())rlist, _, _ = select.select([sys.stdin], [], [], 0.1)if rlist:key = sys.stdin.read(1)else:key = ''termios.tcsetattr(sys.stdin, termios.TCSADRAIN, settings)return key
  • fileno是个文件描述符,文件描述符是一个低级概念,它是一个整数,代表一个打开的文件,也就是说,每打开一个文件都有一个唯一的文件描述符。在在Unix中,按照惯例,三个文件描述符0、1和2分别代表标准输入,标准输出和标准错误。而在Python中输入sys.stdin.fileno()输出为0。
  • tty模块定义可函数tty.setraw:tty.setraw(fdwhen=termios.TCSAFLUSH);这个函数将文件描述符 fd 的模式更改为 raw 。如果 when 被省略,则默认为 termios.TCSAFLUSH ,并传递给termios.tcsetattr()
  • sys.stdin:(在Python中的输出是:<_io.TextIOWrapper name='<stdin>' mode='r' encoding='UTF-8'>)
  • select.select()方法接收并监控3个通信列表,进程指定内核监听哪些文件描述符(最多监听1024个fd)的哪些事件, 第一个是所有的输入的data,就是指外部发过来的数据,第2个是监控和接收所有要发出去的data(outgoing data),第3个监控错误信息。
fd_r_list, fd_w_list, fd_e_list = select.select(rlist, wlist, xlist, [timeout]) 
参数: 可接受四个参数(前三个必须)
rlist: wait until ready for reading
wlist: wait until ready for writing
xlist: wait for an “exceptional condition”
timeout: 超时时间
返回值:三个列表
select方法用来监视文件描述符(当文件描述符条件不满足时,select会阻塞),当某个文件描述符状态改变后,会返回三个列表
1、当参数1 序列中的fd满足“可读”条件时,则获取发生变化的fd并添加到fd_r_list中
2、当参数2 序列中含有fd时,则将该序列中所有的fd添加到 fd_w_list中
3、当参数3 序列中的fd发生错误时,则将该发生错误的fd添加到 fd_e_list中
4、当超时时间为空,则select会一直阻塞,直到监听的句柄发生变化当超时时间 = n(正整数)时,那么如果监听的句柄均无任何变化,则select会阻塞n秒,之后返回三个空列表,如果监听的句柄有变化,则直接执行。
  • 如果序列中的fd满足“可读”条件时,则获取发生变化的fd并添加到rlist中,然后读取出key的值
  • termios.tcsetattr(fdwhenattributes)

    根据 attributes 列表设置文件描述符 fd 的 tty 属性,该列表即 tcgetattr() 所返回的对象。 when 参数确定何时改变属性: TCSANOW 表示立即改变,TCSADRAIN 表示在传输所有队列输出后再改变,或 TCSAFLUSH 表示在传输所有队列输出并丢失所有队列输入后再改变。

关于函数print_msg()还是很好理解的,只要控制了ctrl_leader的输出是True还是False,就可以控制输出是全局控制模式还是领导控制模式:

def print_msg():if ctrl_leader:print(msg2leader)else:print(msg2all)    

4、main主函数

if __name__=="__main__":settings = termios.tcgetattr(sys.stdin)multirotor_type = sys.argv[1]multirotor_num = int(sys.argv[2])control_type = sys.argv[3]if multirotor_num == 18:formation_configs = ['waiting', 'cuboid', 'sphere', 'diamond']elif multirotor_num == 9:formation_configs = ['waiting', 'cube', 'pyramid', 'triangle']elif multirotor_num == 6:formation_configs = ['waiting', 'T', 'diamond', 'triangle']cmd= String()twist = Twist()   rospy.init_node('multirotor_keyboard_multi_control')if control_type == 'vel':multi_cmd_vel_flu_pub = [None]*multirotor_nummulti_cmd_pub = [None]*multirotor_numfor i in range(multirotor_num):multi_cmd_vel_flu_pub[i] = rospy.Publisher('/xtdrone/'+multirotor_type+'_'+str(i)+'/cmd_vel_flu', Twist, queue_size=10)multi_cmd_pub[i] = rospy.Publisher('/xtdrone/'+multirotor_type+'_'+str(i)+'/cmd',String,queue_size=10)leader_cmd_vel_flu_pub = rospy.Publisher("/xtdrone/leader/cmd_vel_flu", Twist, queue_size=10)leader_cmd_pub = rospy.Publisher("/xtdrone/leader/cmd", String, queue_size=10)else:multi_cmd_accel_flu_pub = [None]*multirotor_nummulti_cmd_pub = [None]*multirotor_numfor i in range(multirotor_num):multi_cmd_accel_flu_pub[i] = rospy.Publisher('/xtdrone/'+multirotor_type+'_'+str(i)+'/cmd_accel_flu', Twist, queue_size=10)multi_cmd_pub[i] = rospy.Publisher('/xtdrone/'+multirotor_type+'_'+str(i)+'/cmd',String,queue_size=10)leader_cmd_accel_flu_pub = rospy.Publisher("/xtdrone/leader/cmd_accel_flu", Twist, queue_size=10)leader_cmd_pub = rospy.Publisher("/xtdrone/leader/cmd", String, queue_size=10)forward  = 0.0leftward  = 0.0upward  = 0.0angular = 0.0print_msg()while(1):key = getKey()if key == 'w' :forward = forward + LINEAR_STEP_SIZEprint_msg()if control_type == 'vel':print("currently:\t forward vel %.2f\t leftward vel %.2f\t upward vel %.2f\t angular %.2f " % (forward, leftward, upward, angular))else:print("currently:\t forward vel %.2f\t leftward vel %.2f\t upward vel %.2f\t angular %.2f " % (forward, leftward, upward, angular))elif key == 'x' :forward = forward - LINEAR_STEP_SIZEprint_msg()if control_type == 'vel':print("currently:\t forward vel %.2f\t leftward vel %.2f\t upward vel %.2f\t angular %.2f " % (forward, leftward, upward, angular))else:print("currently:\t forward vel %.2f\t leftward vel %.2f\t upward vel %.2f\t angular %.2f " % (forward, leftward, upward, angular))elif key == 'a' :leftward = leftward + LINEAR_STEP_SIZEprint_msg()if control_type == 'vel':print("currently:\t forward vel %.2f\t leftward vel %.2f\t upward vel %.2f\t angular %.2f " % (forward, leftward, upward, angular))else:print("currently:\t forward vel %.2f\t leftward vel %.2f\t upward vel %.2f\t angular %.2f " % (forward, leftward, upward, angular))elif key == 'd' :leftward = leftward - LINEAR_STEP_SIZEprint_msg()if control_type == 'vel':print("currently:\t forward vel %.2f\t leftward vel %.2f\t upward vel %.2f\t angular %.2f " % (forward, leftward, upward, angular))else:print("currently:\t forward vel %.2f\t leftward vel %.2f\t upward vel %.2f\t angular %.2f " % (forward, leftward, upward, angular))elif key == 'i' :upward = upward + LINEAR_STEP_SIZEprint_msg()if control_type == 'vel':print("currently:\t forward vel %.2f\t leftward vel %.2f\t upward vel %.2f\t angular %.2f " % (forward, leftward, upward, angular))else:print("currently:\t forward vel %.2f\t leftward vel %.2f\t upward vel %.2f\t angular %.2f " % (forward, leftward, upward, angular))elif key == ',' :upward = upward - LINEAR_STEP_SIZEprint_msg()if control_type == 'vel':print("currently:\t forward vel %.2f\t leftward vel %.2f\t upward vel %.2f\t angular %.2f " % (forward, leftward, upward, angular))else:print("currently:\t forward vel %.2f\t leftward vel %.2f\t upward vel %.2f\t angular %.2f " % (forward, leftward, upward, angular))elif key == 'j':angular = angular + ANG_VEL_STEP_SIZEprint_msg()print("currently:\t forward vel %.2f\t leftward vel %.2f\t upward vel %.2f\t angular %.2f " % (forward, leftward, upward, angular))elif key == 'l':angular = angular - ANG_VEL_STEP_SIZEprint_msg()print("currently:\t forward vel %.2f\t leftward vel %.2f\t upward vel %.2f\t angular %.2f " % (forward, leftward, upward, angular))elif key == 'r':cmd = 'AUTO.RTL'print_msg()print('Returning home')elif key == 't':cmd = 'ARM'print_msg()print('Arming')elif key == 'y':cmd = 'DISARM'print_msg()print('Disarming')elif key == 'v':cmd = 'AUTO.TAKEOFF'cmd = ''print_msg()#print('Takeoff mode is disenabled now')elif key == 'b':cmd = 'OFFBOARD'print_msg()print('Offboard')elif key == 'n':cmd = 'AUTO.LAND'print_msg()print('Landing')elif key == 'g':ctrl_leader = not ctrl_leaderprint_msg()elif key in ['k', 's']:cmd_vel_mask = Falseforward   = 0.0leftward   = 0.0upward   = 0.0angular  = 0.0cmd = 'HOVER'print_msg()print("currently:\t forward vel %.2f\t leftward vel %.2f\t upward vel %.2f\t angular %.2f " % (forward, leftward, upward, angular))print('Hover')else:for i in range(10):if key == str(i):print(str(i))cmd = formation_configs[i]print_msg()print(cmd)cmd_vel_mask = Trueif (key == '\x03'):breakif forward > MAX_LINEAR:forward = MAX_LINEARelif forward < -MAX_LINEAR:forward = -MAX_LINEARif leftward > MAX_LINEAR:leftward = MAX_LINEARelif leftward < -MAX_LINEAR:leftward = -MAX_LINEARif upward > MAX_LINEAR:upward = MAX_LINEARelif upward < -MAX_LINEAR:upward = -MAX_LINEARif angular > MAX_ANG_VEL:angular = MAX_ANG_VELelif angular < -MAX_ANG_VEL:angular = - MAX_ANG_VELtwist.linear.x = forward; twist.linear.y = leftward ; twist.linear.z = upwardtwist.angular.x = 0.0; twist.angular.y = 0.0;  twist.angular.z = angularfor i in range(multirotor_num):if ctrl_leader:if control_type == 'vel':leader_cmd_vel_flu_pub.publish(twist)else:leader_cmd_aceel_flu_pub.publish(twist)leader_cmd_pub.publish(cmd)else:if not cmd_vel_mask:if control_type == 'vel':multi_cmd_vel_flu_pub[i].publish(twist)   else:multi_cmd_accel_flu_pub[i].publish(twist)multi_cmd_pub[i].publish(cmd)cmd = ''termios.tcsetattr(sys.stdin, termios.TCSADRAIN, settings)

(1)、初始值的设立

  • settings = termios.tcgetattr(sys.stdin):这个和键盘的输入有关

  • multirotor_type = sys.argv[1]:返回输入执行Python文件时候后面跟着的第一个参数:飞机的机型

    multirotor_num = int(sys.argv[2]):返回第二个参数:飞机的数量

    control_type = sys.argv[3]:返回第三个参数:控制的类型(是速度vel控制,还是加速度控制)

  • 现在针对多机情况:如果飞机数量是18,9,6,这里就有对应的formation_config(飞行结构配置,飞行队形把应该)
  • 设置消息:cmd、twist
  • rospy.init_node('multirotor_keyboard_multi_control'):初始化节点,节点的名字叫做multirotor_keyboard_multi_control(无人机键盘的多样控制)

  • if-else control_type:读取上面的参数之后可以确定control_type的值,然后通过这个值(vel或者空)来判断是速度控制还是加速度控制。我们选取速度(vel)控制来分析:for i in range(multirotor_num)表示对每一架飞机都进行创建发布控制指令消息String以及速度控制消息Twist的Publisher,然后对于领导飞机有专门创建发布领导飞机的控制指令消息String以及速度控制消息Twist的Publisher

  • 初始化 forward、leftward、upward 、angular四个方向的速度都为0.0这个基础值

  • print_msg()在终端输出对应的键盘控制模式图

(2)、while循环监听键盘的输入做出反应

key  = getKey()表示的key得到为键盘按键的值

下面的程序几乎一个样子,选择一个来具体分析一下:

if key == 'w' :forward = forward + LINEAR_STEP_SIZEprint_msg()if control_type == 'vel':print("currently:\t forward vel %.2f\t leftward vel %.2f\t upward vel %.2f\t angular %.2f " % (forward, leftward, upward, angular))else:print("currently:\t forward vel %.2f\t leftward vel %.2f\t upward vel %.2f\t angular %.2f " % (forward, leftward, upward, angular))

当有按键按下为”w“的时候,forword的值就是原来的值再加上按一次就加上一次速度增加的步长

然后在输出一次现在的控制模式

如果现在的控制模式是速度模式,那么就在终端输出此刻的f,l,u,a的值

elif key == 'r':cmd = 'AUTO.RTL'print_msg()print('Returning home')

当有按键按下为”r“的时候就把cmd的模式调整为'AUTO.RTL',还记得这个cmd吗,前面cmd=String(),然后是通过这个消息发布出去的。那你还记得multirotor_communication.py这个上一篇教程解读里面不是有几个订阅消息的subscriber嘛,比如,就是这里的cmd发布出去指令的string()消息,然后上一篇的通讯连接中的cmd订阅到然后做出分析的。

这两个可以提出来给大家看一下:

        elif key == 'g':ctrl_leader = not ctrl_leaderprint_msg()elif key in ['k', 's']:cmd_vel_mask = Falseforward   = 0.0leftward   = 0.0upward   = 0.0angular  = 0.0cmd = 'HOVER'print_msg()print("currently:\t forward vel %.2f\t leftward vel %.2f\t upward vel %.2f\t angular %.2f " % (forward, leftward, upward, angular))print('Hover')

这一段代码是配置多机的飞机队伍的时候用到的,看看就行了:

感觉源代码的格式有点问题,我就调整了一下空格:

        else:for i in range(10):if key == str(i):print(str(i))cmd = formation_configs[i]print_msg()print(cmd)cmd_vel_mask = Trueif (key == '\x03'):break

下面是一大段对最大值的比较,就是不能超过最大值

同时,这里也定义了数据消息Twist的值:

twist.linear.x = forward; twist.linear.y = leftward ; twist.linear.z = upwardtwist.angular.x = 0.0; twist.angular.y = 0.0;  twist.angular.z = angular

然后每一只飞机都发布出去新的位置消息(之前那个是在循环外面的,是创建好了要发布所有的节点的消息以及初始位置的消息的Publisher):

        for i in range(multirotor_num):if ctrl_leader:if control_type == 'vel':leader_cmd_vel_flu_pub.publish(twist)else:leader_cmd_aceel_flu_pub.publish(twist)leader_cmd_pub.publish(cmd)else:if not cmd_vel_mask:if control_type == 'vel':multi_cmd_vel_flu_pub[i].publish(twist)   else:multi_cmd_accel_flu_pub[i].publish(twist)multi_cmd_pub[i].publish(cmd)

最后的这个一条也和键盘的输入有关吧,反正不是很明白:

 termios.tcsetattr(sys.stdin, termios.TCSADRAIN, settings)

二、打开程序,查看节点话题关系图

 

 

 

 

 

 

 

 

 

这篇关于十、键盘控制无人机 · 下(multirotor_keyboard_control.py解读)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/212395

相关文章

Spring Boot集成/输出/日志级别控制/持久化开发实践

《SpringBoot集成/输出/日志级别控制/持久化开发实践》SpringBoot默认集成Logback,支持灵活日志级别配置(INFO/DEBUG等),输出包含时间戳、级别、类名等信息,并可通过... 目录一、日志概述1.1、Spring Boot日志简介1.2、日志框架与默认配置1.3、日志的核心作用

C语言中%zu的用法解读

《C语言中%zu的用法解读》size_t是无符号整数类型,用于表示对象大小或内存操作结果,%zu是C99标准中专为size_t设计的printf占位符,避免因类型不匹配导致错误,使用%u或%d可能引发... 目录size_t 类型与 %zu 占位符%zu 的用途替代占位符的风险兼容性说明其他相关占位符验证示

flask库中sessions.py的使用小结

《flask库中sessions.py的使用小结》在Flask中Session是一种用于在不同请求之间存储用户数据的机制,Session默认是基于客户端Cookie的,但数据会经过加密签名,防止篡改,... 目录1. Flask Session 的基本使用(1) 启用 Session(2) 存储和读取 Se

Linux系统之lvcreate命令使用解读

《Linux系统之lvcreate命令使用解读》lvcreate是LVM中创建逻辑卷的核心命令,支持线性、条带化、RAID、镜像、快照、瘦池和缓存池等多种类型,实现灵活存储资源管理,需注意空间分配、R... 目录lvcreate命令详解一、命令概述二、语法格式三、核心功能四、选项详解五、使用示例1. 创建逻

浅析Spring如何控制Bean的加载顺序

《浅析Spring如何控制Bean的加载顺序》在大多数情况下,我们不需要手动控制Bean的加载顺序,因为Spring的IoC容器足够智能,但在某些特殊场景下,这种隐式的依赖关系可能不存在,下面我们就来... 目录核心原则:依赖驱动加载手动控制 Bean 加载顺序的方法方法 1:使用@DependsOn(最直

解读GC日志中的各项指标用法

《解读GC日志中的各项指标用法》:本文主要介绍GC日志中的各项指标用法,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、基础 GC 日志格式(以 G1 为例)1. Minor GC 日志2. Full GC 日志二、关键指标解析1. GC 类型与触发原因2. 堆

Java设计模式---迭代器模式(Iterator)解读

《Java设计模式---迭代器模式(Iterator)解读》:本文主要介绍Java设计模式---迭代器模式(Iterator),具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,... 目录1、迭代器(Iterator)1.1、结构1.2、常用方法1.3、本质1、解耦集合与遍历逻辑2、统一

MySQL之InnoDB存储页的独立表空间解读

《MySQL之InnoDB存储页的独立表空间解读》:本文主要介绍MySQL之InnoDB存储页的独立表空间,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录1、背景2、独立表空间【1】表空间大小【2】区【3】组【4】段【5】区的类型【6】XDES Entry区结构【

MySQL主从复制与读写分离的用法解读

《MySQL主从复制与读写分离的用法解读》:本文主要介绍MySQL主从复制与读写分离的用法,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、主从复制mysql主从复制原理实验案例二、读写分离实验案例安装并配置mycat 软件设置mycat读写分离验证mycat读

Spring如何使用注解@DependsOn控制Bean加载顺序

《Spring如何使用注解@DependsOn控制Bean加载顺序》:本文主要介绍Spring如何使用注解@DependsOn控制Bean加载顺序,具有很好的参考价值,希望对大家有所帮助,如有错误... 目录1.javascript 前言2. 代码实现总结1. 前言默认情况下,Spring加载Bean的顺