Skip to main content

Starting with Protobufs


Last updated: 15-2026-04-202615

On this page

1) What are protobufs (and why we use them)protobufs?

Protocol Buffers (protobufs) are a way to define structured messages (data packets) in a language-neutral, versionable schema format (.proto). files.

The value propositionpoint is simple: we writedefine the message format once, and thenonce, generate code infor C.your Solanguage, everyand componentnow everyone agrees on what the bytes mean.mean

Protobufs are the shared language they use to exchange status, commands and telemetry (without hand-writteninventing a new packet formatsformat slowlyevery evolving into folklore.semester).

2) Where protobufsthey existlive

The canonicalsource homeof truth for RoboTeam message definitions is: RoboTeamTwente/ERC-Protobufs.

RepoOther description:repositories “The official protobuffers (embedded, controlsoftware, &tooling) softwareshould use for communication”.

consumeEmbedded firmware that consumes these messages lives in: RoboTeamTwente/ERC-Embedded/ERC-Protobuffsdefinitions (mostlyoften C).

3) The mental model: schema → code → bytes

  1. Schema: you define messages/enums in .proto.
  2. Generated code:via a compilergit (protoc)submodule) generatesinstead language-specificof code. (SOFTWARE DOES THIS, MOST OF THE TIME, embedded uses nanopb)
  3. Runtime: your program fills in fields → serializes to bytes → sends bytes over some transport (UART/CAN/UDP/etc.).
  4. Receiver: reads bytes → deserializes using the same schema → gets the structured message back.

4) Rules for editingcopy-pasting .proto files around.

3) Editing rules (the important part)

Field numbers are the real API

In protobuf, the integer tags (field numbers)number areis what goes on the wirewire. format cares about.

Renaming a field is usually doesharmless; nothingchanging onits number is usually the wire; changing a field number changes everything.problem.

Never renumber fields in an existing messagefield unless you’reyou are intentionally breaking compatibility and coordinating the changeupdate across all consumers.

PreferredSafe changechanges types(usually)

  • Add a new optional field with a new,new unused number.
  • Add new enum values (don’t reorderreuse existingold onesnumeric values for new meanings).
  • Stop using a field before deleting it, and reserve its number if your toolingstyle isguide sensitive).
  • Deprecatedoes fields instead of deleting them immediately.that.

Changes that need extra care

  • Changing a field type (e.g. int32string).
  • Changing semanticssemantics/units (“thismm isvs nowm, metersdegrees notvs millimeters”)radians).

5)4) Typical workflow in RoboTeam

  1. PickEdit the/ messageadd you.proto need to change/addfiles in ERC-Protobufs.
  2. EditGenerate the/ update code as required by your project (this step is repo-specific).proto file(s) with a clear goal..
  3. Update colleagues (embedded/control/software) if they needconsumers to use the new fields.fields (and handle missing fields safely).
  4. Test end-to-end:at serializeleast one sendreal send/receive deserialize on the other side.path.
  5. PushOpen ora createPR pullthat requestlists: in ERC-Protobufs:
    • what changedchanged, (fieldsfield +numbers, numbers)
    • whyand it changed
    • compatibility notes (“old firmware can still parse this” or “requires coordinated update”)
    expectations.

6)5) Compatibility: how to not break everyone

Protobuf is designed for forwards/backwards compatibility if you follow the rules. The main idea:

  • Old code should be able to read new messages (it ignores unknown fields).
  • New code should be able to read old messages (missing fields take default values).
  • PLEASE INFORM SOFTWARE, THEY USUALLY GET REALLY PARANOID WHEN THINGS MESS UP!!
    • DON'T WORRY, EMBEDDED OWNS PROTOBUFS☮️

Breaking changes: Reusing a field number for a different meaning is a fast path to silent corruption. The code compiles.

Deletions

If you must remove a field, prefer: stop using it + reserve the field number (so it can’t be reused). The exact syntax depends on protobuf version/style used in the repo.

7) Embedded extra notes (Protobufs Submodules)

Embedded projects are resource-constrained.

  • Payload size: fewer fields and smaller types can matter a lot.

Note: the exact embedded protobuf implementation (nanopb / protobuf-c / custom generator) depends on the current repo setup. Follow the build scripts and existing patterns in ERC-Embedded.

8) Debugging & troubleshootingTroubleshooting

“My message doesn’t parse”

  • Confirm both sides are usinguse the same (or compatible) .proto version (or compatible versions).definitions.
  • Check field numbers: didno someonereuse, accidentallyno reuse one?renumbering.
  • ValidateCheck transport framing:framing protobuf(length prefix / delimiter / CRC). Protobuf gives bytes; youtransport still need a correct length/prefix/CRC strategy.matters.

“It parsesparses, but values are nonsense”

  • Check units/units and semantics (mmthe vsmost m,common degrees“it’s vswrong radians)but not broken” bug).
  • ConfirmMake end-to-end: are you sending the message type you think you’re sending?
  • Look for stalesure generated code is up to date (someonestale updatedgenerated files cause creative failures).proto but didn’t regen).

In the end of the day, the only issues embedded will face is incorrect imports or issues with nanopb. Software issues ARE NOT YOUR CONCERN!

Protobufs are boring on purpose:purpose. boringBoring schemas prevent exciting debugging sessions. Keep changes small, pinned, reviewed,reviewable, and tested.compatible.