Getting Started

Installation

pip install urdfgenpy

Or from source:

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

Minimal Example

Build a single revolute joint between two links and export to URDF. The snippet below produces the same structure as the PTU - 2-DOF example:

simple_arm turntable

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

charcoal = Material("charcoal", rgba=(0.22, 0.22, 0.25, 1.0))
amber    = Material("amber",    rgba=(1.0,  0.55, 0.0,  1.0))

# base plate
plate = Box(length=0.14, width=0.14, height=0.025)
base_plate = Link("base_plate")
base_plate.add_visual(Visual(geometry=plate, origin=Origin.above(plate), material=charcoal))
base_plate.set_inertial(Inertial.from_geometry(mass=0.8, geometry=plate))

# pan neck
neck = Cylinder(radius=0.028, length=0.07)
pan_link = Link("pan_link")
pan_link.add_visual(Visual(geometry=neck, origin=Origin.above(neck), material=charcoal))
pan_link.set_inertial(Inertial.from_geometry(mass=0.18, geometry=neck))

# sensor head
head = Box(length=0.09, width=0.05, height=0.05)
tilt_link = Link("tilt_link")
tilt_link.add_visual(Visual(geometry=head, origin=Origin(xyz=(0.045, 0, 0)), material=amber))
tilt_link.set_inertial(Inertial.from_geometry(mass=0.12, geometry=head))

robot = Robot("ptu")
robot.add_material(charcoal).add_material(amber)
robot.add_link(base_plate).add_link(pan_link).add_link(tilt_link)
robot.add_joint(Joint("pan_joint",  "revolute", "base_plate", "pan_link",
                        origin=Origin(xyz=(0, 0, 0.025)), axis=(0, 0, 1),
                        limit=JointLimit(-3.14, 3.14, effort=10, velocity=1.5)))
robot.add_joint(Joint("tilt_joint", "revolute", "pan_link",   "tilt_link",
                        origin=Origin(xyz=(0, 0, 0.07)),   axis=(0, 1, 0),
                        limit=JointLimit(-0.52, 1.57, effort=6,  velocity=1.5)))
robot.save("ptu.urdf")
robot.print_tree()

Geometry Helpers

Origin.above(geometry)

Lifts a geometry so its bottom face sits at z = 0:

box    = Box(0.2, 0.2, 0.1)  # length(x), width(y), height(z)
origin = Origin.above(box)   # xyz = (0, 0, 0.05)

cyl    = Cylinder(0.05, 0.3) # radius, length
origin = Origin.above(cyl)   # xyz = (0, 0, 0.15)

sphere = Sphere(0.1)           # radius
origin = Origin.above(sphere)  # xyz = (0, 0, 0.05)

Origin.wheel()

Returns an origin with −pi/2 roll so a URDF cylinder acts as a wheel (cylinder Z-axis -> wheel rotation axis ->Y):

wheel_origin = Origin.wheel(xy=(-0.15, 0.0), z=0.05)

Automatic Inertia

# From a specific shape
inertial = Inertial.from_box(mass=1.0, length=0.2, w=0.2, h=0.1)
inertial = Inertial.from_cylinder(mass=0.5, radius=0.05, length=0.2)
inertial = Inertial.from_sphere(mass=0.1, radius=0.03)

# Auto-dispatch from any geometry object
box     = Box(0.2, 0.2, 0.1)
inertial = Inertial.from_geometry(mass=1.0, geometry=box)

Kinematic Tree Visualisation

robot.print_tree()    # coloured ASCII to stdout
text = robot.tree_string()   # plain-text version
robot.save_tree("tree.txt")  # write to file

Exporting

# To string
urdf_xml  = robot.to_urdf()
xacro_xml = robot.to_xacro()

# Directly to file
robot.to_urdf("output.urdf")
robot.to_xacro("output.xacro")

# Auto-detect from extension
robot.save("output.urdf")   # writes URDF
robot.save("output.xacro")  # writes Xacro

What’s Next?

  • API Reference - full documentation for every public class and method, including Robot, Link, Joint, geometry primitives, and exporters.

  • Development Guide - set up a local environment, run tests, and open a pull request.

  • Roadmap - planned features: DH-parameter import, URDF round-trip parsing, SDF export, sensor elements, and more.