Visualize dive log sensor data with Foxglove
With some simple steps you can visualize dive log data with ease in Foxglove. This is a great tool to play back and visualize control signals and estimated states and other sensor data from the dive.
- Download foxglove here and create an account.
- Download a divelog from the drone as shown here.
- Run
pip install "blueye.sdk[examples]"to get the necessary dependencies, if you have not done so already. - Clone the blueye.sdk repository to get the examples, or copy the script below into a file. In the examples folder you simply run
python foxglove_bez_to_mcap.py <logfile.bez> [output_filename.mcap]to convert your .bez-file. - Open foxglove, in the top left menu, click on
Open local file, and pick your newly created .mcap-file. - Click on
Add panel, andRaw message, orPlotand select the signal you want to display. - Start typing
DepthTel.depth.valueto get auto-complete on all available messages in the protocol. - You can also get a nice overview of the logged messages with this command:
mcap info logfile.mcapin your terminal.
The .bez to .mcap log file converter:
import os
import time
from mcap_protobuf.writer import Writer
import sys
from blueye.sdk.logs import LogStream
from pathlib import Path
def parse_logfile(log: Path) -> LogStream:
log_bytes = b""
with open(log, "rb") as f:
log_bytes = f.read()
return LogStream(log_bytes)
def main(logfile_path, output_mcap_path):
start_time_tic = time.time()
print(f"Converting {logfile_path} to {output_mcap_path}...")
# Prepare MCAP writer
with open(output_mcap_path, "wb") as mcap_file:
writer = Writer(mcap_file)
# Read messages from the log file, deserialize, and forward the protobuf object to the MCAP file.
path = Path(logfile_path)
# We need to get the last message's timestamp and delta in order to get the correct start time
# after the clock is set. The delta time is then added to the start time to get a continuous timeline in foxglove.
last_time = 0
last_delta = 0
for last_time, last_delta, _, _ in parse_logfile(path):
continue
start_time = last_time - last_delta
count = 0
for unix_ts, delta, msg_type, msg in parse_logfile(path):
writer.write_message(
topic=msg_type.__name__,
message=msg._pb,
log_time=int((start_time + delta).timestamp() * 1e9),
publish_time=int((start_time + delta).timestamp() * 1e9),
)
count += 1
# Add indexes to the MCAP file
writer.finish()
print(f"MCAP file successfully created!")
print(
f"Total of messages written: {count} in {round(time.time() - start_time_tic, 3)} seconds"
)
print(f"MCAP file name: {output_mcap_path}")
print(f"MCAP file size: {round(os.path.getsize(output_mcap_path)/1000000, 2)} MB")
print(f"Start of dive time: {unix_ts - delta}")
print(f"Duration of dive log: {delta}")
if __name__ == "__main__":
if len(sys.argv) < 2:
print("Usage: python bez_to_mcap.py <logfile.bez> [output_filename.mcap]")
sys.exit(1)
logfile = sys.argv[1]
output = sys.argv[2] if len(sys.argv) > 2 else sys.argv[1].replace(".bez", ".mcap")
main(logfile, output)