Skip to main content

Programmatically generate URDF and Xacro robot description files

Project description

urdfgenpy

A Python library for programmatically generating URDF (Unified Robot Description Format) and Xacro robot description files.

Features

  • Build robot kinematic trees with links, joints, and materials using a clean Python API
  • Geometry primitives: Box, Cylinder, Sphere
  • Automatic inertia calculation from geometry and mass
  • Convenience helpers: Origin.above() (lift geometry to sit on a plane), Origin.wheel() (orient cylinder as a wheel)
  • Export to .urdf or .xacro - format is inferred from the file extension
  • ASCII kinematic tree visualisation with robot.print_tree() / robot.tree_string()

Installation

pip3 install urdfgenpy

Or from source:

git clone https://github.com/svaibhav101/urdfgenpy
cd urdfgenpy
pip3 install -e ".[dev,docs]"

Quick Start

from urdfgenpy import (
    Robot, Link, Joint, JointLimit, JointDynamics,
    Box, Cylinder, Sphere,
    Origin, Material, Visual, Collision, Inertial,
)

# --- Materials ---
grey = Material("grey", rgba=(0.5, 0.5, 0.5, 1.0))
blue = Material("blue", rgba=(0.0, 0.3, 0.8, 1.0))

# --- Base link: flat box ---
base_box = Box(length=0.2, width=0.2, height=0.05)
base_link = Link("base_link")
base_link.add_visual(Visual(geometry=base_box, origin=Origin.above(base_box), material=grey))
base_link.add_collision(Collision(geometry=base_box, origin=Origin.above(base_box)))
base_link.set_inertial(Inertial.from_geometry(mass=1.0, geometry=base_box))

# --- Shoulder link: upright cylinder ---
shoulder_cyl = Cylinder(radius=0.04, length=0.15)
shoulder_link = Link("shoulder_link")
shoulder_link.add_visual(Visual(geometry=shoulder_cyl, origin=Origin.above(shoulder_cyl), material=blue))
shoulder_link.add_collision(Collision(geometry=shoulder_cyl, origin=Origin.above(shoulder_cyl)))
shoulder_link.set_inertial(Inertial.from_geometry(mass=0.5, geometry=shoulder_cyl))

# --- Joint ---
joint = Joint(
    name="base_shoulder_joint",
    joint_type="revolute",
    parent="base_link",
    child="shoulder_link",
    origin=Origin(xyz=(0.0, 0.0, 0.05)),
    axis=(0.0, 0.0, 1.0),
    limit=JointLimit(lower=-3.14, upper=3.14, effort=50.0, velocity=2.0),
    dynamics=JointDynamics(damping=0.5, friction=0.01),
)

# --- Assemble and export ---
robot = Robot("my_robot")
robot.add_material(grey).add_material(blue)
robot.add_link(base_link).add_link(shoulder_link)
robot.add_joint(joint)

robot.save("my_robot.urdf")   # or .xacro
robot.print_tree()

API Reference

Robot

Method Description
add_link(link) Add a Link; returns self for chaining
add_joint(joint) Add a Joint; validates parent/child exist
add_material(material) Register a global Material
to_urdf(output_path=None) Return URDF XML string; optionally write file
to_xacro(output_path=None) Return Xacro XML string; optionally write file
save(output_path) Write .urdf or .xacro based on extension
tree_string() Plain-text ASCII kinematic tree
save_tree(output_path) Write tree_string() to file
print_tree() Print coloured ASCII tree to stdout

Geometry

Class Parameters
Box(length, width, height) Axis-aligned box
Cylinder(radius, length) Cylinder along Z-axis
Sphere(radius) Sphere

Origin

Origin(xyz=(0,0,0), rpy=(0,0,0))           # explicit
Origin.above(geometry, xy=(0,0), rpy=...)  # lift so bottom sits at z=0
Origin.wheel(xy=(0,0), z=0)                # -pi/2 roll, cylinder becomes wheel

Inertial

Inertial.from_geometry(mass, geometry)               # auto-compute from Box/Cylinder/Sphere
Inertial.from_box(mass, length, w, h)
Inertial.from_cylinder(mass, radius, length)
Inertial.from_sphere(mass, radius)
Inertial(mass, matrix=InertiaMatrix(...))            # manual

Joint

Joint(
    name, joint_type,          # "fixed" | "revolute" | "continuous" | "prismatic" | ...
    parent, child,             # link names
    origin=Origin(),
    axis=(1, 0, 0),
    limit=JointLimit(lower, upper, effort, velocity),    # optional
    dynamics=JointDynamics(damping, friction),           # optional
    mimic=JointMimic(joint, multiplier, offset),         # optional
)

Examples

Install the package first, then run any example directly:

pip3 install -e ".[dev]"
python examples/simple_arm.py   # 4-DOF serial arm
python examples/hobu.py         # multi-link mobile base with wheels
python examples/base.py         # minimal single-link robot

Each script writes its output files (.urdf, .xacro, _tree.txt) into a subdirectory named after the robot.

Running Tests

pip3 install -e ".[dev]"
pytest

Run with coverage:

pytest --cov=urdfgenpy --cov-report=term-missing

Building Documentation

pip3 install -e ".[docs]"
cd docs
make html
# open docs/_build/html/index.html

Project Structure

urdfgenpy/
├── src/urdfgenpy/        # library source
│   ├── robot.py          # Robot class
│   ├── link.py           # Link class
│   ├── joint.py          # Joint, JointLimit, JointDynamics, JointMimic
│   ├── geometry.py       # Box, Cylinder, Sphere
│   ├── inertia.py        # InertiaMatrix and inertia helpers
│   ├── elements.py       # Origin, Material, Visual, Collision, Inertial
│   └── exporters/        # URDFExporter, XacroExporter
├── tests/                # pytest test suite (77 tests)
├── docs/                 # Sphinx documentation source
├── examples/             # standalone usage examples
│   ├── simple_arm.py     # 4-DOF serial arm
│   ├── hobu.py           # multi-link mobile base with wheels
│   └── base.py           # minimal single-link example
└── pyproject.toml        # project metadata and tool config

Roadmap

See docs/source/roadmap.md for the full list. Top items:

Priority Feature
High DH parameters -> skeleton URDF/Xacro - generate kinematic chain from a DH table
High URDF parser - round-trip import of existing .urdf files
High Model validation - positive-definite inertia check, joint-limit sanity
Medium SDF export - Gazebo Simulation Description Format
Medium Mesh-based inertia - auto-compute from .stl/.obj + density
Medium Sensor elements - <camera>, <lidar>, <imu> tags
Low ROS 2 scaffolding - generate package.xml + CMakeLists.txt
Low Visualiser - quick matplotlib / rerun 3-D preview

License

urdfgenpy is made available under the MIT License. For more details, see LICENSE

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

urdfgenpy-0.3.0.tar.gz (21.7 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

urdfgenpy-0.3.0-py3-none-any.whl (18.0 kB view details)

Uploaded Python 3

File details

Details for the file urdfgenpy-0.3.0.tar.gz.

File metadata

  • Download URL: urdfgenpy-0.3.0.tar.gz
  • Upload date:
  • Size: 21.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.10.12

File hashes

Hashes for urdfgenpy-0.3.0.tar.gz
Algorithm Hash digest
SHA256 96b479e037ec0aafcfcbdf0a1dab5cdf2d8ba3ab1c9631f5590191b4ce95a25b
MD5 17197c836801b8d2abf13cf0eaf743a3
BLAKE2b-256 e9cb25dfbbbf3b550bfb4bb7cd6efed224acbce2e599e7c725f6a5cf75c92e8c

See more details on using hashes here.

File details

Details for the file urdfgenpy-0.3.0-py3-none-any.whl.

File metadata

  • Download URL: urdfgenpy-0.3.0-py3-none-any.whl
  • Upload date:
  • Size: 18.0 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.10.12

File hashes

Hashes for urdfgenpy-0.3.0-py3-none-any.whl
Algorithm Hash digest
SHA256 b380b7b7cea835235a536c1bb083a20212ccb21e29f321be6adaf9b2d9d7d373
MD5 8a81fb3fab0857ac7f160fc9f79f9b35
BLAKE2b-256 84e20aed1bde386c8f308c586ec356b051d97d995185652a4010594dea0d7269

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page