fpltool (release, no ROS, 0.0.0-heads/main-0-g97f6014)
Copyright (c) Fixposition AG (www.fixposition.com) and contributors
License: see the LICENSE files included in the source distribution
Tool for .fpl files (recordings)
Usage:
fpltool [<flags>] <command> <fpl-file> [...]
Where (availability of flags depends on <command>, see below):
-h, --help -- Print program help screen, and exit
-V, --version -- Print program, version and license information, and exit
-v, --verbose -- Increase logging verbosity, multiple flags accumulate
-q, --quiet -- Decrease logging verbosity, multiple flags accumulate
-J, --journal -- Use systemd journal logging markers instead of colours
-p, --progress -- Show progress (default: automatic)
-P, --no-progress -- Don't show progress (default: automatic)
-f, --force -- Force overwrite output (default: refuse to overwrite existing output files)
-c, --compress -- Compress output (e.g. ROS bags), -c -c to compress more
-x, --extra -- Add extra output, multiple -x can be given
-o, --output <out> -- Output file prefix <out> (default: derive from <fpl-file> name)
-S, --skip <sec> -- Skip <sec> seconds from start of log (default: 0, i.e. no skip)
-D, --duration <sec> -- Process <sec> seconds of log (default: everything)
-e, --formats <fmts> -- Comma-separated list of output formats for the extract <command> (default: all)
<command> -- The command, see below
<fpl-file> -- The .fpl (or .fpl.gz) file to process
The available <command>s are:
meta -- Print the meta data
fpltool [-vqpP] meta <fpl-file>
The meta printed to stdout is suitable for further processing (yq, Python, ...).
dump -- Print information about the data in a .fpl file
fpltool [-vqpPx] dump <fpl-file>
By default it prints the statistics and meta data to stdout. With -x it prints a line for all data
in the <fpl-file> (sequence number, offset into <fpl-file>, size of chunk, type of data, debug info).
Adding another -x adds a hexdump.
Note that with -x this can print a lot of output to stdout!
trim -- Trim a .fpl file to a shorter .fpl file
fpltool [-vqpPfoc] -S <start-sec> -D <duration> <fpl-file>
This shortens the <fpl-file> by removing (skipping) <start-sec> seconds of data from the beginning
and using <duration> sections from that point in the <fpl-file>. Note that this process is inaccurate
and the effective start time and duration of the resulting file may be off by 30 to 60 seconds.
Therefore, both the <start-sec> and <duration> must be at least 60 seconds.
rosbag -- Extract (some of) the data to a ROS bag
This is an alias of 'extract -e ros'. See that for details.
extract -- Extract the data in a .fpl file
fpltool [-vqpPfocSD] [-e <fmts>] extract <fpl-file>
The data is extracted to different files in the current directory. The files are named like the
<fpl-file> with added suffixes and different file extension, depending on the kind of data that
is extracted. By default the data is extracted to all supported formats. Specify a comma-separated
list of formats in <fmts> to limit to some formats. The available output data formats are:
jsonl -- All data in JSONL format (see below)
raw -- Stream messages (I/O messages, raw messages from GNSS receiver, ...)
file -- Recorded files (configuration, ...)
ros -- ROS data extracted to a ROS bag. This option is only available when compiled with ROS
(1 or 2) support (see output of 'fpltool -V' to check what your version is). For ROS1
the standard .bag file format is used. For ROS2 the standard sqlite3 format is used,
unless compression is used, in which case the mcap format is used.
The jsonl format consists of one JSON object per line. Depending on the data different fields are
available. The fields starting with a '_' (_type, ...) should always be present. The fields not
starting with a '_' are decoded values. What values can be decoded depends on the data in question,
the sensor configuration and software version, and the fpltool support for the data. Typically,
the following kind of JSON objects can be found in the exacted .jsonl file:
Log meta data: { "_type": "LOGMETA", "_yaml": "...", ... }
Where _yaml contains the raw meta data in YAML format. The additional fields (...) are decoded
from that (hw_uid, product_model, sw_version, etc.)
Log status data: { "_type": "LOGSTATUS", "_yaml": "...", ... }
Where _yaml contains the raw status data in YAML format. The additional fields (...) are decoded
from that (state, log_duration, log_size, etc.)
ROS data: { "_type": "ROSMSGBIN", "_topic": "...", "_msg": "...", "_stamp": ..., ... }
Where _topic is the ROS topic (e.g. /imu/data), _msg is the message type (e.g. sensor_msgs/Imu),
_stamp is the recording (!) timestamp, and ... are the decoded data (e.g. header with frame_id,
seq and stamp, linear_acceleration, etc.). See the ROS1 documentation for the definitions of
the decoded fields.
Stream messages: { "_type": "STREAMMSG", "_stream": "...", "_stamp": ..., "_raw": "...",
"_raw_b64": "...", "_proto": "...", "_name": "...", "_seq": ...,
"_valid": ..., ... }
Where _stream is the stream name (userio, gnss1, ...), _stamp is the recording (!) timestamp,
_raw or _raw_b64 is the raw message data (_raw if data is non-binary, _raw_b64 = base64 encoded
binary data), _proto is the protocol name (FP_A, NMEA, ...), _name is the message name
(FP_A-ODOMETRY, NMEA-GN-RMC, ...), _seq is the sequence counter, and _valid indicates if the
message could be decoded (true) or not (false). Note that decoded fields (...) may be null.
See the protocol (UBX, FP_A, NMEA) specification documentation for the definitions of the
decoded fields.
Files: { "_type": "FILEDUMP", "_filename": "...", "_mtime": "...", "_stamp": ...,
"_data": "...", "_data_b64": "..." }
Where _filename is the filename of the file, _mtime its last modification time and _data or
or _data_b64 is the file contents (_data if it is non-binary, _data_b64 = base64 encoded data).
Examples:
Print the sensor UID of the sensor that recorded the fpl:
fpltool -qq meta some.fpl | yq .hw_uid
Save detailed info about recorded data to a text file:
fpltool -x dump some.fpl > some.txt
Extract all data from a .fpl file:
fpltool extract some.fpl
Create a ROS some.bag file (ROS1) resp. some_bag directory (ROS2) from a .fpl file:
fpltool extract -e ros some.fpl
fpltool robag some.fpl # shortcut
Create a compressed another.bag (res. another_bag) with 2 minutes of data starting 60 seconds into some.fpl:
fpltool rosbag some.fpl -c -c -o another.bag -S 60 -D 120
Check what is in the extracted ROS bag:
rosbag info some.bag # ROS 1
ros2 bag info some_bag # ROS 2 (default, see above)
mcap info some_bag/some.mcap # ROS 2 (with compression, see above)
Check what is in some_userio.raw obtained by 'extract some.fpl':
parsertool some_userio.raw > some_userio.txt
Pretty-print some_all.jsonl obtained by 'extract some.fpl':
jq < some_all.jsonl
Pretty-print all some_all.jsonl obtained by 'extract some.fpl':
jq < some_all.jsonl
fpltool meta some.fpl
Trim a verylong.fpl into a shorter one:
fpltool trim some.fpl -S 3600 -D 1800
Extract data from some.fpl:
fpltool extract some.fpl
Pretty-print all log status from some_all.jsonl obtained by 'extract some.fpl':
jq '.|select(._type=="LOGSTATUS")' < some_all.jsonl
Pretty-print all IMU samples from some_all.jsonl obtained by 'extract some.fpl':
jq '.|select(._type=="ROSMSGBIN" and ._topic=="/imu/data")' < some_all.jsonl
Plot IMU acceleration from some_all.jsonl obtained by 'extract some.fpl':
jq -r '.|select(._topic=="/imu/data") | .linear_acceleration | join(" ")' \
< some_all.jsonl > plot.dat
gnuplot -p -e 'plot "plot.dat" using 1 w l t "x", "" using 2 w l t "y", "" using 3 w l t "z"'