ardupilot의 로그로 다음의 파일이 생성된다.
- *.bin (FCC SW 가 생성)
- *.tlog (Mission Planner 가 생성)
해당 파일들을 사람이 읽을 수 있는 ASCII 문자열이 아닌 바이너리로 저장되어있기 때문에 변환하는 과정이 필요하다.
본 글은 생성된 로그 파일을 쉼표로 구분된 파일인 csv 파일로 생성하는 방법을 다룬다.
파이썬 라이브러리 pymavlink 설치하기
MAVLink 란? [1]
오픈소스 비행제어 소프트웨어인 Ardupilot과 PX4는 외부 장치와 통신할 때 메시징 프로토콜로 MAVLink를 사용한다. [1]
이 메시징 프로토콜은 사람이 읽을 수 있는 형태의 포맷인 *.xml 형태의 파일로 표현[2]되며, 예시로 common.xml은 다음 위치에서 설명과 xml 파일을 볼 수 있다. 또한 사용자가 원한다면 유사하게 *.xml 파일을 만들어서 메시지 프로토콜로 추가할 수 있다. 이러한 임의의, 혹은 다른 목적을 가지고 추가한 것을 Dialect (방언, 사투리)이라 한다.
*.xml으로 정의된 MAVLink 메시지는 해당 메시지를 사용하는 장비에 모두 사용되기 때문에 비행제어 SW의 빌드, 지상통제SW의 빌드 시에 반드시 같이 사용해야한다.
Dialect 란? [4]
Dialect 는 사전적 의미로 보면 방언, 사투리이다. MAVLink는 표준 메시지와 시험용 메시지를 정의해놓은 바 있으며, 추가적으로 특정 목적에 따라 필요한 메시지, 열거형, 명령들을 정의할 수 있도록 해두었다.
위와 같은 점을 정리해볼 때, 지방에서만 통용되는 방언, 즉 특정 목적 및 환경에서만 사용하는 메시지들을 정의해놓은 것을 Dialect라 할 수 있다.
Dialect는 다른 MAVLink xml 파일을 포함할 수 있으며, 그 깊이는 mavgen.py에 MAXIMUM_INCLUDE_FILE_NESTING으로 정의된 대로 5단계 까지 가능하다고 한다. 일반적인 Dialect의 패턴은 다음과 같이 common.xml 을 포함한다.
PyMavlink 란? [3]
pymavlink는 MAVLink 프로토콜을 다룰 수 있도록 만든 파이썬 패키지이다.
이를 사용하기 위해서 윈도우 환경에서 Native으로 Python을 설치하거나, Anaconda와 같은 가상환경 상에 Python을 설치하도록 한다. 그 다음, 아래의 명령어를 입력하여 pymavlink 패키지를 설치하자.
python -m pip install pymavlink
설치가 완료되면 pymavlink 패키지의 설치 위치는 다음과 같다. 굵은 글씨는 달라질 수 있다.
- Native 환경 : C:\Users\[ACCOUNT_NAME]\AppData\Local\Programs\Python\PythonXX\Lib\site-packages\pymavlink
- Anaconda 환경 : [ANACONDA_PATH]\envs\[ENV_NAME]\Lib\site-packages\pymavlink
pymavlink 패키지에서 사용하는 Dialect들은 위 경로에서 더하여 MAVLink 의 버전별로 다음 위치에 *.xml 및 *.py 파일으로 존재한다. 해당 방언들을 바탕으로 pymavlink 패키지의 기능들을 사용할 수 있다.
- [PYMAVLINK_PATH]\dialects\v10
- [PYMAVLINK_PATH]\dialects\v20
pymavlink를 이용하여 로그 파일 추출하기
pymavlink를 이용하여 로그를 추출하는 방법은 패키지의 라이브러리인 mavlogdump를 이용하면 된다. 해당 라이브러리를 사용하는 형태는 일반적으로 다음의 명령어를 입력하여 사용할 수 있다.
python -m mavlogdump --format [FORMAT] --types [TYPES] --dialect [DIALECT] --output [OUTPUT_FILENAME] [INPUT_FILENAME]
python -m mavlogdump --format csv --types DATA1 --output somewhere\output.csv somewhere\input.bin
python -m mavlogdump --format csv --types DATA1 --output somewhere\output.csv somewhere\input.tlog
인자에 대해서 설명하면 다음과 같다.
- FORMAT : 출력 포맷으로 'standard', 'json', 'csv', 'mat'을 선택할 수 있으며, MAT 출력이라면 --mat_file 옵션이 필요하다.
- TYPES : 메시지 타입이며, 콤마로 구분하여 여러개를 넣어줄 수도 있다고 한다. [--types DATA1,DATA2,DATA3]
- DIALECT : 특정 방언을 선택할 수 있으며, 생략한다면 ardupilotmega.xml/py을 참조하게 된다.
- OUTPUT_FILENAME : 출력 파일 이름이다. 확장자까지 써야한다.
- INPUT_FILE_NAME : 입력 파일 이름이다. 항상 마지막에 나와야한다.
입출력 파일 이름에 띄어쓰기가 있다면 쌍따옴표 " " 으로 감싸준다.
이를 통해서 *.bin, *.tlog 파일에서 csv 파일으로 다음과 같이 데이터를 추출할 수 있다.
여러 types을 입력하면 다음과 같이 나오면서 안된다.
설명에는 여러 개 된다는데 안되나보다.
Need exactly one type when dumping CSV from bin file
타입과 메시지 포맷에 맞추어 대량의 데이터를 한꺼번에 추출하는 코드는 다음과 같다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
|
import os
import argparse
import sys
parser = argparse.ArgumentParser(description="make csv from *.bin/*.tlog (ardupilot log)")
parser.add_argument("-s", "--signature")
args = parser.parse_args()
print("Input signature : {}".format(args.signature))
pymavlink_path = ""
root_path = ""
script_path = "{}\Scripts".format(pymavlink_path)
dialect_name = "cubepilot"
# Message types
bin_msg_types = list()
bin_msg_types.append("DATA1")
tlog_msg_types = dict()
tlog_msg_types["50002"] = "HERELINK_VIDEO_STREAM_INFORMATION"
print("At {}...".format(root_path))
# File Names
signature = args.signature
file_list = os.listdir(root_path + "\\input_{}\\".format(signature))
os.makedirs(root_path + "\\input_{}\\output_{}\\".format(signature, signature), exist_ok=True)
print(" - Dump logs")
for file_name in file_list:
filename = file_name[:-4]
extension = file_name[-4:]
if(filename[0] != '2'):
continue
# Extension Check
if(extension.lower() == ".bin"):
# filename = "00000019"
for msg_type in bin_msg_types:
# msg_type = "TM11"
input_file = "{}\input_{}\{}".format(root_path, signature, file_name)
output_file = "{}\input_{}\output_{}\{}_{}.csv".format(root_path, signature, signature, filename, msg_type)
bash_cmd = 'python {}\mavlogdump.py --format csv --types {:} "{:}" > "{:}"'.format(script_path, msg_type, input_file, output_file)
# print(bash_cmd)
os.system(bash_cmd)
print_msg = "\tdump {:} - {:}".format(file_name, bin_msg_types)
print(print_msg)
elif(extension.lower() == "tlog"):
for id in tlog_msg_types.keys():
# msg_type = "TM11"
input_file = "{}\input_{}\{}".format(root_path, signature, file_name)
output_file = "{}\input_{}\output_{}\{}_{}.csv".format(root_path, signature, signature, filename[:-1], id)
bash_cmd = 'python -m mavlogdump --dialect {:} --format csv --types {:} "{:}" > "{:}"'.format(tlog_msg_types[id], input_file, output_file)
# print(bash_cmd)
os.system(bash_cmd)
print_msg = "\tdump {:}".format(file_name)
print(print_msg)
for key, value in tlog_msg_types.items():
print("\t\t{} - {}".format(key, value))
|
cs |
pymavlink를 이용하여 dialect 만들고 로그 데이터 추출용 코드 생성하기
pymavlink는 사용자가 *.xml 형태의 dialect를 만들면 pymavlink에서 사용할 수 있도록 코드를 자동생성해주는 라이브러리인 mavgen을 제공한다. mavgen의 사용 명령어는 다음과 같다.
python -m mavgen --wire-protocol [MAVLINK_VERSION] -o [OUTPUT_NAME] [XML_FILENAME]
python -m mavgen --wire-protocol 2.0 -o somewhere\common somewhere\common.xml
각 인자에 대해서 설명하면 다음과 같다.
- MAVLINK_VERSION : 특정 MAVLink 버전을 선택해서 처리하며 0.9, 1.0, 2.0을 고를 수 있으며 기본은 1.0 이다.
- OUTPUT_NAME : 출력 파일의 이름을 기입한다.이름에는 확장자를 쓰지 않는다. 기본적으로 py 파일로 출력되며, 생략하면 mavlink.py으로 출력된다.
- XML_FILENAME : 입력할 MAVLink 메시지를 정의한 *.xml 파일을 경로를 포함하여 입력한다.
이렇게 자동 생성된 파이썬 코드 *.py 파일을 앞서 언급한 pymavlink 패키지 위치의 MAVLink 버전 폴더 [PYMAVLINK_PATH]\dialects\v20 에 놓아주면 pymavlink 에서 사용할 수 있다.
예시로 보면 해당 위치에는 다음과 같이 MAVLink 메시지의 정의 파일 *.xml 과 메시지 정의를 파이썬에서 쓸 수 있도록 만들어둔 라이브러리 파일인 *.py 파일이 위치한다.
끝
Reference
[2] https://mavlink.io/kr/messages/common.html
[3] https://mavlink.io/en/mavgen_python/
[4] https://mavlink.io/en/messages/
** EOF **
'SW' 카테고리의 다른 글
파이썬 스크립트를 실행파일로 만들기 : PyInstaller (0) | 2024.04.18 |
---|---|
[PyQt5] 중복된 띄어쓰기를 1개로 치환해주는 GUI 프로그램 (0) | 2024.02.27 |
임베디드 코드에서 C++ 사용하는 방법 찾아보기 (0) | 2023.10.09 |
PX4, ROS2 and Gazebo On Ubuntu 22.04 (0) | 2023.09.26 |
[PyQt5] 새창 띄워서 matplotlib & blit을 이용한 더 빠른 실시간 그래프 그리기 (0) | 2023.08.08 |