Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

w6_mission_timeout.py

W6 實驗 2:觀察任務上傳協定的逾時與重送(pymavlink)。

檔案位置:scripts/w6_mission_timeout.py

"""W6 實驗 2:觀察任務上傳協定的逾時與重送(pymavlink)。

用法:vendor/venv/bin/python -u -I scripts/w6_mission_timeout.py
先執行 scripts/sitl.sh;本腳本連 tcp:127.0.0.1:5762。
做法:送 MISSION_COUNT 後完全不回應,印出飛控之後送來的每一則 MISSION_REQUEST[_INT] / MISSION_ACK 與時間,
最後(逾時之後)再回一次 MISSION_ITEM_INT,看飛控怎麼處理遲到的項目。結束時清空任務。
"""
import time

from pymavlink import mavutil

CONN = "tcp:127.0.0.1:5762"
COUNT = 3  # 宣告的任務項目數
WATCH_SECONDS = 20  # 不回應時觀察幾秒
T = mavutil.mavlink  # T:MAVLink 常數的命名空間,只為了縮短下面的名稱
# m:MAVLink 連線;m.mav.*_send 送出訊息,m.recv_match 接收訊息
m = mavutil.mavlink_connection(CONN)
m.wait_heartbeat(timeout=10)
t0 = time.time()  # 腳本開始時刻


def log(msg):
    print(f"[{time.time() - t0:5.1f}s] {msg}")


def drain(seconds):
    """印出接下來 seconds 秒內收到的任務協定訊息與 STATUSTEXT。"""
    end = time.time() + seconds
    while time.time() < end:
        msg = m.recv_match(type=["MISSION_REQUEST", "MISSION_REQUEST_INT", "MISSION_ACK", "STATUSTEXT"],
                           blocking=True, timeout=0.5)
        if msg is None:
            continue
        if msg.get_type() == "STATUSTEXT":
            log(f"STATUSTEXT:{msg.text}")
        elif msg.get_type() == "MISSION_ACK":
            log(f"MISSION_ACK type={msg.type}")
        else:
            log(f"{msg.get_type()} seq={msg.seq}")


m.mav.mission_clear_all_send(m.target_system, m.target_component)
m.recv_match(type="MISSION_ACK", blocking=True, timeout=5)
m.mav.mission_count_send(m.target_system, m.target_component, COUNT)
log(f"送出 MISSION_COUNT = {COUNT},之後不回應")
drain(WATCH_SECONDS)

# 遲到的項目:第 0 項(home 位置,內容隨便填)
log("逾時後才回 MISSION_ITEM_INT seq=0")
m.mav.mission_item_int_send(m.target_system, m.target_component, 0, T.MAV_FRAME_GLOBAL,
                            T.MAV_CMD_NAV_WAYPOINT, 0, 1, 0, 0, 0, 0, 0, 0, 0)
drain(5)

m.mav.mission_clear_all_send(m.target_system, m.target_component)
ack = m.recv_match(type="MISSION_ACK", blocking=True, timeout=5)
log(f"清空任務:{'無回應' if ack is None else f'MISSION_ACK type={ack.type}'}")