Skip to main content
Beyond the built-in message types, Avala can parse custom messages defined with Protobuf, JSON Schema, or ROS .msg definitions. This means you can record proprietary sensor data or application-specific messages and still visualize them in Avala.

Protobuf

If your MCAP file uses Protocol Buffers for serialization, include the .proto file descriptors in the MCAP schema registry. Avala reads the embedded schema and decodes messages automatically — no server-side schema configuration is needed.

Embedding Protobuf Schemas

When writing MCAP files with the MCAP Python library, register your schema before writing messages:
from mcap.writer import Writer

with open("recording.mcap", "wb") as f:
    writer = Writer(f)
    writer.start()

    # Read your compiled .proto file descriptor
    with open("my_message.desc", "rb") as desc:
        schema_data = desc.read()

    schema_id = writer.register_schema(
        name="my_package.MyMessage",
        encoding="protobuf",
        data=schema_data,
    )

    channel_id = writer.register_channel(
        topic="/my_topic",
        message_encoding="protobuf",
        schema_id=schema_id,
    )

    # Write messages using the registered channel
    writer.add_message(
        channel_id=channel_id,
        log_time=timestamp_ns,
        publish_time=timestamp_ns,
        data=my_message.SerializeToString(),
    )

    writer.finish()
Generate the .desc file from your .proto source using protoc:
protoc --descriptor_set_out=my_message.desc --include_imports my_message.proto
The --include_imports flag ensures all referenced types are included in the descriptor.

JSON Schema

MCAP files that use JSON serialization with embedded JSON Schema definitions are parsed automatically. Avala uses the embedded schema to understand field names, types, and structure.

Embedding JSON Schemas

When writing MCAP files with JSON-encoded messages, register the JSON Schema as the schema data:
import json
from mcap.writer import Writer

schema = {
    "type": "object",
    "properties": {
        "timestamp": {"type": "number"},
        "temperature": {"type": "number"},
        "status": {"type": "string"},
    },
}

with open("recording.mcap", "wb") as f:
    writer = Writer(f)
    writer.start()

    schema_id = writer.register_schema(
        name="my_package.SensorReading",
        encoding="jsonschema",
        data=json.dumps(schema).encode(),
    )

    channel_id = writer.register_channel(
        topic="/sensor/temperature",
        message_encoding="json",
        schema_id=schema_id,
    )

    writer.add_message(
        channel_id=channel_id,
        log_time=timestamp_ns,
        publish_time=timestamp_ns,
        data=json.dumps({"timestamp": 1.0, "temperature": 23.5, "status": "ok"}).encode(),
    )

    writer.finish()

ROS Message Definitions

Standard .msg files embedded in ROS 1 bags and ROS 2 bags are used for decoding automatically. When you record with rosbag record (ROS 1) or ros2 bag record (ROS 2), the message definitions are embedded in the bag file by the recording tool.
ROS 1 bags embed .msg definitions in the bag header. No additional steps are needed — rosbag record includes them automatically.
# Record with message definitions embedded (default behavior)
rosbag record /my_custom_topic /camera/image_raw /lidar/points
If you convert ROS bags to MCAP, make sure the conversion tool preserves the embedded message definitions. The mcap CLI handles this automatically:
# Convert a ROS 1 bag to MCAP (preserves message definitions)
mcap convert recording.bag recording.mcap

# Convert a ROS 2 bag to MCAP
mcap convert recording.db3 recording.mcap

How Custom Messages Are Displayed

Custom messages that do not match a built-in schema are displayed in the Raw Messages panel by default. The panel renders every field as an expandable JSON tree, making it straightforward to inspect the data. In addition:
  • Numeric fields within custom messages can be plotted in the Plot panel. If a custom message contains fields like temperature, velocity, or any numeric value, you can assign the topic to a Plot panel to see those values over time.
  • Known sub-message types are recognized even within custom messages. For example, if your custom message contains a sensor_msgs/PointCloud2 field, Avala can render that field in a 3D panel.
Need a fully custom visualization for your proprietary message type? Contact support@avala.ai to discuss custom panel rendering for your use case.

Best Practices

Embed schemas in the file

Always include schema definitions (Protobuf descriptors, JSON Schemas, or ROS .msg files) directly in the MCAP file. This ensures Avala can decode every message without external dependencies.

Use consistent naming

Name your custom schemas with a clear package prefix (e.g., my_company.SensorReading). Consistent naming makes it easier to identify topics in the viewer and across recordings.

Include type information

Provide full type annotations in your schemas. Typed fields enable richer visualization — for example, Avala can plot numeric fields and display string fields as labels.

Test with a small recording

Before uploading a large dataset, test your custom schema with a short recording to verify that Avala parses and displays the messages correctly.

Next Steps