Skip to content

URDF import: generate a BB DSL module from a URDF file #101

@jimsynz

Description

@jimsynz

Problem

bb already exports BB robot definitions to URDF (BB.Urdf.Exporter / mix bb.to_urdf) for use with ROS tools like RViz and Gazebo. The reverse — taking an existing URDF file and producing an equivalent BB DSL module — would be a much bigger lever for adoption. Most off-the-shelf robot arms (Universal Robots, Franka, WidowX, SO-101, etc.) ship URDFs from the manufacturer or community, and porting them to BB by hand is tedious and error-prone.

Proposal

Add a mix bb.from_urdf Igniter task that reads a URDF XML file and writes a defmodule MyRobot do ... use BB ... end module to lib/.

# Generate lib/my_app/robot.ex from a URDF
mix bb.from_urdf path/to/robot.urdf --module MyApp.Robot

# With explicit output path
mix bb.from_urdf path/to/robot.urdf --module MyApp.Robot --output lib/my_app/robot.ex

The generator should:

  • Walk the URDF <link> and <joint> graph and emit nested link/joint blocks in topology order.
  • Convert URDF values (which are SI base units already — metres, radians, kg) into ~u(...) sigil literals for clarity.
  • Emit visual/collision/inertial/origin/axis/limit/dynamics blocks, mapping URDF's <box>/<cylinder>/<sphere>/<mesh> geometries to bb's box/cylinder/sphere/mesh DSL entities.
  • Set the robot's name setting from the URDF <robot name="..."> attribute.
  • Default any optional fields bb expects but URDF doesn't provide.

Runtime parsing (loading URDF into a BB.Robot struct on the fly without code generation) is explicitly not in scope — bb is built around compile-time DSL processing, and generating source code keeps the resulting robot first-class with everything else (Spark transformers, supervision tree, etc.).

Things URDF has that BB doesn't (or treats differently)

These need either a translation, a warning-and-skip, or a documented limitation:

URDF feature Notes
<joint type="floating">/"planar" bb has both, should map directly
<joint type="fixed"> bb has fixed, direct map
<mimic> URDF allows a joint to mirror another; bb has no equivalent. Warn and skip, point to the proposals repo.
<safety_controller> URDF position/velocity safety limits; could map to bb's limit block but the semantics differ. Probably skip with a notice.
<transmission> Maps a joint to an actuator with a transmission ratio. bb doesn't model transmissions explicitly; skip with a notice that the user will need to define the actuator manually.
<gazebo> extensions Simulator-specific. Skip.
<material> definitions outside <visual> URDF allows top-level material defs that visuals reference by name. Resolve them at parse time and inline into each visual's material block.
<mesh filename="..."> URDF mesh paths use package:// URIs from ROS. The importer can either copy the mesh files into the project's priv/ and rewrite paths, or emit the path as-is with a notice. Probably the latter as v1 — file management is a separate concern.

Implementation notes

  • Parse XML with :xmerl_scan from stdlib (no extra dep needed) or SweetXml if we want better ergonomics.
  • The generator should use Sourceror to emit formatted Elixir source, not string templating.
  • Handle the topology by building an in-memory link→joint→link adjacency map first, then emitting nested blocks starting from the root link (the one that's never a child of any joint).
  • Unit handling: URDF values are floats in SI base. Emit them via ~u(<n> meter) / ~u(<n> radian) etc. The choice of unit literal is purely cosmetic — bb's DSL accepts any compatible unit and converts to SI internally anyway, but ~u(0.1 meter) reads better in source than the equivalent float.

Open questions

  • mesh resolution. Do we copy mesh files into the project (and rewrite filename to a relative path), leave them where they are (referenced via absolute path), or just emit a comment and require the user to handle them? Leaning toward the comment-and-require-manual-step for v1.
  • Round-trip fidelity. Should mix bb.from_urdf foo.urdf then mix bb.to_urdf MyRobot produce a URDF equivalent to the input? Probably approximately yes, but lossless round-trip is hard because bb normalises some things (e.g. axis orientations) at compile time.
  • Validation. Should the importer reject URDFs that contain features bb doesn't support, or always emit something and warn? Probably the latter — fail-soft for adoption.
  • The example robots. Could we use this importer to regenerate bb_example_wx200's robot definition from a vendor URDF, as a smoke test and demo of the workflow?

Related

  • Existing exporter: lib/bb/urdf/exporter.ex, BB.Urdf.Xml helpers
  • DSL reference: documentation/dsls/DSL-BB.md
  • Tutorial: documentation/tutorials/06-urdf-export.md — the export tutorial; an 07-urdf-import.md would be a natural pair

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions