Skip to main content

Python SDK for RoboInfra URDF validation, kinematic analysis, semantic diff, SDF/MJCF conversion, MoveIt config generation, 3D model conversion and mesh analysis APIs for ROS developers

Project description

roboinfra-sdk

Python SDK for RoboInfra Robotics API for URDF validation, kinematic analysis, 3D model conversion and mesh quality analysis.

PyPI version Python 3.8+

API: https://roboinfra-api.azurewebsites.net
Dashboard: https://roboinfra-dashboard.azurewebsites.net
PyPI: https://pypi.org/project/roboinfra-sdk/
GitHub Action: uses: roboinfra/validate-urdf-action@v1


Installation

pip install roboinfra-sdk

Quick Start

import roboinfra as roboinfra

# Create client with your API key from the dashboard
client = roboinfra.Client("rk_your_api_key_here")

# 1. Check API health (no auth needed)
status = client.health()
print(status["status"])          # "Healthy"

# 2. Validate a URDF file (Free plan)
result = client.urdf.validate("robot.urdf")
if result.is_valid:
    print("URDF is valid!")
else:
    for error in result.errors:
        print(f"  Error: {error}")

# 3. Kinematic analysis (Basic + Pro plan)
analysis = client.urdf.analyze("robot.urdf")
print(f"DOF: {analysis.dof}")
print(f"End effectors: {analysis.end_effectors}")

# 4. Convert 3D model (Pro plan)
output = client.model.convert("robot.obj", "fbx", "robot.fbx")
print(f"Saved: {output}")

# 5. Mesh quality analysis (Pro plan)
mesh = client.model.analyze("robot.stl")
print(f"Triangles: {mesh.total_triangles}, Watertight: {mesh.is_watertight}")

# 6. URDF → SDF/MJCF conversion (Pro plan)
sdf = client.urdf.convert_format("robot.urdf", "sdf")
with open("robot.sdf", "w") as f:
    f.write(sdf.converted_xml)
print(f"Converted to SDF: {sdf.link_count} links, {sdf.joint_count} joints")

mjcf = client.urdf.convert_format("robot.urdf", "mjcf")
with open("robot.xml", "w") as f:
    f.write(mjcf.converted_xml)
print(f"Converted to MJCF: {mjcf.link_count} links, {mjcf.joint_count} joints")

# 7. MoveIt config generation (Pro plan)
cfg = client.urdf.moveit_config("robot.urdf")
with open("config/kinematics.yaml", "w") as f:
    f.write(cfg.kinematics_yaml)
with open(f"config/{cfg.robot_name}.srdf", "w") as f:
    f.write(cfg.srdf)
print(f"MoveIt: {len(cfg.planning_groups)} groups, "
      f"{cfg.movable_joint_count} movable joints")

Get an API Key

  1. Register at roboinfra-dashboard.azurewebsites.net
  2. Go to API Keys → Create key
  3. Keys start with rk_
  4. Free plan: 50 calls/month for URDF validation no credit card required

API Reference

client.health() Public, no key needed

Check API connectivity and service status.

result = client.health()
# Returns dict:
# {
#   "status": "Healthy",
#   "version": "1.0.0",
#   "uptime": "2d 4h 12m"
# }

client.urdf.validate(file_path) All plans (Free/Basic/Pro)

Validates a URDF file against 9 structural checks.

result = client.urdf.validate("robot.urdf")

result.is_valid   # bool   True if all 9 checks pass
result.errors     # list   empty when valid, list of strings when invalid

9 checks performed:

  1. Root element must be <robot>
  2. At least one <link> must exist
  3. No duplicate link names
  4. No duplicate joint names
  5. All joint parent links must reference a defined link
  6. All joint child links must reference a defined link
  7. Joint type must be valid (revolute, continuous, prismatic, fixed, floating, planar)
  8. revolute and prismatic joints must include <limit>
  9. Exactly one root link (no cycles, no orphans)

Valid URDF example:

result = client.urdf.validate("robot.urdf")
# result.is_valid → True
# result.errors   → []

Invalid URDF example:

result = client.urdf.validate("bad_robot.urdf")
# result.is_valid → False
# result.errors   → [
#     "Root element must be <robot>",
#     "At least one <link> must exist"
# ]

client.urdf.analyze(file_path) Basic + Pro plan

Kinematic analysis DOF, joint chain, end effectors.

result = client.urdf.analyze("robot.urdf")

result.robot_name      # str    name from <robot name="...">
result.link_count      # int    total links
result.joint_count     # int    total joints
result.dof             # int    degrees of freedom (non-fixed joints)
result.max_chain_depth # int    longest kinematic chain
result.root_link       # str    root link name
result.end_effectors   # list   end effector link names
result.joints          # list   joint details

Example:

result = client.urdf.analyze("robot.urdf")
# result.robot_name      → "sample_arm"
# result.dof             → 2
# result.end_effectors   → ["tool0"]
# result.joints[0]       → {"name": "joint_1", "type": "revolute",
#                            "parent": "base_link", "child": "link_1"}


client.urdf.convert_format(file_path, target_format) Pro plan

Convert URDF to Gazebo SDF or MuJoCo MJCF format.

# Convert to Gazebo SDF
sdf = client.urdf.convert_format("robot.urdf", "sdf")
with open("robot.sdf", "w") as f:
    f.write(sdf.converted_xml)

# Convert to MuJoCo MJCF
mjcf = client.urdf.convert_format("robot.urdf", "mjcf")
with open("robot.xml", "w") as f:
    f.write(mjcf.converted_xml)

# Check warnings (e.g. mesh file references)
for w in mjcf.warnings:
    print(f"  Warning: {w}")

sdf.target_format    # str  — "sdf" or "mjcf"
sdf.robot_name       # str  — robot name from URDF
sdf.converted_xml    # str  — the output XML
sdf.link_count       # int
sdf.joint_count      # int
sdf.warnings         # list — non-fatal notes

Supported formats: "sdf" (Gazebo Sim v1.7) and "mjcf" (MuJoCo / Google DeepMind).

What gets converted: all 6 joint types, inertia tensors, visual + collision geometry, materials, mesh references, joint limits/damping/friction, origin transforms. MJCF includes auto-generated actuators.

client.urdf.moveit_config(file_path) Pro plan

Generate MoveIt configuration starter files from a URDF — kinematics.yaml, joint_limits.yaml, an SRDF stub, and planning group suggestions. A faster starting point than the MoveIt Setup Assistant GUI (seconds instead of hours).

cfg = client.urdf.moveit_config("robot.urdf")

# Save the generated files into a moveit_config package
with open("config/kinematics.yaml", "w") as f:
    f.write(cfg.kinematics_yaml)
with open("config/joint_limits.yaml", "w") as f:
    f.write(cfg.joint_limits_yaml)
with open(f"config/{cfg.robot_name}.srdf", "w") as f:
    f.write(cfg.srdf)

# Inspect detected planning groups
for g in cfg.planning_groups:
    print(f"{g['name']}: {len(g['joints'])} joints "
          f"({g.get('baseLink','')} -> {g.get('tipLink','')})")

cfg.robot_name           # str
cfg.kinematics_yaml      # str  — config/kinematics.yaml (KDL solver)
cfg.joint_limits_yaml    # str  — config/joint_limits.yaml
cfg.srdf                 # str  — config/<robot>.srdf
cfg.planning_groups      # list — [{name, joints, baseLink, tipLink, reason}]
cfg.movable_joint_count  # int
cfg.base_link            # str
cfg.tip_link             # str
cfg.warnings             # list

What it generates: KDL kinematics config per planning group, velocity limits read from the URDF (with sensible acceleration defaults), an SRDF stub with planning groups / virtual joint / home state / adjacent-link disable_collisions, and auto-detected planning groups (arm chain + gripper separated by joint name).

This is a starter, not a full replacement for the MoveIt Setup Assistant. Review the SRDF collision rules and tune acceleration limits for your hardware before real execution.

client.model.convert(file_path, target_format, output_path) Pro plan

Convert 3D model files between formats. No Blender required.

output = client.model.convert("robot.stl", "obj", "robot.obj")
# Returns absolute path to saved output file

# All supported conversions:
# .fbx  → obj, stl, glb, gltf
# .obj  → stl, glb, gltf, fbx
# .stl  → obj, glb, gltf
# .gltf → obj, stl, glb
# .glb  → obj, stl, gltf
# .dae  → obj, stl, glb
# .3ds  → obj, stl, glb
# .blend→ obj, stl, glb

Examples:

client.model.convert("robot.stl", "obj",  "robot.obj")
client.model.convert("robot.obj", "fbx",  "robot.fbx")
client.model.convert("robot.fbx", "glb",  "robot.glb")
client.model.convert("robot.obj", "gltf", "robot.gltf")

client.model.analyze(file_path) Pro plan

Mesh quality analysis for physics simulation readiness.

result = client.model.analyze("robot.stl")

result.mesh_count       # int    number of mesh objects
result.total_vertices   # int    total vertex count
result.total_triangles  # int    triangle count after triangulation
result.material_count   # int    number of materials
result.has_bones        # bool   True if skeletal data detected
result.is_watertight    # bool   True if ALL meshes are watertight (required for physics)
result.bounding_box     # dict   {"x": 0.42, "y": 0.38, "z": 0.75}
result.center_of_mass   # dict   {"x": 0.0, "y": 0.0, "z": 0.21}
result.meshes           # list   per-mesh breakdown

Example:

result = client.model.analyze("robot_arm.stl")
# result.total_triangles → 30240
# result.is_watertight   → True
# result.bounding_box    → {"x": 0.42, "y": 0.38, "z": 0.75}

if not result.is_watertight:
    print("WARNING: mesh has holes  robot will fall through ground in Gazebo!")

Error Handling

from roboinfra import (
    RoboInfraError,   # base  any API error
    AuthError,        # 401  invalid API key
    PlanError,        # 403  endpoint requires higher plan
    QuotaError,       # 429  monthly quota exceeded
)

try:
    result = client.urdf.validate("robot.urdf")
except AuthError:
    print("Invalid API key  get one at roboinfra-dashboard.azurewebsites.net/keys")
except PlanError:
    print("Upgrade your plan at roboinfra-dashboard.azurewebsites.net/subscription")
except QuotaError:
    print("Monthly quota exceeded  upgrade or wait until next month")
except RoboInfraError as e:
    print(f"API error: {e} (HTTP {e.status_code})")

Note: 400 errors (bad file, oversized file) also count against your monthly quota. The SDK validates file size and extension locally before any HTTP call to avoid wasting quota on obvious errors.


Plans and Limits

Plan Price Quota Features
Free $0/month 50 calls URDF validation only
Basic $25/month 500 calls URDF validation + kinematic analysis
Pro $75/month 5,000 calls All features (3D conversion + mesh analysis)

File Limits

Endpoint Max file size Allowed extensions
urdf.validate 1 MB .urdf
urdf.analyze 1 MB .urdf
model.convert 20 MB .fbx .obj .stl .gltf .glb .dae .3ds .blend
model.analyze 20 MB .fbx .obj .stl .gltf .glb .dae .3ds .blend

The SDK validates file size and extension locally before any HTTP call no wasted quota on obvious errors.


CI/CD Integration

Option 1 GitHub Action (simplest, recommended)

No Python required. Just add 3 lines to your workflow:

# .github/workflows/validate-urdf.yml
name: Validate URDF
on: [push, pull_request]

jobs:
  validate:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: roboinfra/validate-urdf-action@v1
        with:
          api-key: ${{ secrets.ROBOINFRA_API_KEY }}
          file: urdf/robot.urdf

Full docs: github.com/roboinfra/validate-urdf-action


Option 2 SDK inside a run step (more control)

Use this approach when you need custom logic multiple files, conditional checks, or integration with other tools:

- name: Validate URDF
  run: |
    pip install roboinfra-sdk
    python - <<'EOF'
    import roboinfra as roboinfra
    import sys
    client = roboinfra.Client("${{ secrets.ROBOINFRA_API_KEY }}")
    result = client.urdf.validate("urdf/robot.urdf")
    if not result.is_valid:
        print("URDF validation failed:")
        for e in result.errors:
            print(f"  - {e}")
        sys.exit(1)
    print("URDF valid!")
    EOF

License

MIT

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

roboinfra_sdk-1.0.12.tar.gz (22.9 kB view details)

Uploaded Source

Built Distribution

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

roboinfra_sdk-1.0.12-py3-none-any.whl (17.1 kB view details)

Uploaded Python 3

File details

Details for the file roboinfra_sdk-1.0.12.tar.gz.

File metadata

  • Download URL: roboinfra_sdk-1.0.12.tar.gz
  • Upload date:
  • Size: 22.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.3

File hashes

Hashes for roboinfra_sdk-1.0.12.tar.gz
Algorithm Hash digest
SHA256 d69d41a0e19e4bfa53a125572d7878f1607449a55ad8926e2977a7927c62e9bd
MD5 1522b76c6c5a443f5f8cdb3743a8caa6
BLAKE2b-256 954c103c29680cae7d399f609e9e3a1b71324dd423f8e573f219993916a37e3f

See more details on using hashes here.

File details

Details for the file roboinfra_sdk-1.0.12-py3-none-any.whl.

File metadata

  • Download URL: roboinfra_sdk-1.0.12-py3-none-any.whl
  • Upload date:
  • Size: 17.1 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.3

File hashes

Hashes for roboinfra_sdk-1.0.12-py3-none-any.whl
Algorithm Hash digest
SHA256 82eed696468909dbc3440450e35ac44134b18cbb72a3ec851d24da931a251659
MD5 4c199bba127136f7635b413c82e12863
BLAKE2b-256 4860fe011349088c0872feffd7ddd10ee3e800f6249e457e607421ab6910c7ff

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