【PX4二次开发】PX4 offboard 模式发布 推力+姿态

写在前面

由于项目需要,最近想发布推力+姿态指令给PX4控制器,然后由PX4跟踪给定的控制指令。我注意到,所需的推力是一个归一化的值,所以我想当然的将所需推力与最大推力的比值作为归一化推力发布出去。不过,在测试时候发现,发布的这个归一化推力根本无法让无人机起飞,于是我就这一问题展开了资料的查询和分析……

PX4 offboard 模式发布推力+姿态

我们先进行一个简单的小测试让无人机实现悬停,此时推力为无人机的重力,姿态指令为0。
参考官方mavros写的python源码如下:

px4_node_test.py

#!/usr/bin/env python
# -*- coding: utf-8 -*-

import rospy
from geometry_msgs.msg import PoseStamped, TwistStamped, Twist, Pose, Quaternion, Point
from mavros_msgs.msg import State, AttitudeTarget
from sensor_msgs.msg import Imu
from std_msgs.msg import Bool
from mavros_msgs.srv import CommandBool, CommandBoolRequest, SetMode, SetModeRequest
import tf
import math
import numpy as np

PI = 3.14159
THRUST_FULL = 31

# sdf参数:
m = 1.5
thrust = m * 9.8
motor_constant = 5.84e-06
min_motor_vel = 0
max_motor_vel = 1100
THRUST_FULL = 4 * motor_constant * max_motor_vel * max_motor_vel

current_state = State()

# Callback functions
def state_cb(msg):
    global current_state
    current_state = msg

# Function to convert Euler angles to quaternion
def euler_to_quat(roll, pitch, yaw):
    q = tf.transformations.quaternion_from_euler(roll, pitch, yaw)
    quat = Quaternion()
    quat.x = q[0]
    quat.y = q[1]
    quat.z = q[2]
    quat.w = q[3]
    return quat

# Function to scale thrust
def thrust_scale(thrust):
    print("THRUST_FULL:",THRUST_FULL)
    if thrust >= THRUST_FULL:
        thrust = THRUST_FULL

    # 每个电机推力的归一化
    # THR_MDL_FAC = 1 时使用!
    thrust_normalized = thrust/THRUST_FULL
    print("thrust_normalized:",thrust_normalized)

    # 每个电机转速的归一化
    # THR_MDL_FAC = 0 时使用!
    # thrust_normalized = (np.sqrt(thrust /4 /motor_constant)-min_motor_vel)/(max_motor_vel-min_motor_vel)
    # print("thrust_normalized:",thrust_normalized)

    return thrust_normalized


def main():
    rospy.init_node("offb_node_py")

    state_sub = rospy.Subscriber("mavros/state", State, callback=state_cb)
    imu_sub = rospy.Subscriber("mavros/imu/data", Imu)
    pos_sub = rospy.Subscriber("mavros/local_position/pose", PoseStamped)
    vel_sub = rospy.Subscriber("mavros/global_position/raw/gps_vel", TwistStamped)
    local_pos_pub = rospy.Publisher("mavros/setpoint_position/local", PoseStamped, queue_size=10)
    setvel_pub = rospy.Publisher("mavros/setpoint_velocity/cmd_vel_unstamped", Twist, queue_size=10)
    start_pub = rospy.Publisher("start_time", Bool, queue_size=10)
    refv_sub = rospy.Subscriber("reference", Twist)
    refp_sub = rospy.Subscriber("reference2", Pose)

    rospy.wait_for_service("/mavros/cmd/arming")
    arming_client = rospy.ServiceProxy("mavros/cmd/arming", CommandBool)
    rospy.wait_for_service("/mavros/set_mode")
    set_mode_client = rospy.ServiceProxy("mavros/set_mode", SetMode)

    raw_pub_att = rospy.Publisher('mavros/setpoint_raw/attitude', AttitudeTarget, queue_size=10)

    rate = rospy.Rate(20.0)
    while not rospy.is_shutdown() and not current_state.connected:
        rospy.loginfo("Waiting for FCU connection...")
        rate.sleep()

    offb_set_mode = SetModeRequest()
    offb_set_mode.custom_mode = "OFFBOARD"

    arm_cmd = CommandBoolRequest()
    arm_cmd.value = True

    raw_att = AttitudeTarget()
    raw_att.type_mask = 7  # Ignore body rate
    raw_att.thrust = thrust_scale(thrust)  # Initial thrust
    raw_att.orientation = euler_to_quat(0, 0, 0)  # Level orientation

    last_request = rospy.Time.now()

    while not rospy.is_shutdown():
        if current_state.mode != "OFFBOARD" and (rospy.Time.now() - last_request > rospy.Duration(5.0)):
            set_mode_resp = set_m
<think>好的,用户想找关于PX4 Offboard模式下用Python实现控制的示例代码。首先,我需要回忆一下PX4Offboard模式是什么。Offboard模式允许外部程序通过MAVLink或ROS2等协议向飞控发送控制指令,比如位置、速度或姿态设定值。这对于自主飞行或集成到外部系统非常重要。 根据提供的引用,引用[1]提到了px4_ros_com中的offboard_control.cpp,但这是C++的ROS2示例。用户需要的是Python代码,所以可能需要找类似但用Python实现的例子。不过官方资源可能更倾向于C++或ROS2,Python的示例可能较少。不过,引用[5]提到了MAVROS的Offboard示例,虽然原文是C++,但MAVROS也支持Python,所以可能需要引导用户使用MAVROS的Python客户端库。 接下来,我需要检查用户提供的引用中有没有直接相关的Python示例。看起来引用[1]、[3]、[4]都是关于C++或ROS2的,引用[5]是C++的MAVROS代码。因此,可能需要建议用户参考MAVROS的Python实现,或者使用dronekit等其他库。 另外,用户可能需要配置uORB桥接,如引用[3]提到的urtps_bridge_topics.yaml,确保相关消息被正确接收和发送。不过Python可能通过MAVLink直接通信,而不需要RTPS桥接,这取决于使用的协议。 考虑到PX4官方可能没有提供Python的Offboard示例,但社区可能有相关资源。比如,使用pymavlink库来发送SET_POSITION_TARGET_LOCAL_NED或其他MAVLink消息。需要指导用户如何建立连接,切换模式,发送指令,并处理安全措施,如引用[5]提到的Offboard模式危险性,必须要有手动接管的方法。 最后,可能需要综合这些信息,提供一个简单的Python示例,使用pymavlink连接到飞控,切换到Offboard模式,并发送位置设定值。同时提醒用户测试时注意安全,先在仿真环境中验证,比如使用Gazebo(如引用[2]提到的启动命令)。</think>### PX4 Offboard模式Python控制示例说明 在PX4Offboard模式下,**Python主要通过MAVLink协议与飞控通信**。以下是基于`pymavlink`库的核心实现步骤: 1. **建立MAVLink连接** 使用串口或UDP连接飞控: ```python from pymavlink import mavutil # 通过UDP连接仿真器(如Gazebo) master = mavutil.mavlink_connection('udp:127.0.0.1:14550') ``` 2. **切换至Offboard模式** 发送模式切换指令前需先发送设定点: ```python master.mav.set_position_target_local_ned_send( time_boot_ms=0, target_system=1, target_component=1, coordinate_frame=mavutil.mavlink.MAV_FRAME_LOCAL_NED, type_mask=0x0C00, # 仅控制位置 x=0, y=0, z=-5, # 设定初始目标高度5米 vx=0, vy=0, vz=0 ) # 发送模式切换命令 master.mav.set_mode_send( target_system=1, base_mode=mavutil.mavlink.MAV_MODE_FLAG_CUSTOM_MODE_ENABLED, custom_mode='OFFBOARD' ) ``` 3. **持续发送控制指令** Offboard模式需要**至少2Hz的持续指令流**,否则触发失效保护: ```python import time while True: master.mav.set_position_target_local_ned_send(...) time.sleep(0.1) # 控制频率10Hz ``` [^1]: 官方C++示例中展示了Offboard模式的核心通信逻辑,Python实现需采用类似的消息结构 --- ### 关键配置注意事项 1. **飞控参数配置** 检查`COM_RCL_EXCEPT`参数是否允许Offboard模式,并设置失效保护动作: ```bash param set COM_RCL_EXCEPT 4 # 允许Offboard模式下遥控器失效保护 param set NAV_RCL_ACT 1 # 失控后自动返航 ``` 2. **仿真测试流程** 使用Gazebo启动仿真环境(参考引用[2]): ```bash make px4_sitl gazebo_iris ``` 建议通过QGroundControl观察飞行状态变化[^4] --- ###
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值