无人机按点飞行脚本

#!/usr/bin/env python

指定使用系统中的 python 解释器来运行该脚本(Linux 下 ROS 必须)

import rospy

ROS 的 Python 客户端库,用于节点、话题、服务等操作

import mavros

MAVROS 的 Python 接口库,用于和飞控(PX4/ArduPilot)通信

from geometry_msgs.msg import PoseStamped

引入带时间戳的位姿消息,用于发布位置控制指令

from mavros_msgs.msg import State

引入飞控状态消息(连接状态、模式、解锁状态等)

from mavros_msgs.srv import CommandBool, SetMode

引入解锁服务(CommandBool)和模式切换服务(SetMode)

from geometry_msgs.msg import Point

引入三维点类型(这里其实没用到,可以删)

---------------- 全局变量 ----------------

current_state = State()

保存当前飞控状态的全局变量

---------------- 回调函数 ----------------

def state_callback(state):

global current_state

声明使用全局变量 current_state

current_state = state

将订阅到的飞控状态保存到全局变量中

---------------- MAVROS 命名空间 ----------------

mavros.set_namespace()

设置 MAVROS 命名空间(一般为 /mavros)

des_pos = PoseStamped()

期望位置(目标点),用于 offboard 位置控制

---------------- 订阅 & 发布 ----------------

state_sub = rospy.Subscriber(

'mavros/state',

State,

callback=state_callback

)

订阅飞控状态话题 /mavros/state

position_pub = rospy.Publisher(

'mavros/setpoint_position/local',

PoseStamped,

queue_size=10

)

发布本地坐标系下的位置期望,用于 OFFBOARD 模式

---------------- 服务客户端 ----------------

arming_drone = rospy.ServiceProxy(

'/mavros/cmd/arming',

CommandBool

)

解锁/上锁飞控的服务客户端

setting_mode = rospy.ServiceProxy(

'mavros/set_mode',

SetMode

)

设置飞控模式(如 OFFBOARD)的服务客户端

---------------- 主控制函数 ----------------

def offb_control_sample():

print("Init Node: Offboard_node")

打印提示信息

rospy.init_node('Offboard_node', anonymous=True)

初始化 ROS 节点,节点名为 Offboard_node

prev_state = current_state

保存之前的状态(这里实际上没用到)

rate = rospy.Rate(20.0)

设置循环频率为 20Hz(OFFBOARD 至少 2Hz,推荐 >10Hz)

-------- 初始目标点 --------

des_pos.pose.position.x = 0

des_pos.pose.position.y = 0

des_pos.pose.position.z = 1

设置初始目标位置:起飞到高度 1 米

-------- 等待飞控连接 --------

while(not rospy.is_shutdown() and not current_state.connected):

print("Waiting for FCU connection")

如果还未连接飞控,持续等待

rate.sleep()

按 20Hz 睡眠,避免死循环

print("FCU connected")

成功连接飞控

-------- OFFBOARD 前必须先发送一段 setpoint --------

for i in range(60):

发送 60 次位置指令(约 3 秒)

if(rospy.is_shutdown()):

break

如果 ROS 被关闭,跳出循环

position_pub.publish(des_pos)

发布目标位置

rate.sleep()

print("Switching to offboard Mode")

提示:开始切换 OFFBOARD 模式

setting_mode(base_mode=0, custom_mode="OFFBOARD")

请求切换飞控模式为 OFFBOARD

last_request = rospy.get_rostime()

记录当前时间

while((rospy.get_rostime() - last_request) < rospy.Duration(2.0)):

持续 2 秒发布 setpoint,防止 OFFBOARD 失效

position_pub.publish(des_pos)

rate.sleep()

print("Arming the drone on offboard Mode")

提示:在 OFFBOARD 模式下解锁电机

if current_state.mode == "OFFBOARD":

确认当前模式是 OFFBOARD

arming_drone(True)

解锁飞控(电机上电)

-------- 起飞并悬停 --------

print("Take off to Point 1")

last_request = rospy.get_rostime()

while((rospy.get_rostime() - last_request) < rospy.Duration(8.0)):

持续 8 秒向飞控发送起飞目标点

position_pub.publish(des_pos)

rate.sleep()

-------- 飞往第二个点 --------

print("Fly to Point 2")

des_pos.pose.position.x = 0

des_pos.pose.position.y = 0.5

des_pos.pose.position.z = 1

修改目标点坐标

last_request = rospy.get_rostime()

while((rospy.get_rostime() - last_request) < rospy.Duration(2.0)):

position_pub.publish(des_pos)

rate.sleep()

-------- 飞往第三个点 --------

print("Fly to Point 3")

des_pos.pose.position.x = 0.5

des_pos.pose.position.y = 0.5

des_pos.pose.position.z = 1

last_request = rospy.get_rostime()

while((rospy.get_rostime() - last_request) < rospy.Duration(2.0)):

position_pub.publish(des_pos)

rate.sleep()

-------- 飞往第四个点 --------

print("Fly to Point 4")

des_pos.pose.position.x = 0.5

des_pos.pose.position.y = 0

des_pos.pose.position.z = 1

last_request = rospy.get_rostime()

while((rospy.get_rostime() - last_request) < rospy.Duration(2.0)):

position_pub.publish(des_pos)

rate.sleep()

-------- 返回起点 --------

print("Fly back to Point 1")

des_pos.pose.position.x = 0

des_pos.pose.position.y = 0

des_pos.pose.position.z = 1

last_request = rospy.get_rostime()

while((rospy.get_rostime() - last_request) < rospy.Duration(3.0)):

position_pub.publish(des_pos)

rate.sleep()

-------- 任务结束 --------

print("Vehicle Landing")

注意:这里只是打印,没有真正发送降落指令

print("Mission End")

---------------- 程序入口 ----------------

if name == 'main':

try:

offb_control_sample()

调用主控制函数

except rospy.ROSInterruptException:

pass

捕获 ROS 中断异常,防止程序崩溃

🔍 关键理解点(帮你快速吃透)

  • OFFBOARD 必须持续发布 setpoint(否则会自动退出)

  • 解锁前必须已经是 OFFBOARD

  • PoseStamped 使用的是 本地坐标系(ENU)

  • 这个程序 没有真正降落,只是结束了任务

发 setpoint(>2Hz)

↓

切 OFFBOARD

↓

确认 mode == OFFBOARD

↓

解锁(Arming)

相关推荐
AC100740919 小时前
【德信康】无人机射频功放多频段切换模块
无人机
我喜欢就喜欢20 小时前
无人机正射色差:镶嵌线 shp + 羽化接缝实操思路
无人机·遥感
小O的算法实验室2 天前
IEEE IOTJ,基于点云网络辅助粒子群算法+三维无人机基站部署
无人机
雨晨源码(同名B站)2 天前
深度学习毕业设计选题推荐:基于卷积神经网络的无人机影像建筑裂缝裂纹检测分类与分割系统(LeNet-5 二分类模型、GCN-Res50分割模型)
深度学习·信息可视化·分类·cnn·毕业设计·无人机·课程设计
沃达德软件3 天前
智慧无人机图像识别分析技术
人工智能·目标检测·计算机视觉·目标跟踪·视觉检测·无人机
AiNightVision3 天前
电力巡检夜视方案选型指南——无人机/机器人/固定监测三种场景怎么选
人工智能·科技·车载系统·机器人·无人机·边缘计算·视频
sxgzzn3 天前
如何利用无人机提升光伏巡检效率?
运维·重构·无人机·开关柜局放在线监测·光伏运维管理系统
迅翼SwiftWing3 天前
论文分享 | 固定翼无人机深失速栖停,NMPC 跟踪的稳定性从哪来?轨迹优化与时变终端设计
无人机
FPGA小迷弟4 天前
FPGA 与无人机:从飞控实时性到智能载荷的硬件加速实践
人工智能·ai·fpga开发·架构·无人机·ai编程
zzlyx994 天前
无电子身份无人机的精准侦测与高端反制
无人机