由于项目需要,完成一个测试demo, 本次从dronekit中发送mavlink消息给飞控,飞控接收发来的wp信息,然后进行修改供程序使用。
首先祭出测试视频 dronekit_arudpilot_test

dronekit

  1. 首先从copter.cpp中找到到对应的函数,如下图所示:在这里插入图片描述
  2. 跳转进去
    在这里插入图片描述
  3. 再次套娃,可以得到下图:
    在这里插入图片描述
  4. 该函数中的最后一个函数 handleMessage();在这里插入图片描述
  5. 涉及的文件主要是 GCS_mavlink.cpp , 找到其中 headleMessage() 即可。里面是通过switch语句来判断对应的消息ID的, 如下面代码所示:


case MAVLINK_MSG_ID_SET_POSITION_TARGET_GLOBAL_INT:    // MAV ID: 86
    {
        // decode packet
        mavlink_set_position_target_global_int_t packet;
        mavlink_msg_set_position_target_global_int_decode(&msg, &packet);

        // exit if vehicle is not in Guided mode or Auto-Guided mode
        if (!copter.flightmode->in_guided_mode()) {
            break;
        }

        bool pos_ignore      = packet.type_mask & MAVLINK_SET_POS_TYPE_MASK_POS_IGNORE;
        bool vel_ignore      = packet.type_mask & MAVLINK_SET_POS_TYPE_MASK_VEL_IGNORE;
        bool acc_ignore      = packet.type_mask & MAVLINK_SET_POS_TYPE_MASK_ACC_IGNORE;
        bool yaw_ignore      = packet.type_mask & MAVLINK_SET_POS_TYPE_MASK_YAW_IGNORE;
        bool yaw_rate_ignore = packet.type_mask & MAVLINK_SET_POS_TYPE_MASK_YAW_RATE_IGNORE;

        // exit immediately if acceleration provided
        if (!acc_ignore) {
            break;
        }

        // extract location from message
        Location loc;
        if (!pos_ignore) {
            // sanity check location
            if (!check_latlng(packet.lat_int, packet.lon_int)) {
                break;
            }
            Location::AltFrame frame;
            if (!mavlink_coordinate_frame_to_location_alt_frame((MAV_FRAME)packet.coordinate_frame, frame)) {
                // unknown coordinate frame
                break;
            }
            loc = {packet.lat_int, packet.lon_int, int32_t(packet.alt_100), frame};
        }

        // prepare yaw
        float yaw_cd = 0.0f;
        bool yaw_relative = false;
        float yaw_rate_cds = 0.0f;
        if (!yaw_ignore) {
            yaw_cd = ToDeg(packet.yaw) _ 100.0f;
            yaw_relative = packet.coordinate_frame == MAV_FRAME_BODY_NED || packet.coordinate_frame == MAV_FRAME_BODY_OFFSET_NED;
        }
        if (!yaw_rate_ignore) {
            yaw_rate_cds = ToDeg(packet.yaw_rate) _ 100.0f;
        }

        // send targets to the appropriate guided mode controller
        if (!pos_ignore && !vel_ignore) {
            // convert Location to vector from ekf origin for posvel controller
            if (loc.get_alt_frame() == Location::AltFrame::ABOVE_TERRAIN) {
                // posvel controller does not support alt-above-terrain
                break;
            }
            Vector3f pos_neu_cm;
            if (!loc.get_vector_from_origin_NEU(pos_neu_cm)) {
                break;
            }
            copter.mode_guided.set_destination_posvel(pos_neu_cm, Vector3f(packet.vx _ 100.0f, packet.vy _ 100.0f, -packet.vz _ 100.0f), !yaw_ignore, yaw_cd, !yaw_rate_ignore, yaw_rate_cds, yaw_relative);
        } else if (pos_ignore && !vel_ignore) {
            copter.mode_guided.set_velocity(Vector3f(packet.vx _ 100.0f, packet.vy _ 100.0f, -packet.vz _ 100.0f), !yaw_ignore, yaw_cd, !yaw_rate_ignore, yaw_rate_cds, yaw_relative);
        } else if (!pos_ignore && vel_ignore) {
            copter.mode_guided.set_destination(loc, !yaw_ignore, yaw_cd, !yaw_rate_ignore, yaw_rate_cds, yaw_relative);
        }

        break;

大概流程就是判断接收到的数据是什么类型,然后进行相应的控制(控制速度,控制航点,还是速度和位置都控制)。需要修改的地方就显而易见了。


需要注意的点:


  1. 本次实验采用的是dronekit脚本的形式完成mavnlink消息的解析。在dronekit中 不要采用simple_go函数,该函数好像用的是manvlink_command, 而不是mavlink_message,导致捕获不到消息。
  2. dronekit脚本在处理 goto_position_target_global_int的时候,pymavlink解析出错,报错为python中的struct.pack需要整形的数据,但是发送的不是。最后采用强制数据类型转换完成。
  3. dronekit脚本附赠如下:

import time
import random
import dronekit
import math
from pymavlink import mavutil
import threading
vehicle = dronekit.connect(‘127.0.0.1:14550’,wait_ready=True)
master =  mavutil.mavlink_connection(‘udp:127.0.0.1:{}’.format(14551))
master.wait_heartbeat()

def prearm_check():
    if vehicle.mode.name != “STABILIZE”:
        vehicle.mode = “STABILIZE”
        print(“waiting for changing the mode to stabilize…”)
        vehicle.wait_for_mode(“STABILIZE”)
        print(“changing mode to stabilize successfully…”)
    while not vehicle.gps_0.fix_type:
        time.sleep(0.5)
    print(“gps check passed…”)
    while not vehicle.ekf_ok:
        time.sleep(0.5)
    print(“ekf check passed…”)

def goto_position_target_global_int(alocation):
    “””
    Send SET_POSITION_TARGET_GLOBAL_INT command to request the vehicle fly to a specified location.
    “””
    msg = vehicle.message_factory.set_position_target_global_int_encode(
        0,       # time_boot_ms (not used)
        0, 0,    # target system, target component
        mavutil.mavlink.MAV_FRAME_GLOBAL_RELATIVE_ALT_INT, # frame
        0b0000111111111000, # type_mask (only speeds enabled)
        alocation.lat_1e7, # lat_int - X Position in WGS84 frame in 1e7 _ meters
        alocation.lon_1e7, # lon_int - Y Position in WGS84 frame in 1e7 _ meters
        alocation.alt, # alt - Altitude in meters in AMSL altitude, not WGS84 if absolute or relative, above terrain if GLOBAL_TERRAIN_ALT_INT
        0, # X velocity in NED frame in m/s
        0, # Y velocity in NED frame in m/s
        0, # Z velocity in NED frame in m/s
        0, 0, 0, # afx, afy, afz acceleration (not supported yet, ignored in GCS_Mavlink)
        0, 0)    # yaw, yaw_rate (not supported yet, ignored in GCS_Mavlink)
    # send command to vehicle
    vehicle.send_mavlink(msg)

def goto_position_target_local_ned(vehicle, north, east, down):
    “””
    Send SET_POSITION_TARGET_LOCAL_NED command to request the vehicle fly to a specified
    location in the North, East, Down frame.
    “””
    msg = vehicle.message_factory.set_position_target_local_ned_encode(
        0,  # time_boot_ms (not used)
        0, 0,  # target system, target component
        mavutil.mavlink.MAV_FRAME_LOCAL_NED,  # frame
        0b0000111111111000,  # type_mask (only positions enabled)
        north, east, down,
        0, 0, 0,  # x, y, z velocity in m/s  (not used)
        0, 0, 0,  # x, y, z acceleration (not supported yet, ignored in GCS_Mavlink)
        0, 0)  # yaw, yaw_rate (not supported yet, ignored in GCS_Mavlink)
    # send command to vehicle
    vehicle.send_mavlink(msg)

def is_fly_land_reset():
    if vehicle.armed == True:
        while vehicle.mode != “RTL”:
            vehicle.wait_for_mode(“RTL”)
        print(“Set mode to RTL…”)
    while vehicle.armed != False:
        time.sleep(1)
    vehicle.wait_for_mode(“STABILIZE”)
    print(“Vehicle reset OK…”)


def get_location_metres(original_location, dNorth, dEast):
    earth_radius = 6378137.0  # Radius of “spherical” earth
    # Coordinate offsets in radians
    dLat = dNorth / earth_radius
    dLon = dEast / (earth_radius _ math.cos(math.pi _ original_location.lat / 180))

    # New position in decimal degrees
    newlat = original_location.lat + (dLat _ 180 / math.pi)
    newlon = original_location.lon + (dLon * 180 / math.pi)
    if type(original_location) is dronekit.LocationGlobal:
        targetlocation = dronekit.LocationGlobal(newlat, newlon, original_location.alt)
    elif type(original_location) is dronekit.LocationGlobalRelative:
        targetlocation = dronekit.LocationGlobalRelative(newlat, newlon, original_location.alt)
    else:
        raise Exception(“Invalid Location object passed”)

    return targetlocation

def goto(dNorth, dEast, gotoFunction=vehicle.simple_goto):

    currentLocation = vehicle.location.global_relative_frame
    targetLocation = get_location_metres(currentLocation, dNorth, dEast)
    # targetDistance = get_distance_metres(currentLocation, targetLocation)
    gotoFunction(targetLocation)

delay_time = 60
def time_schedule():
    while True:
        if ‘i’ == input():
            delay_time  = delay_time + 0.1
        elif ‘k’ == input():
            delay_time = delay_time - 0.1
        else:
            print(“Wrong input… Nothing changed…”)
        if delay_time < 0:
            delay_time = 0.1
        elif delay_time > 60:
            delay_time = 60
        print(delay_time)
        time.sleep(0.1)

if __name__ == ‘__main__‘:
    is_fly_land_reset()
    prearm_check()
    vehicle.mode = “GUIDED”
    vehicle.wait_for_mode(“GUIDED”)

    while vehicle.armed == False:
        vehicle.arm(True)
    print(“vehicle armed…”)

    # vehicle.simple_takeoff(alt=12)
    vehicle.wait_simple_takeoff(alt= 12,epsilon=2)
    while vehicle.location.local_frame.down > -8:
        print(vehicle.location.local_frame.down)
        time.sleep(0.5)
    print(“Begin to navigation…”)
    while True:
        lat = 39.1036 + random.random() _ 32 _ 1e-4
        lon = 117.16 + random.random() _ 66 _ 1e-4
        alt = 30
        location_send = dronekit.LocationGlobalRelative(lat, lon, alt)
        # vehicle.simple_goto(location=location_send)
        # goto(-100, -130, goto_position_target_global_int)
        goto_position_target_global_int(location_send)
        # goto_position_target_local_ned(vehicle,5,2,-20)
        # master.mav.set_position_target_global_int_send(
        #     0,
        #     master.target_system,
        #     master.target_component,
        #     6,
        #     lat_1e7,
        #     lon_1e7,
        #     alt,
        #     0,0,0,
        #     0,0,0,
        #     0,0,0, force_mavlink1=True)
        print(“target lat=%f,\t lon=%f,\t current lat=%f,\t lon=%f”
              %(lat, lon, vehicle.location.global_frame.lat, vehicle.location.global_frame.lon))
        random_time = random.random()*9.9+0.1
        time.sleep(random_time)