Исправление в Mission Planner для улучшения качества линка телеметрии

Купил два комплекта модулей 3DR телеметрии на 433 МГц - от HK и himodel. Модули чуть разные, антенны тоже разные, даже прошивки разные (1.7 и 1.9). В Mission Planner при установлении связи на default настройках (MavLink, ECC, Opresend, 20db, Link quality был стабильно порядка 10%, иногда опускаясь или подымаясь на 5%, а счетчик потерянных пакетов бежал как угорелый. Я пробывал пропаивать модуль, разбирал антенны (они оказались нормальными, с пружинкой), даже сделал свой диполь - качество не улучшалось. Потом нашел лог принятых пакетов и из него понял, что часто происходят сбои синхронизации по причине того, что иногда приходят несколько сообщений с порядковым номером сильно отличающимся от того, который ожидался. Добавив немного отладки, я выяснил, что коды этих сообщений всегда 166 и 109, приходят они иногда парами, иногда по-одиночке, а их порядковые номера имеют свою собственную нумерацию, не похожую на другие сообщения. Число потерянных пакетов вычисляется как разница между порядковыми номерами (по модулю 256), отсюда и их большое число.

Интернет про эти пакеты знает мало, и пришлось залезть в исходники прошивки телеметрии (github.com/tridge/SiK/blob/master/…/mavlink.c). Видим, что сообщения 166 и 109 (MAVLINK_MSG_ID_RADIO и MAVLINK_MSG_ID_RADIO_STATUS) посылаются в MAVLink_report со своей собственной нумерацией из seqnum. Зачем нужно слать оба - не понятно.

Поняв в чем дело, я подправил MissionPlanner, чтобы нумерация именно этих сообщений игнорировалась. Теперь MissionPlanner показывает 100% линк, и если и появляется потерянный пакет, это реально так. Также я поправил подсчет потерянных пакетов, там были “ошибки десятого столба изгороди”.

Все изменения помечены комментом, начинающимся с // AP;

File: MAVLinkInterface.cs

        public byte[] readPacket()
...
                if ((buffer[0] == 'U' || buffer[0] == 254) && buffer.Length >= buffer[1])
                {
                    // check if we lost pacakets based on seqno
                        byte packetSeqNo = buffer[2];
                        int expectedPacketSeqNo = ((MAVlist[sysid].recvpacketcount + 1) % 0x100);

                        {
                            // AP; START; Suppress sync lost error when RADIO and RADIO_STATUS packets coome with the same seqno;
                            if (buffer[5] == (byte)MAVLINK_MSG_ID.RADIO || buffer[5] == (byte)MAVLINK_MSG_ID.RADIO_STATUS) // It is RADIO or RADIO_STATUS packet;
                            {
                                log.InfoFormat("injected pkt seqno {0}, crc {1}, msg {2}", packetSeqNo, crc, buffer[5]);
                            }
                            else
                            // AP; STOP; Suppress sync lost error when RADIO and RADIO_STATUS packets coome with the same seqno;
                            {
                                if (packetSeqNo != expectedPacketSeqNo && !MAVlist[sysid].justStarted)
                                {
                                    synclost++; // actualy sync loss's
                                    int numLost = 0;

                                    if (packetSeqNo < ((MAVlist[sysid].recvpacketcount + 1))) // recvpacketcount = 255 then   10 < 256 = true if was % 0x100 this would fail
                                    {
                                        numLost = 0x100 - MAVlist[sysid].recvpacketcount + packetSeqNo - 1; // AP; i.e. rec=255;exp=0;rec=1;256-255+1-1=1=lost;
                                    }
                                    else
                                    {
                                        numLost = packetSeqNo - MAVlist[sysid].recvpacketcount - 1; // AP; -1 added; i.e. MAV.recvpacketcount = 163; expected = 164;
                                    }
                                    packetslost += numLost;
                                    WhenPacketLost.OnNext(numLost);

                                    log.InfoFormat("lost pkts new seqno {0} expected seqno {1} pkts lost {2}; crc {3}, msg {4}",
                                        packetSeqNo, expectedPacketSeqNo, numLost, crc, buffer[5]);
                                }
                                else
                                {
                                    log.InfoFormat("good pkt seqno {0}; crc {1}, msg {2}", packetSeqNo, crc, buffer[5]);
                                }

                                // AP; START; Fixing counting packets, first packet recedived;
                                if (MAVlist[sysid].justStarted)
                                {
                                    MAVlist[sysid].justStarted = false;
                                    log.InfoFormat("started");
                                }
                                // AP; STOP; Fixing counting packets, first packet recedived;

                                packetsnotlost++;
                                MAVlist[sysid].recvpacketcount = packetSeqNo;
                            }
                        }

                        WhenPacketReceived.OnNext(1);
        void SetupMavConnect(byte sysid, byte compid,byte mgsno, mavlink_heartbeat_t hb)

        {
...
            log.InfoFormat("recvpacketcount set to {0}", mgsno);
            MAV.justStarted = true; // AP;
        }

File: MAVState.cs

    public class MAVState : MAVLink
    {
...
        internal int recvpacketcount = 0;
        internal bool justStarted = true; // AP; not detecting synh loss just after connect;
    }

Из мелких изменений: для ускорения коннекта и поиска портов поставил в начало зависающих функций проверку на специальный параметр skip_get_portName, который надо добавить в файл конфигурации в

подкаталоге bin того места, куда установлен MissionPlanner.

File: CommSerialPort.cs

        public static string GetNiceName(string port)
        {
            if (System.Configuration.ConfigurationManager.AppSettings["skip_get_portName"] == "1") // AP; Skip quering for port name (hanging with Bluetooth ports in Win);
                return "";

             // make sure we are exclusive
...
        internal bool ispx4(string port)
        {
            if (System.Configuration.ConfigurationManager.AppSettings["skip_get_portName"] == "1") // AP; Skip ispx4 detection (hanging with Bluetooth ports in Win);
                return false;

            try
            {
...

Пока отлаживал свои изменения в прошивке MegaPirateNG при помощи текстовых сообщений в закладке Messages, обнаружил, что список сообщений автоматически не проматывается в конец при добавлении сообщения. Так что я поставил ему в дизайнере вертикальный ScrollBar и добавил промотку:

File: FlightData.cs

        private void Messagetabtimer_Tick(object sender, EventArgs e)
        {
...
                txt_messagebox.Text = message.ToString();

                // AP; START; Scroll to the end when messages added; Vertical bar is added in designer as well;
                txt_messagebox.SelectionStart = txt_messagebox.Text.Length;
                txt_messagebox.ScrollToCaret();
                txt_messagebox.Refresh();
                // AP; STOP; Scroll to the end;

                messagecount = MainV2.comPort.MAV.cs.messages.Count;

Стало гораздо удобнее 😉

Вот так выглядит лог теперь (видны injected (вставленные) пакеты):

2014-10-24 01:00:44,141  INFO MissionPlanner.MAVLinkInterface - good pkt seqno 19; crc 16352, msg 163 (c:\Andrey\MegaPirateNG\MissionPlanner.2\MissionPlanner-master\Mavlink\MAVLinkInterface.cs:2511) [Main Serial reader]
2014-10-24 01:00:44,141  INFO MissionPlanner.MAVLinkInterface - good pkt seqno 20; crc 4247, msg 165 (c:\Andrey\MegaPirateNG\MissionPlanner.2\MissionPlanner-master\Mavlink\MAVLinkInterface.cs:2511) [Main Serial reader]
2014-10-24 01:00:44,142  INFO MissionPlanner.MAVLinkInterface - good pkt seqno 21; crc 11259, msg 2 (c:\Andrey\MegaPirateNG\MissionPlanner.2\MissionPlanner-master\Mavlink\MAVLinkInterface.cs:2511) [Main Serial reader]
2014-10-24 01:00:44,142  INFO MissionPlanner.MAVLinkInterface - good pkt seqno 22; crc 61601, msg 0 (c:\Andrey\MegaPirateNG\MissionPlanner.2\MissionPlanner-master\Mavlink\MAVLinkInterface.cs:2511) [Main Serial reader]
2014-10-24 01:00:44,142  INFO MissionPlanner.MAVLinkInterface - injected pkt seqno 165, crc 24721, msg 166 (c:\Andrey\MegaPirateNG\MissionPlanner.2\MissionPlanner-master\Mavlink\MAVLinkInterface.cs:2485) [Main Serial reader]
2014-10-24 01:00:44,143  INFO MissionPlanner.MAVLinkInterface - injected pkt seqno 165, crc 4848, msg 109 (c:\Andrey\MegaPirateNG\MissionPlanner.2\MissionPlanner-master\Mavlink\MAVLinkInterface.cs:2485) [Main Serial reader]
2014-10-24 01:00:44,202  INFO MissionPlanner.MAVLinkInterface - good pkt seqno 23; crc 28240, msg 30 (c:\Andrey\MegaPirateNG\MissionPlanner.2\MissionPlanner-master\Mavlink\MAVLinkInterface.cs:2511) [Main Serial reader]
2014-10-24 01:00:44,202  INFO MissionPlanner.MAVLinkInterface - good pkt seqno 24; crc 1174, msg 74 (c:\Andrey\MegaPirateNG\MissionPlanner.2\MissionPlanner-master\Mavlink\MAVLinkInterface.cs:2511) [Main Serial reader]
  • 2462
Comments
Lazy

И снова MavLink…

fly55

Странно у всех какие то проблемы с телеметрией постоянно я летаю на штатных модемах и на коаксиальных диполях самодельных на 4-5 км. вполне стабильно при этом вполне спокойно правлю настройки и пиды в процессе если надо линк обычно ниже 60% не падает на таких удалениях. дальше не летал. Все кроме антенн из “коробки”

Prikupets

fly55, лог пришлите пожалуйста на пару минут, можно даже на земле.
А против MavLink’а я ничего не имею, замечательная “экосистема”, гораздо лучше чем протоколы MultiWii (про OpenPilot не скажу).

fly55

лог какой локальный или с автопилота ?

Prikupets

Локальный - мне же качество приема на земле надо посмотреть. А лучше, файлы MissionPlanner.log, MissionPlanner.log.1, MissionPlanner.log.2 … из каталога c MissionPlanner.