mirror of
https://github.com/okalachev/flix.git
synced 2025-07-27 09:39:33 +00:00
Add C++ tool for conversion csv logs to ulog
This commit is contained in:
parent
1119c77cca
commit
63d602dd7a
21
.github/workflows/tools.yml
vendored
Normal file
21
.github/workflows/tools.yml
vendored
Normal file
@ -0,0 +1,21 @@
|
||||
name: Build tools
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ '*' ]
|
||||
pull_request:
|
||||
branches: [ master ]
|
||||
|
||||
jobs:
|
||||
csv_to_ulog:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Build csv_to_ulog
|
||||
run: cd tools/csv_to_ulog && mkdir build && cd build && cmake .. && make
|
||||
- name: Test csv_to_ulog
|
||||
run: |
|
||||
cd tools/csv_to_ulog/build
|
||||
echo -e "t,x,y,z\n0,1,2,3\n1,4,5,6" > log.csv
|
||||
./csv_to_ulog log.csv
|
||||
test $(stat -c %s log.ulg) -eq 196
|
23
tools/csv_to_ulog/CMakeLists.txt
Normal file
23
tools/csv_to_ulog/CMakeLists.txt
Normal file
@ -0,0 +1,23 @@
|
||||
cmake_minimum_required(VERSION 3.15)
|
||||
project(csv_to_ulog)
|
||||
include(FetchContent)
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
|
||||
FetchContent_Declare(
|
||||
ulog_cpp
|
||||
GIT_REPOSITORY https://github.com/PX4/ulog_cpp.git
|
||||
GIT_TAG cf24ec6
|
||||
)
|
||||
|
||||
FetchContent_Declare(
|
||||
rapidcsv
|
||||
GIT_REPOSITORY https://github.com/d99kris/rapidcsv.git
|
||||
GIT_TAG v8.82
|
||||
)
|
||||
|
||||
FetchContent_MakeAvailable(ulog_cpp)
|
||||
FetchContent_MakeAvailable(rapidcsv)
|
||||
|
||||
add_executable(csv_to_ulog csv_to_ulog.cpp)
|
||||
target_link_libraries(csv_to_ulog PUBLIC ulog_cpp::ulog_cpp)
|
||||
target_include_directories(csv_to_ulog PUBLIC ${rapidcsv_SOURCE_DIR}/src)
|
20
tools/csv_to_ulog/README.md
Normal file
20
tools/csv_to_ulog/README.md
Normal file
@ -0,0 +1,20 @@
|
||||
# csv_to_ulog
|
||||
|
||||
Tool for converting CSV flight logs to ULog format so they can be analyzed using [FlightPlot](https://github.com/PX4/FlightPlot) software.
|
||||
|
||||
To build, go to the `<flix>/tools/csv_to_ulog` directory and run:
|
||||
|
||||
```bash
|
||||
mkdir build
|
||||
cd build
|
||||
cmake ..
|
||||
make
|
||||
```
|
||||
|
||||
Convert a CSV file to ULog:
|
||||
|
||||
```bash
|
||||
./csv_to_ulog log_file.csv
|
||||
```
|
||||
|
||||
ULog file will be saved in the same directory.
|
72
tools/csv_to_ulog/csv_to_ulog.cpp
Normal file
72
tools/csv_to_ulog/csv_to_ulog.cpp
Normal file
@ -0,0 +1,72 @@
|
||||
// Copyright (c) 2023 Oleg Kalachev <okalachev@gmail.com>
|
||||
// Repository: https://github.com/okalachev/flix
|
||||
|
||||
// Tool for conversion CSV log file to ULog format
|
||||
|
||||
#include <ulog_cpp/simple_writer.hpp>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <filesystem>
|
||||
#include "rapidcsv.h"
|
||||
|
||||
using std::vector;
|
||||
using std::string;
|
||||
|
||||
struct Data {
|
||||
uint64_t timestamp;
|
||||
float values[30];
|
||||
};
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
if (argc < 2) {
|
||||
printf("Usage: %s file.csv [file.ulg]\n", argv[0]);
|
||||
return -1;
|
||||
}
|
||||
|
||||
// check input file exists
|
||||
if (!std::filesystem::exists(argv[1])) {
|
||||
printf("Input file \"%s\" does not exist\n", argv[1]);
|
||||
return -1;
|
||||
}
|
||||
|
||||
// open csv file
|
||||
rapidcsv::Document csv(argv[1]);
|
||||
auto columns = csv.GetColumnNames();
|
||||
|
||||
|
||||
// open ulog file
|
||||
string ulog_file;
|
||||
if (argc < 3) {
|
||||
ulog_file = std::filesystem::path(argv[1]).replace_extension(".ulg").string();
|
||||
} else {
|
||||
ulog_file = argv[2];
|
||||
}
|
||||
ulog_cpp::SimpleWriter writer(ulog_file.c_str(), 0);
|
||||
writer.writeInfo("sys_name", "flix");
|
||||
|
||||
vector<ulog_cpp::Field> fields;
|
||||
fields.push_back(ulog_cpp::Field("uint64_t", "timestamp"));
|
||||
columns.erase(columns.begin()); // remove timestamp column
|
||||
for (auto& column : columns) {
|
||||
// Valid field name for ULog: [a-z0-9_]+
|
||||
std::replace(column.begin(), column.end(), '.', '_'); // replace dots with underscores
|
||||
std::transform(column.begin(), column.end(), column.begin(), [](unsigned char c) { return std::tolower(c); }); // lowercase column name
|
||||
fields.push_back(ulog_cpp::Field("float", column));
|
||||
}
|
||||
|
||||
const char* msg_name = "state";
|
||||
writer.writeMessageFormat(msg_name, fields);
|
||||
writer.headerComplete();
|
||||
|
||||
const uint16_t msg_id = writer.writeAddLoggedMessage(msg_name);
|
||||
|
||||
for (size_t i = 0; i < csv.GetRowCount(); i++) {
|
||||
Data data;
|
||||
data.timestamp = csv.GetCell<float>(0, i) * 1000000.0;
|
||||
for (size_t j = 1; j <= columns.size(); j++) {
|
||||
data.values[j - 1] = csv.GetCell<float>(j, i);
|
||||
}
|
||||
writer.writeData(msg_id, data);
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user