Mavros: MAVLinkメッセージをQGroundControlに送信します

作成日 2016年07月14日  ·  14コメント  ·  ソース: mavlink/mavros

やあ!

私は飛行機シミュレーターを持っています。それはROSトピックを通していくつかの飛行情報を送ります。 それを受け取り、MAVLinkを使用してQGroundControlに送信したいと思います。

それがどのように機能するかをテストするために、私は偽のバッテリーステータス(mavros_msgs / BatteryStatus.msg)で1つのメッセージを送信しようとしました:

1-まず、mavros_nodeをgcs_url = udp://:[email protected] :14551で実行します。
2-バッテリーメッセージを送信することになっているノードを実行します。

#include <ros/ros.h>
#include <mavros_msgs/BatteryStatus.h>

int main(int argc, char *argv[])

{
    ros::init(argc, argv, "battery_node");
    ros::NodeHandle n;
    ros::Publisher battery_pub = n.advertise<mavros_msgs::BatteryStatus>("/mavros/battery", 1000);
    ros::Rate loop_rate(10);

    while (ros::ok())
    {
        mavros_msgs::BatteryStatus baterry_msg;

        baterry_msg.voltage = 5;
        baterry_msg.current = 0.5;
        baterry_msg.remaining = 0.36;

        battery_pub.publish(baterry_msg);

        ros::spinOnce();
        loop_rate.sleep();
    }
    return 0;
}

3-QGroundControlをUDPに接続します:127.0.0.1:14551

...そして何も起こりません= /

mavrosを「ブリッジ」として使用して127.0.0.1:14540を介してMAVProxyでシミュレーションを実行すると、飛行機が認識されるため、mavrosとQGCの間の接続は機能すると確信しています。

私は何が間違っているのですか?

Ubuntu 14、ROS Indigo、QGC2.9.7を使用しています。

事前にどうもありがとうございました、
パブロ

question

最も参考になるコメント

また、メッセージを送信できるMAVConnInterfaceクラスがあるため、カスタムgcs_bridgeを作成することをお勧めします。

auto gcs_link = MAVConnInterface::open_url("udp-b://@");

mavlink::common::msg::HEARTBEAT hb{};
// fill hb

gcs_link->send_message_ignore_drop(hb);

全てのコメント14件

sys_status :ご覧のとおり、mavrosは_publisher_であり、サブスクライバーではありません。

こんにちは、

ご回答ありがとうございます。 よく理解していれば、このメッセージは送信できず、ROSでのみ受信して表示されますよね?

次に、_mavlink / to_を使用してこれらのメッセージを送信できますか?
どうすればいいですか?

再度、感謝します!

mavlink/toは、GCSではなくFCUにメッセージ送信します。

ただし、 gcs_bridgeノードとmavlink/fromトピックを使用することはできます。

また会ったね、

わかりました。単純なハートビートメッセージを送信するようにコードを変更しました。

#include <ros/ros.h>
#include <mavros_msgs/Mavlink.h>

int main(int argc, char **argv){

    ros::init(argc, argv, "hertbeat_publisher");
    ros::NodeHandle n;

    ros::Publisher example_pub = n.advertise<mavros_msgs::Mavlink>("/mavlink/from", 1000);
    ros::Rate loop_rate(1); // 1 Hz

    mavros_msgs::Mavlink mavlink_msg;

    mavlink_msg.len = 2;
    mavlink_msg.sysid = 1;
    mavlink_msg.compid = 1;
    mavlink_msg.msgid = 0;

    std::vector<long unsigned int> payload64(7, 0);

    mavlink_msg.payload64 = payload64;

    while (ros::ok())
    {
        mavlink_msg.header.stamp = ros::Time::now();
        if (mavlink_msg.seq < 255){
            mavlink_msg.seq++;
        }
        else {mavlink_msg.seq = 0;}

        // publish message
        example_pub.publish(mavlink_msg);

        ros::spinOnce();
        loop_rate.sleep();
    }
    return 0;
}

1-mavros_nodeをfcu_url = udp://:14540 @およびgcs_url = udp://:[email protected] :14551で実行すると、次のようになります。

[ INFO] [1468659493.280504313]: FCU URL: udp://:14540@
[ INFO] [1468659493.289025098]: udp0: Bind address: 0.0.0.0:14540
[ INFO] [1468659493.289457240]: GCS URL: udp://:[email protected]:14551
[ INFO] [1468659493.289691565]: udp1: Bind address: 0.0.0.0:14570
[ INFO] [1468659493.289824558]: udp1: Remote address: 127.0.0.1:14551
...
[ INFO] [1468659494.906066742]: MAVROS started. MY ID 1.240, TARGET ID 1.1

2-gcs_url:= 'udp://@127.0.0.1'を指定してgcs_bridgeを実行すると、次のようになります。

[ INFO] [1468659758.392659411]: udp0: Bind address: 0.0.0.0:14555
[ INFO] [1468659758.392800665]: udp0: Remote address: 127.0.0.1:14550

3-上記のノードを実行し、1Hzで/ mavlink / fromに公開します。
4-システムID1を使用してUDP127.0.0.1:14550を使用してQGroundControlを接続します

...そして再びMAVLinkインスペクターは空です。

最初は何も起こりませんが、ある時点で、QGroundControlは次のエラーをスローします。

MAVLinkバージョンまたはボーレートの不一致があります。 QGroundControlとオートパイロットのボーレートが同じかどうかを確認してください。

どういうわけか、QGCはこのエラーの前のある時点でUDPポートを変更すると思います。

私は何が間違っているのですか?

ありがとう!

a) gcs_urlのmavrosを使用しないでください! gcs_bridge接続する必要があります!
b)Mavlink.msgを埋めるための不正なコード。 次のようになります。

mavlink::common::msg::HEARTBEAT hb{};
...

mavlink::mavlink_message_t msg;
mavlink::MsgMap map(msg);

hb.serialize(map);
mavlink::finalize_message_buffer(&msg, sysid, compid, ...);

mavros_msgs::Mavlink ml;
mavros_msgs::mavlink::convert(msg, ml);

見る:

やあ!

ありがとう! 私はついにそれを機能させました。 Indigoを使用しているので、さまざまなクラスを使用しました。 他の誰かがそれを正確に行う方法を疑問に思っている場合に備えて、ここにコードを残します。 ハートビートと高度メッセージを送信し、QGroundControlで受信します。

1- fcu_url = udp://:14540 @およびgcs_url = udp://:[email protected] :14551を使用してmavrosノードを起動します。
2- gcs_url:= udp://@127.0.0.1:14560を使用してgcs_bridgeを起動します。
3-このノードを起動します。

#include <ros/ros.h>
#include <mavconn/interface.h>
#include <mavros_msgs/Mavlink.h>
#include <mavros_msgs/mavlink_convert.h>

// General parameters
uint8_t system_id = 1;
uint8_t component_id = 1;
uint8_t type = 1;
uint8_t autopilot = 0;
uint8_t base_mode = 128;
uint32_t custom_mode = 0;
uint8_t system_status = 0;

// Parameters of the altitude message
float alt_monotonic = 10.0;
float alt_amsl = 100;
float alt_local = 10.0;
float alt_relative = 10.0;
float alt_terrain = 10;
float bottom_clearance = 0;

int main(int argc, char **argv){

    // Create heartbeat message
    mavlink_message_t msg_heartbeat;
    mavlink_msg_heartbeat_pack(system_id, component_id, &msg_heartbeat, type, autopilot, base_mode, custom_mode, system_status);

    mavros_msgs::Mavlink ml_heartbeat;
    mavros_msgs::mavlink::convert(msg_heartbeat, ml_heartbeat);

    // Create altitude message
    mavlink_message_t msg_altitude;
    mavros_msgs::Mavlink ml_altitude;

    ros::init(argc, argv, "telemetry_publisher");
    ros::NodeHandle n;

    ros::Publisher example_pub = n.advertise<mavros_msgs::Mavlink>("/mavlink/from", 1000);
    ros::Rate loop_rate(1); // 1 Hz

    while (ros::ok())
    {
        uint64_t time_stamp = ros::Time::now().nsec;

        // Finish altitude message
        mavlink_msg_altitude_pack(system_id, component_id, &msg_altitude, time_stamp, alt_monotonic, alt_amsl, alt_local, alt_relative, alt_terrain, bottom_clearance);
        mavros_msgs::mavlink::convert(msg_altitude, ml_altitude);

        // Publish messages
        example_pub.publish(ml_heartbeat);
        example_pub.publish(ml_altitude);

        ros::spinOnce();
        loop_rate.sleep();
    }
    return 0;
}

4- QGroundControlを起動し、127.0.0.1:14560で接続を構成します

MavLink Inspectorを開くと、約1Hzで心拍と高度のメッセージが表示されます。

私はこれを試みますが、エラーが発生します、私は本当に理由を理解できません、誰かが私を助けることができますか?
#includeの場合、mavlink_msg_heartbeat_pack関数を含める必要がありますしかし、そうではありませんでした...
私はcmakeで間違っていたのかもしれませんか?

#include "ros/ros.h"
#include <mavros_msgs/mavlink_convert.h>
#include <mavconn/interface.h>

int main(int argc, char **argv)
{
    ros::init(argc, argv, "talker");
    ros::NodeHandle n;
    ros::Publisher pub = n.advertise<mavros_msgs::Mavlink>("/mavlink/from", 1000);
    ros::Rate loop_rate(10);

    uint8_t system_id = 1;
    uint8_t component_id = 1;
    uint8_t type = 1;
    uint8_t autopilot = 0;
    uint8_t base_mode = 128;
    uint32_t custom_mode = 0;
    uint8_t system_status = 0;
    mavlink_message_t msg;
    mavlink_msg_heartbeat_pack(system_id, component_id, &msg, type, autopilot, base_mode, custom_mode, system_status);
  return 0;
}
cmake_minimum_required(VERSION 2.8.3)
project(talker)

find_package(catkin REQUIRED COMPONENTS mavros mavros_msgs mavlink)
catkin_package()
include(EnableCXX11)
include(MavrosMavlink)
include_directories(
  ${catkin_INCLUDE_DIRS}
  ${mavlink_INCLUDE_DIRS}
)

add_executable(talker talker.cpp)
target_link_libraries(talker ${catkin_LIBRARIES})

エラー:「mavlink_message_t」はこのスコープで宣言されていません
mavlink_message_t msg;
エラー:「mavlink_msg_heartbeat_pack」はこのスコープで宣言されていません
mavlink_msg_heartbeat_pack(system_id、component_id、&msg、type、autopilot、base_mode、custom_mode、system_status);

@shawinmihailどのバージョンのmavros? 0.18+には、mavlink_helpers.hとC ++ 11libのみが含まれます。

私は自分の問題の解決策を見つけました。 おそらく、mavros v0.18 +はmavlinkv2.0ヘッダーのみを使用します。 メッセージを作成するには、msg_name_pack()の代わりにMsgMap.serialize()を使用する必要があります

    mavlink::mavlink_message_t msg;
    mavlink::MsgMap map(msg);
    mavlink::groupcontrol::msg::GROUP_COEFFS_PART1 msgPart1 //my custom msg;

    msgPart1.kc = kc;
    msgPart1.ks = ks;
        //........................... - fill msg

         msgPart1.serialize(map);
    map.reset();
    auto mi = msgPart1.get_message_info();
    mavlink::mavlink_finalize_message(&msg, system_id, component_id, mi.min_length, mi.length, mi.crc_extra);

    mavros_msgs::Mavlink mavrosMsg;
    mavros_msgs::mavlink::convert(msg, mavrosMsg);

多分それは誰かを助けることができます。 あなたがより良い方法を知っているなら、plsはそれを書きます。
ヒントをありがとう。

Message::serialize()MsgMap::reset()を実行します。直接呼び出さないでください! メッセージが壊れることがあります。

また、メッセージを送信できるMAVConnInterfaceクラスがあるため、カスタムgcs_bridgeを作成することをお勧めします。

auto gcs_link = MAVConnInterface::open_url("udp-b://@");

mavlink::common::msg::HEARTBEAT hb{};
// fill hb

gcs_link->send_message_ignore_drop(hb);

@vooon 、コメントありがとう

#include "ros/ros.h"
#include <mavros_msgs/mavlink_convert.h>
#include <mavconn/interface.h>
#include <iostream>
#include <mavlink/v2.0/mavlink_helpers.h>


float kc = 0.0f; /*< gravity coeff */
float ks = 0.0f; /*< repulsive coeff */
float ka = 0.0f; /*< speed alignment coeff */
float kp = 0.0f; /*< chasing coeff */
float km = 0.0f; /*< waypoint gravity coeff */
float kh = 0.0f; /*< rotate speed coeff */
float vmax = 0.0f; /*< max autopilot velocity */
float rn = 0.0f; /*< search radius of groupmate  */
float rs = 0.0f; /*< repulsiveOn radius */
float rm = 0.0f; /*< getting waypoint radius */
float rmb = 0.0f; /*< change gravity law radius */

void packMavlinkMessage(const mavlink::Message& mavMsg, mavros_msgs::Mavlink &rosMsg)
{
    mavlink::mavlink_message_t msg;
    mavlink::MsgMap map(msg);
    mavMsg.serialize(map);
    auto mi = mavMsg.get_message_info();

    mavlink::mavlink_status_t *status = mavlink::mavlink_get_channel_status(mavlink::MAVLINK_COMM_0);
    status->flags |= MAVLINK_STATUS_FLAG_OUT_MAVLINK1;
    mavlink::mavlink_finalize_message_buffer(&msg, 1, 1, status, mi.min_length, mi.length, mi.crc_extra);

    mavros_msgs::mavlink::convert(msg, rosMsg);
}

void mavlinkCallback(const mavros_msgs::Mavlink& msg)
{
    mavlink::mavlink_message_t mavMsg;
    mavros_msgs::mavlink::convert(msg, mavMsg);

    if(mavMsg.msgid == mavlink::groupcontrol::msg::SET_GROUP_PARAMS::MSG_ID)
    {
        ROS_WARN("SET GROUP_PARAMS");
        mavlink::MsgMap map(mavMsg);
        mavlink::groupcontrol::msg::SET_GROUP_PARAMS setParamsMsg;
        setParamsMsg.deserialize(map);

        std::cout << setParamsMsg.kc;
    }
}

int main(int argc, char **argv)
{
    ros::init(argc, argv, "talker");
    ros::NodeHandle n;
    ros::Publisher pub = n.advertise<mavros_msgs::Mavlink>("/mavlink/from", 1000);
    ros::Subscriber sub = n.subscribe("mavlink/to", 1000, mavlinkCallback);
    ros::Rate loop_rate(10);

    ROS_INFO("%s", "Talker started");

    mavlink::groupcontrol::msg::GROUP_PARAMS msgPart1;
    msgPart1.kc = kc;
    msgPart1.ks = ks;
    msgPart1.ka = ka;
    msgPart1.kp = kp;
    msgPart1.km = km;
    msgPart1.kh = kh;
    msgPart1.vmax = vmax;
    msgPart1.rn = rn;
    msgPart1.rs = rs;
    msgPart1.rm = rm;
    msgPart1.rmb = rmb;

    while (ros::ok())
    {
        mavros_msgs::Mavlink mavrosMsg;
        packMavlinkMessage(msgPart1, mavrosMsg);
        pub.publish(mavrosMsg);
        ros::spinOnce();
        loop_rate.sleep();
    }


  return 0;
}

誰かが私を助けて書くことができるかもしれません
Pythonから同じことをどのように行うことができますか?
mavlink msgを作成し、mavros msgに変換しますか?

また、メッセージを送信できるMAVConnInterfaceクラスがあるため、カスタムgcs_bridgeを作成することをお勧めします。

auto gcs_link = MAVConnInterface::open_url("udp-b://@");

mavlink::common::msg::HEARTBEAT hb{};
// fill hb

gcs_link->send_message_ignore_drop(hb);

このメソッドは単にカスタムメッセージを送信できますが、リスクはありますか? @vooon

このページは役に立ちましたか?
0 / 5 - 0 評価