Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Type Mapping

Effective conversion between Protobuf and ROS2 message formats requires careful consideration of type system differences. This chapter provides comprehensive information about how ROC maps types between these systems.

Type System Comparison

Protobuf Type System

Protobuf uses a rich type system designed for cross-language compatibility:

  • Primitive Types: Integers of various sizes, floating-point, boolean, string, bytes
  • Composite Types: Messages (structs), enums, oneofs (unions)
  • Container Types: Repeated fields (arrays), maps
  • Special Types: Well-known types (Timestamp, Duration, Any, etc.)
  • Advanced Features: Optional fields, default values, extensions

ROS2 Type System

ROS2 uses a simpler, more constrained type system:

  • Primitive Types: Fixed-size integers, floating-point, boolean, string
  • Composite Types: Messages (structs), constants
  • Container Types: Fixed and dynamic arrays
  • Special Types: Standard message types (Header, etc.)
  • Constraints: Bounded arrays, default values

Comprehensive Type Mapping Tables

Protobuf to ROS2 Mapping

Numeric Types

Protobuf TypeROS2 TypeSizeSignedNotes
boolbool1 byteN/ADirect mapping
int32int324 bytesYesDirect mapping
int64int648 bytesYesDirect mapping
uint32uint324 bytesNoDirect mapping
uint64uint648 bytesNoDirect mapping
sint32int324 bytesYesZigZag encoded in protobuf
sint64int648 bytesYesZigZag encoded in protobuf
fixed32uint324 bytesNoFixed-width encoding
fixed64uint648 bytesNoFixed-width encoding
sfixed32int324 bytesYesFixed-width signed
sfixed64int648 bytesYesFixed-width signed
floatfloat324 bytesYesIEEE 754 single precision
doublefloat648 bytesYesIEEE 754 double precision

String and Binary Types

Protobuf TypeROS2 TypeNotes
stringstringUTF-8 encoded strings
bytesuint8[]Binary data as byte array

Container Types

Protobuf TypeROS2 TypeExample
repeated TT[]repeated int32 valuesint32[] values
map<K,V>MapEntry[]map<string,int32> dataDataEntry[] data

ROS2 to Protobuf Mapping

Numeric Types

ROS2 TypeProtobuf TypeRationale
boolboolDirect mapping
byteuint32ROS2 byte is unsigned 8-bit
charint32ROS2 char is signed 8-bit
int8int32Protobuf doesn't have 8-bit integers
uint8uint32Protobuf doesn't have 8-bit integers
int16int32Protobuf doesn't have 16-bit integers
uint16uint32Protobuf doesn't have 16-bit integers
int32int32Direct mapping
uint32uint32Direct mapping
int64int64Direct mapping
uint64uint64Direct mapping
float32floatDirect mapping
float64doubleDirect mapping
stringstringDirect mapping

Array Types

ROS2 TypeProtobuf TypeNotes
T[]repeated TDynamic arrays
T[N]repeated TFixed-size arrays (size constraint lost)
T[<=N]repeated TBounded arrays (bound constraint lost)

Special Type Conversions

Protobuf Oneof to ROS2

Protobuf oneof fields don't have a direct equivalent in ROS2. ROC handles this by creating separate optional fields:

// Protobuf
message Command {
  oneof command_type {
    string text_command = 1;
    int32 numeric_command = 2;
    bool flag_command = 3;
  }
}

Converts to:

# ROS2 - all fields are optional, only one should be set
string text_command
int32 numeric_command
bool flag_command

Protobuf Maps to ROS2

Maps are converted to arrays of key-value pair messages:

// Protobuf
message Configuration {
  map<string, double> parameters = 1;
}

Converts to:

# Configuration.msg
ConfigurationParametersEntry[] parameters

# ConfigurationParametersEntry.msg (auto-generated)
string key
float64 value

ROS2 Constants to Protobuf

ROS2 constants are converted to enum values when they represent a set of related values:

# ROS2
uint8 STATE_IDLE=0
uint8 STATE_MOVING=1
uint8 STATE_ERROR=2
uint8 current_state

Converts to:

// Protobuf
enum State {
  STATE_IDLE = 0;
  STATE_MOVING = 1;
  STATE_ERROR = 2;
}

message RobotStatus {
  State current_state = 1;
}

Well-Known Type Mappings

Protobuf Well-Known Types

ROC provides special handling for common Protobuf well-known types:

Protobuf TypeROS2 EquivalentNotes
google.protobuf.Timestampbuiltin_interfaces/TimeNanosecond precision
google.protobuf.Durationbuiltin_interfaces/DurationNanosecond precision
google.protobuf.EmptyEmpty messageNo fields
google.protobuf.StringValuestringWrapper type flattened
google.protobuf.Int32Valueint32Wrapper type flattened
google.protobuf.BoolValueboolWrapper type flattened

Standard ROS2 Types

Common ROS2 types have conventional Protobuf mappings:

ROS2 TypeProtobuf EquivalentNotes
std_msgs/HeaderCustom messageTimestamp + frame_id
geometry_msgs/PointCustom messagex, y, z coordinates
geometry_msgs/QuaternionCustom messagex, y, z, w components
geometry_msgs/PoseCustom messagePosition + orientation
geometry_msgs/TwistCustom messageLinear + angular velocity

Type Conversion Edge Cases

Precision and Range Considerations

Integer Overflow Scenarios

# ROS2 uint8 field
uint8 small_value 255  # Maximum value for uint8

When converted to Protobuf uint32, the range increases significantly. ROC preserves the original constraint information in comments:

// Protobuf
message Example {
  uint32 small_value = 1;  // Originally uint8, max value 255
}

Floating-Point Precision

# ROS2 float32
float32 precise_value 3.14159265359

Converting to Protobuf maintains the precision level:

float precise_value = 1;  // 32-bit precision maintained

Array Bound Handling

Fixed-Size Arrays

# ROS2 fixed-size array
float64[3] position

Protobuf doesn't support fixed-size arrays, so this becomes:

repeated double position = 1;  // Size constraint documented separately

Bounded Arrays

# ROS2 bounded array
int32[<=100] readings

The bound constraint is preserved in documentation:

repeated int32 readings = 1;  // Maximum 100 elements

Advanced Mapping Strategies

Nested Message Flattening

ROC flattens nested Protobuf messages for ROS2 compatibility:

// Protobuf nested messages
message Robot {
  message Status {
    bool active = 1;
    string state = 2;
  }
  Status current_status = 1;
  string robot_id = 2;
}

Becomes:

# Robot.msg
RobotStatus current_status
string robot_id

# RobotStatus.msg (flattened)
bool active
string state

Package and Namespace Translation

Protobuf Package to ROS2 Package

// Protobuf
syntax = "proto3";
package robotics.sensors;

message LaserData { ... }

Becomes:

# File: robotics_sensors_msgs/msg/LaserData.msg
# Content of the message...

ROS2 Package to Protobuf Package

# File: my_robot_msgs/msg/Status.msg
# Message content...

Becomes:

syntax = "proto3";
package my_robot_msgs;

message Status { ... }

Configuration and Customization

Custom Type Mappings

ROC supports configuration files for custom type mappings:

# type_mappings.yaml
protobuf_to_ros2:
  "my.custom.Timestamp": "builtin_interfaces/Time"
  "my.custom.Position": "geometry_msgs/Point"

ros2_to_protobuf:
  "my_msgs/CustomType": "my.package.CustomMessage"

Usage:

roc idl protobuf --config type_mappings.yaml input_files...

Mapping Validation

ROC validates type mappings and warns about potential issues:

Warning: Converting uint64 to int64 may cause overflow for large values
Warning: Map type conversion may affect lookup performance
Warning: Oneof semantics lost in ROS2 conversion

Performance Implications

Serialization Efficiency

Different type choices affect serialization performance:

  • Protobuf varint encoding: Smaller integers encode more efficiently
  • Fixed-width types: Predictable size but potentially wasteful
  • String vs bytes: UTF-8 validation overhead for strings

Memory Usage

Type conversions can affect memory usage:

  • Array bounds: ROS2 bounded arrays vs Protobuf repeated fields
  • Message size: Nested vs flattened message structures
  • Field ordering: Affects struct packing and cache efficiency

Best Practices for Type Mapping

Design Considerations

  1. Choose appropriate numeric types: Don't use int64 when int32 suffices
  2. Consider array bounds: Use bounded arrays in ROS2 when possible
  3. Document constraints: Preserve semantic meaning across conversions
  4. Plan for evolution: Design messages that can evolve over time

Conversion Guidelines

  1. Test thoroughly: Validate converted messages with real data
  2. Preserve semantics: Maintain the original meaning of fields
  3. Document decisions: Record rationale for non-obvious mappings
  4. Monitor performance: Profile converted message performance

Maintenance Strategies

  1. Version control: Track message schema changes
  2. Backward compatibility: Plan for schema evolution
  3. Testing automation: Automated conversion validation
  4. Documentation updates: Keep mapping documentation current

Understanding these type mapping strategies ensures successful and maintainable conversions between Protobuf and ROS2 message formats.