PX4无人机 - 键盘控制飞行代码_px4飞控源代码-程序员宅基地

技术标签: 键盘控制  Gazebo  Offboard  无人机  PX4  

PX4无人机 - 键盘控制飞行代码

仿真效果
在这里插入图片描述

实机效果
由于图片限制5M以内,只能上传一小段了,整段视频请点击链接 Pixhawk 6c | 无人机 | 键盘控制无人机 | Offboard模式
在这里插入图片描述

核心: 发布 mavros/setpoint_velocity/cmd_vel_unstamped 话题,控制x y z三个方向的速度
运行前先运行PX4自带仿真,例如

roslaunch px4 mavros_posix_sitl.launch

接着运行以下代码(根据WHEELTEC麦克纳姆轮小车的键盘控制代码改写)

注意:

空格:降落

5 :开启offboard模式

6 :解锁,准备起飞

7 :起飞

控制顺序:
先按 5 开启offboard 模式
再按 6 解锁,会看到浆液开始转动
再按 7 起飞 (这里起飞后就不在 offboard 模式)
再按一次 5 切换到 offboard 模式(之后就可以通过键盘控制前后运动,左右旋转了)

控制运动键如下
i 键:前进
K 键:停止运动
, 键:后退
J 键:向左转
L键:向右转
R键:上升
F键:下降

运动速度调整键如下
常用键如下:
W 键:增加运动线速度
X 键:减少运动线速度
E 键:增加旋转角速度
C 键:减少旋转角速度

降落
空格键

#!/usr/bin/env python
# coding=utf-8

import rospy

from geometry_msgs.msg import Twist
from geometry_msgs.msg import PoseStamped
from mavros_msgs.srv import *
from mavros_msgs.msg import State
import math
import sys, select, termios, tty

# 空格:降落
# 5  :开启offboard模式
# 6  :解锁,准备起飞
# 7  :起飞

msg = """
Control Your Turtlebot!
---------------------------
Moving around:
   u    i    o
   j    k    l
   m    ,    .

q/z : increase/decrease max speeds by 10%
w/x : increase/decrease only linear speed by 10%
e/c : increase/decrease only angular speed by 10%
space key, k : force stop
anything else : stop smoothly
b : switch to OmniMode/CommonMode
CTRL-C to quit
"""
Omni = 0 #全向移动模式

#键值对应移动/转向方向
moveBindings = {
    
        'i':( 1, 0),
        'o':( 1,-1),
        'j':( 0, 1),
        'l':( 0,-1),
        'u':( 1, 1),
        ',':(-1, 0),
        '.':(-1, 1),
        'm':(-1,-1),
           }

#键值对应速度增量
speedBindings={
    
        'q':(1.1,1.1),
        'z':(0.9,0.9),
        'w':(1.1,1),
        'x':(0.9,1),
        'e':(1,  1.1),
        'c':(1,  0.9),
          }

#获取键值函数
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


speed = 0.2 #默认移动速度 m/s
turn  = 1   #默认转向速度 rad/s
#以字符串格式返回当前速度
def vels(speed,turn):
    return "currently:\tspeed %s\tturn %s " % (speed,turn)

sita = 0.0  # 朝向
z = 0
w = 0
zf = 1
# 回调函数:订阅无人机位姿
def pose_cb(m):
    global sita
    global z
    global w
    global zf
    z = m.pose.orientation.z
    w = m.pose.orientation.w
    # 计算朝向在x轴的上方还是下方
    if z*w > 0:
        zf = 1
    else:
        zf = -1
    sita = 2*math.acos(w)*180/math.pi
    # rospy.loginfo('%.2f\r',sita)

current_state = State()
# 回调函数:订阅mavros状态
def state_cb(state):
    global current_state
    current_state = state

#主函数
if __name__=="__main__":
    settings = termios.tcgetattr(sys.stdin) #获取键值初始化,读取终端相关属性
    
    rospy.init_node('turtlebot_teleop') #创建ROS节点
    pub = rospy.Publisher('mavros/setpoint_velocity/cmd_vel_unstamped', Twist, queue_size=5) #创建速度话题发布者
    # 订阅无人机位姿
    rospy.Subscriber('mavros/local_position/pose',PoseStamped, pose_cb)

    # 订阅mavros状态
    rospy.Subscriber('mavros/state',State,state_cb)

    # 定义起飞降落服务客户端(起飞,降落)
    setModeServer = rospy.ServiceProxy('mavros/set_mode',SetMode)

    armServer = rospy.ServiceProxy('/mavros/cmd/arming', CommandBool)

    x      = 0   #前进后退方向
    y      = 0   #左右移动方向
    z      = 0   #上下移动方向
    th     = 0   #转向/横向移动方向
    count  = 0   #键值不再范围计数
    target_speed = 0 #前进后退目标速度
    target_z_speed = 0 #上下运动目标速度
    target_turn  = 0 #转向目标速度
    control_speed = 0 #前进后退实际控制速度
    control_z_speed = 0 #上下运动实际控制速度
    control_turn  = 0 #转向实际控制速度
    try:
        print(msg) #打印控制说明
        print(vels(speed,turn)) #打印当前速度
        while(1):
            key = getKey() #获取键值

            # if key:
            #     print('key = ',key)
            
            #判断键值是否在移动/转向方向键值内
            # if key in moveBindings.keys():
            #     x  = moveBindings[key][0]
            #     th = moveBindings[key][1]
            #     count = 0

            if key == 'i':   #前进
                count = 0
                x = 1
                z = 0
            elif key == ',': #后退 
                count = 0
                x = -1
                z = 0
            elif key == 'j': #往左转
                count = 0
                th = 1
                z = 0
            elif key == 'l': #往右转
                count = 0
                th = -1
                z = 0
            elif key == 'r': #上升
                count = 0
                z = 1
            elif key == 'f': #下降
                count = 0
                z = -1
            #判断键值是否在速度增量键值内
            elif key in speedBindings.keys():
                speed = speed * speedBindings[key][0]
                turn  = turn  * speedBindings[key][1]
                count = 0
                print(vels(speed,turn)) #速度发生变化,打印出来

            #空键值/'k',相关变量置0
            elif key == 'k' :
                x  = 0
                y  = 0
                z  = 0
                th = 0
                control_speed = 0
                control_z_speed = 0
                control_turn  = 0

            # 降落
            elif key == ' ':
                print("Vehicle Land")
                setModeServer(custom_mode='AUTO.LAND')
            # 开启offboard模式
            elif key == '5':
                if current_state.mode != "OFFBOARD" :
                    setModeServer(custom_mode='OFFBOARD')
                    print("Offboard enabled")
            # 解锁,准备起飞
            elif key == '6':
                armServer(True) 
                print("Vehicle armed")
            # 起飞
            elif key == '7':
                print("Vehicle Takeoff")
                setModeServer(custom_mode='AUTO.TAKEOFF')

            #长期识别到不明键值,相关变量置0
            else:
                count = count + 1
                if count > 4:
                    x  = 0
                    y  = 0
                    z  = 0
                    th = 0
                if (key == '\x03'):
                    break

            #根据速度与方向计算目标速度
            target_speed = speed * x
            target_z_speed = speed * z
            target_turn  = turn * th

            #x方向平滑控制,计算前进后退实际控制速度
            if target_speed > control_speed:
                control_speed = min( target_speed, control_speed + 0.1 )
            elif target_speed < control_speed:
                control_speed = max( target_speed, control_speed - 0.1 )
            else:
                control_speed = target_speed
            
            #z方向平滑控制,实际控制速度
            if target_z_speed > control_z_speed:
                control_z_speed = min( target_z_speed, control_z_speed + 0.1 )
            elif target_z_speed < control_z_speed:
                control_z_speed = max( target_z_speed, control_z_speed - 0.1 )
            else:
                control_z_speed = target_z_speed

            #平滑控制,计算转向实际控制速度
            if target_turn > control_turn:
                control_turn = min( target_turn, control_turn + 0.5 )
            elif target_turn < control_turn:
                control_turn = max( target_turn, control_turn - 0.5 )
            else:
                control_turn = target_turn
         
            # 计算出y方向的sin值
            y_sita = math.sin(sita/180*math.pi)
            # 如果小于0,则改为正数
            if y_sita < 0:
                y_sita = -y_sita
            # 乘以y分量的正负(通过四元数z*w获得,z*w>0,y分量在x轴上方)
            y_sita = y_sita * zf

            twist = Twist()  #创建ROS速度话题变量
            twist.linear.x = control_speed * math.cos(sita/180*math.pi)
            twist.linear.y = control_speed * y_sita  # 朝向速度乘以y轴sin值
            twist.linear.z = control_z_speed
            twist.angular.x = 0
            twist.angular.y = 0
            twist.angular.z = control_turn

            pub.publish(twist) #ROS发布速度话题

    #运行出现问题则程序终止并打印相关错误信息
    except Exception as e:
        print(e)

    #程序结束前发布速度为0的速度话题
    finally:
        twist = Twist()
        twist.linear.x = 0; twist.linear.y = 0; twist.linear.z = 0
        twist.angular.x = 0; twist.angular.y = 0; twist.angular.z = control_turn
        pub.publish(twist)

    #程序结束前设置终端相关属性
    termios.tcsetattr(sys.stdin, termios.TCSADRAIN, settings)

跑实机的话,就不需要运行gazebo仿真了,直接运行mavros的px4.launch文件

roslaunch mavros px4.launch

再运行上面代码即可控制实机(我用的飞控是 Pixhawk6C)
实机操作有风险,请各位有十足把握后再尝试实机

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/HuangChen666/article/details/129642230

智能推荐

递归法:一个实数数列共有N项,已知ai=(ai-1 - ai+1) / 2 + d_已知ai,ai-1,如何求通项公式-程序员宅基地

文章浏览阅读2.5k次。题目描述:一个实数数列共有N项,已知ai = (a_i-1 - a_i+1) / 2 + d, (1 < i < N)(N < 60)键盘输入N,d, a1, an, n, 输出 an。进行简单的代换2ai - 2d = ai-1 - ai+1 ==>ai+1 = ai-1 - 2ai + 2d ==>ai = ai-2 - 2ai-1 + 2d 2 &..._已知ai,ai-1,如何求通项公式

【机器学习小常识】“parameters(参数)” 与 “hyperparameters(超参数)”的概念及区别详解_parameters参数-程序员宅基地

文章浏览阅读8.1k次,点赞8次,收藏32次。目录1、参数与超参数概念1.什么是参数2.什么是超参数2、二者有什么区别1.得到方式不同2.影响因素不同3.可控程度不同说在前面的话有些概念其实,很纠结,它到底是属于机器学习呢,还是属于深度学习呢?比如说,分类与回归,这个有些是很难界定的,有人说,它属于深度学习,又有人说,它属于机器学习。其实争论这些,好像并无太大意义,就像一个男生对一个姑娘宠溺的说:这天下..._parameters参数

TNS-12535: TNS: 操作超时-程序员宅基地

文章浏览阅读333次。今天一个服务器装了数据库后,本机可以登录了,但是其他机器登录就是提示 tns连接超时,不管是用tnsping ip还是tnsping sid命令,都是提示TNS-12535: TNS: 操作超时。原因:一定要把xp系统自身的防火墙关闭,而不是一些杀毒软件的防火墙关闭。 ..._linux tnsping timeout 12535

linux qt5启动失败,Qt Creator 启动失败 可能的解决办法-程序员宅基地

文章浏览阅读619次。blocking and unblocking mechanism for linux drivern code概念: 1> 阻塞操作 是指在执行设备操作时,若不能获得资源,则挂起进程直到满足操作条件后再进行操作.被挂起的进程进入休眠,被从调度器移走,直到条件满足: 2> 非阻塞操作 在 ...学习笔记:java线程安全首先得明白什么是线程安全: 线程安全是编程中的术语,指..._linux下无法启动qtcreator

python存txt不删之前_我怎样才能保存到一个.txt文件而不覆盖其中已经存在的所有内容?...-程序员宅基地

文章浏览阅读604次。我在空闲时间做一个应该是非常基本的操作系统。但是,我试图创建它以便您可以拥有任意多个用户,但是每次我创建一个新用户时,它都会删除旧用户。到目前为止,我有这个:def typer():print("Start typing to get started. Unfortunately, you cannot currently save your files.")typerCMD = input(" ..._txt存文件之前的留下来

请使用c++通过遗传算法解决旅行商问题-程序员宅基地

文章浏览阅读60次。我可以向您提供关于使用遗传算法解决旅行商问题的一些指导。首先,需要确定旅行商问题的地图数据,然后编写代码,创建一个遗传算法,然后对算法进行调优,以获得最佳路线。最后,将结果显示在地图上,以便查看最终路线。...

随便推点

打表法-程序员宅基地

文章浏览阅读4.8k次,点赞9次,收藏24次。今天见到了传说中的打表法,有人说这是流氓算法,但是我觉得这个也是非常牛逼的。下面就来说说这个打表法把,打表法对于某些用时较长的题目非常的有用。就是将我们要的结果打印到一个文本文档中,然后直接调用这个结果就可以了。在编译的时候就不用再程序里面计算,这样就省了很多时间,。是不是非常的牛逼呢,哈哈程序如下;#include<iostream>#include<..._打表法

Ribbon实战与原理剖析_ribbon原理-程序员宅基地

文章浏览阅读2.3k次,点赞2次,收藏11次。通过实现IRule接口可以自定义负载策略,主要的选择服务逻辑在 choose 方法中。}_ribbon原理

Centos 安装GPU并行lammps_centos lammps gpu-程序员宅基地

文章浏览阅读6.1k次,点赞6次,收藏16次。以下描述了如何在Centos服务器上安装GPU版本的lammps。安装环境目标属性系统Linux/CentOS 7.6CPU12*Intel Xeon CPU E5-2609 v3 @ 1.90GHzGPU2*NVIDIA Tesla K80/CUDA 8.0安装准备1. CUDA由于是安装GPU版本lammps,首先应确保系统安装有显卡所对..._centos lammps gpu

小米HR:说说对API有多少的理解? 看了后,和面试官扯皮,吹牛逼!绰绰有余!_能直接温hr是不是刷api的吗-程序员宅基地

文章浏览阅读2.9k次,点赞4次,收藏32次。目录什么是API?什么是API测试API测试的测试用例:API测试方法:如何进行API测试API测试的最佳做法:API测试检测到的错误类型API测试工具API测试的挑战结论:最后什么是API?API(全称Application Programming Interface)是两个单独的软件系统之间的通信和数据交换。实现API的软件系统包含可以由另一个软件系统执行的功能/子例程。什么是API测试API测试是一种用于验证API(应用程序编程接口)的._能直接温hr是不是刷api的吗

Android开发 入门篇(二) - 常用UI控件_能(textview、edittext、button、progressbar、alertdialog-程序员宅基地

文章浏览阅读915次,点赞2次,收藏7次。date: 2020-01-12 21:46:05文章目录控件ButtonTextViewEditTextImageViewProgressBarAlertDialogProgressDialog布局LenearLayoutandroid:layout_gravityandroid:layout_weightRelativeLayoutFrameLayout百分比布局其他自定义控件ListVie..._能(textview、edittext、button、progressbar、alertdialog、progressdialog、lis

python3.4中文版下载-Python 3.4 入门指南 官方中文版.pdf-程序员宅基地

文章浏览阅读1.2k次。【实例简介】【实例截图】【核心代码】CONTENTS1 开胃菜 22 使用 Python 解释器 42.1 调用 Python 解释器 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42.2 解释器及其环境 . . . . . . . . . . . . . . . . . . . . . . . . . . . . ...._python_3.4_入门指南(官方中文版).pdf

推荐文章

热门文章

相关标签