본문 바로가기
etc/드론 시스템

[MAVLink 메시지 → JSON] 파싱 후 Flask 서버 전송 코드

by 클레어몬트 2024. 10. 20.

https://mavlink.io/ko/messages/common.html

 

메세지 (공통) · MAVLink Developer Guide

 

mavlink.io

MAVLink 메시지 타입과 필드값 공식 문서

 

https://claremont.tistory.com/entry/Nodejs-MQTT-MAVLink-JSON-%EB%9D%BC%EC%9D%B4%EB%B8%8C%EB%9F%AC%EB%A6%AC

 

[Node.js] MQTT, MAVLink, JSON 라이브러리

ㅁMQTT 라이브러리: 구독(subscribe) / 발행(publish) 설정 설치 명령어npm install mqttNode.js import문const mqtt = require('mqtt');  ㅁMAVLink 라이브러리: MAVLink 메시지의 각 필드를 추출설치 명령어npm install mavlinkN

claremont.tistory.com

 

 

 


1. 드론 ID 및 상태
: 드론 ID는 HEARTBEAT 메시지에서 "메타 데이터인 system_id 값을 직접 추출" + 상태값은 base_mode 필드와 custom_mode 필드

MAVLink 메시지 구조(System ID 주목)

 

[필요한 드론의 3가지 상태]

①Armed: 모터가 활성화되어 프로펠러가 회전할  있는 상태 (이륙할 준비가 되어 있거나 이미 비행 중)

②Disarmed: 드론의 모터가 꺼져 있는 상태 (이륙 불가능)

③Guided: 드론이 외부에서 명령을 받아 그에 따라 움직이고 있다는 상태. e.g. 특정 좌표로 이동하라는 명령을 받으면 그 방향으로 움직이는 상태

상태를 알기 위해선 MAV_MODE_FLAG 값과 AND(&) 연산을 해야 한다

 

 

(MAVLink HEARTBEAT 메시지에서 system_id 값과 base_mode, custom_mode값을 추출해 json 데이터로 변환시키고 Flask 서버로 전송하는 코드)

const mqtt = require('mqtt');
const client = mqtt.connect('mqtt://flask_server_ip'); // Flask 서버 IP 주소 입력

// 드론으로부터 MAVLink HEARTBEAT 메시지 수신 시
mavlink.on('HEARTBEAT', (message, metadata) => {
    // 드론의 system_id를 추출
    const systemId = metadata.system_id; 
    
    const isArmed = parsedMessage.base_mode & MAV_MODE_FLAG_SAFETY_ARMED; // AND 연산
    const isGuided = parsedMessage.base_mode & MAV_MODE_FLAG_CUSTOM_MODE_ENABLED && parsedMessage.custom_mode === 4; // ArduPilot 기준 GUIDED 모드일 때 custom_mode 값은 4
                   
    // JSON 형식으로 변환
    const jsonData = { 
        system_id: systemId,
        armed: isArmed ? "ARMED" : "DISARMED",
        guided: isGuided ? "GUIDED" : "NOT GUIDED",
        message_type: 'HEARTBEAT',
        timestamp: new Date().toISOString() // 데이터 수신 시간을 포함
    };

    // MQTT를 통해 JSON 데이터를 Flask 서버에 전송
    client.publish('drone/status', JSON.stringify(jsonData), (err) => {
        if (err) {
            console.error('Failed to send system ID to Flask server:', err);
        } else {
            console.log('Status sent to Flask server:', jsonData);
        }
    });
});

 

 

 

2. 위도/경도 및 고도(절대고도 = 해발고도): GLOBAL_POSITION_INT (33) 메시지의 lat, lon 필드 및 alt 필드

 

 

(MAVLink GLOBAL_POSITION_INT 메시지 필드 lat, lon 값을 추출해 json 데이터로 변환시키고 Flask 서버로 전송하는 코드)

const mqtt = require('mqtt');
const client = mqtt.connect('mqtt://flask_server_ip'); // Flask 서버 IP 주소 입력

// 드론으로부터 MAVLink GLOBAL_POSITION_INT 메시지 수신 시
mavlink.on('GLOBAL_POSITION_INT', (message) => {
    // 메시지의 위도 및 경도 값을 추출 (단위: 1E7 및 밀리미터)
    const latitude = message.lat / 1e7; // 실제 위도 값으로 변환
    const longitude = message.lon / 1e7; // 실제 경도 값으로 변환
    const altitude = message.alt / 1000; // 밀리미터 단위에서 미터 단위로 변환
	
    // JSON 형식으로 변환
    const jsonData = {
        latitude: latitude.toFixed(6), // 소수점 6자리까지 반올림
        longitude: longitude.toFixed(6), // 소수점 6자리까지 반올림,
        altitude: altitude.toFixed(2), // 소수점 2자리까지 반올림
        message_type: 'GLOBAL_POSITION_INT',
        timestamp: new Date().toISOString() // 데이터 수신 시간을 포함
    };

    // MQTT를 통해 JSON 데이터를 Flask 서버에 전송
    client.publish('drone/position', JSON.stringify(jsonData), (err) => {
        if (err) {
            console.error('Failed to send position to Flask server:', err);
        } else {
            console.log('Position sent to Flask server:', jsonData);
        }
    });
});

 

 

 

3. 배터리 잔량: SYS_STATUS (1) 메시지의 battery_remaining 필드

제일 아래에 있다

 

 

(MAVLink SYS_STATUS 메시지 필드 battery_remaining 값을 추출해 json 데이터로 변환시키고 Flask 서버로 전송하는 코드)

const mqtt = require('mqtt');
const client = mqtt.connect('mqtt://flask_server_ip'); // Flask 서버 IP 주소 입력

// 드론으로부터 MAVLink SYS_STATUS 메시지 수신 시
mavlink.on('SYS_STATUS', (message) => {
    // 메시지의 battery_remaining 값을 추출 (단위: %)
    const batteryRemaining = message.battery_remaining;
	
    // JSON 형식으로 변환
    const jsonData = {
        battery_remaining: batteryRemaining,
        message_type: 'SYS_STATUS',
        timestamp: new Date().toISOString() // 데이터 수신 시간을 포함
    };

    // MQTT를 통해 JSON 데이터를 Flask 서버에 전송
    client.publish('drone/battery_status', JSON.stringify(jsonData), (err) => {
        if (err) {
            console.error('Failed to send battery status to Flask server:', err);
        } else {
            console.log('Battery status sent to Flask server:', jsonData);
        }
    });
});

 

 

 

(현재 가고 있는 목표지점을 알 수 있는지 확인하는 용도)

4. mission_item: MISSION_CURRENT (42) 메시지의 seq 필드

 

 

(MAVLink MISSION_CURRENT 메시지 필드 seq 값을 추출해 json 데이터로 변환시키고 Flask 서버로 전송하는 코드)

const mqtt = require('mqtt');
const client = mqtt.connect('mqtt://flask_server_ip'); // Flask 서버 IP 주소 입력

// 드론으로부터 MAVLink MISSION_CURRENT 메시지 수신 시
mavlink.on('MISSION_CURRENT', (message) => {
    // 메시지의 seq 값을 추출 (현재 진행 중인 미션 아이템의 순서)
    const missionSequence = message.seq;
	
    // JSON 형식으로 변환
    const jsonData = {
        mission_sequence: missionSequence,
        message_type: 'MISSION_CURRENT',
        timestamp: new Date().toISOString() // 데이터 수신 시간을 포함
    };

    // MQTT를 통해 JSON 데이터를 Flask 서버에 전송
    client.publish('drone/mission_status', JSON.stringify(jsonData), (err) => {
        if (err) {
            console.error('Failed to send mission status to Flask server:', err);
        } else {
            console.log('Mission status sent to Flask server:', jsonData);
        }
    });
});

 

 

 

 

 

 

 

참고 및 출처: https://www.researchgate.net/publication/344738029_A_Software_Defined_Radio_Based_Implementation_for_the_Radio_Frequency_Analysis_of_Signals_from_Unmanned_Aerial_Systems

'etc > 드론 시스템' 카테고리의 다른 글

행정안전부의 SW 개발보안 가이드  (1) 2024.10.05
드론 서버 개발 관련 유용한 링크들  (0) 2024.10.04
드론 배경지식  (7) 2024.09.25