센서 데이터 수집을 위해 ros2 bag을 이용했다.
이때 ros2 bag record가 정상 종료되면 db3 파일과 metadata 파일이 생긴다.
- metadata.yaml은 다음과 같은 내용을 가지고 있으며 ROS 노드와 토픽 메시지 정보가 있다.
rosbag2_bagfile_information:
version: 4
storage_identifier: sqlite3
relative_file_paths:
- new_0.db3
duration:
nanoseconds: 8231007494
starting_time:
nanoseconds_since_epoch: 1717553797242000455
message_count: 102
topics_with_message_count:
- topic_metadata:
name: /turtle1/cmd_vel
type: geometry_msgs/msg/Twist
serialization_format: cdr
offered_qos_profiles: "- history: 3\n depth: 0\n reliability: 1\n durability: 2\n deadline:\n sec: 2147483647\n nsec: 4294967295\n lifespan:\n sec: 2147483647\n nsec: 4294967295\n liveliness: 1\n liveliness_lease_duration:\n sec: 2147483647\n nsec: 4294967295\n avoid_ros_namespace_conventions: false"
message_count: 102
compression_format: ""
compression_mode: ""
- 이게 있어야 ros2 bag info로 정보 확인이 가능하다.
- 하지만 없어도 bag파일을 play하는데 문제되지는 않는다.
- sigint가 발생해야 metadata.yaml이 생성된다.
문제 및 해결
문제
비정상적인 종료에 따라 bag 파일이 제대로 저장되지 않는 문제 발생
분석
- metadata.yaml 까지 생성되어야 ros2 bag info 명령으로 bag 파일 정보 확인이 가능하다.
- 비정상적인 종료 발생 시 metadata.yaml이 제대로 생성되지 않는 문제가 발생한다. ctrl+c 로 종료 시에도 생성되지 않는다.
- 하지만 metadata.yaml 이 없어도 db3파일을 이용해 bag 파일 play는 가능하다.
해결
- sigint 발생 시 metadata.yaml 이 정상적으로 생성되는 것을 발견했다.
- 실행 스크립트 종료 시 ros2 bag이 들어간 프로세스를 검색하고 모두 sigint 처리로 종료시키도록 적용했다.
KILLALL_FUNC() {
while pgrep -f "ros2 bag record" >/dev/null; do
pgrep -f "ros2 bag record" | xargs kill -2
echo "=================== KILL ROS2 BAG RECORD ======================"
sleep 1
done
}
KILLALL='KILLALL_FUNC'
trap "$KILLALL; sleep 1; $KILLALL" EXIT INT QUIT KILL SEGV TERM
metadata 복구하기
https://github.com/arplaboratory/ros2bag_fixer
GitHub - arplaboratory/ros2bag_fixer
Contribute to arplaboratory/ros2bag_fixer development by creating an account on GitHub.
github.com
ros2 bag record 진행 중 PC 전원이 갑자기 종료되거나 비정상적인 종료가 발생하면 db3파일을 직접 play하는 것 외에는 ros2 bag play 명령이 되지 않는다. 비정상적인 종료 시 사진과 같이 저장이 된다.
sqlite3 툴을 이용해 db3 파일을 sql 파일로 변환한다.
chmod +x sqlite3
./sqlite3 path_to_corrupt.db3 .recover >data.sql
sql 파일을 csv 파일로 변환한다.
python3 sql_to_csv.py --input path/to/file.sql --output path/to/output_base.csv
*이때 sql_to_csv.py 에서 create_table_pattern = re.compile(r'CREATE TABLE\s+"?(\w+)"?', re.IGNORECASE) 부분을 create_table_pattern = re.compile(r'CREATE TABLE (?:IF NOT EXISTS )?"?(\w+)"?', re.IGNORECASE)로 변경해야 한다.
결과
변경 후 진행을 하면 다음과 같은 내용을 얻을 수 있다. 이때 두 번째 사진의 data는 BLOB(Binary Large Object) 형식의 내용이다.