# Robot Format Converter
[](https://pypi.org/project/robot-format-converter/)
[](https://pypi.org/project/robot-format-converter/)
[](https://opensource.org/licenses/Apache-2.0)
A universal robot description format converter that enables seamless conversion between different robot modeling formats including URDF, SDF, MJCF, USD, and a unified schema format.
## Features
- **Multi-Format Support**: Convert between URDF, SDF, MJCF, USD, and custom schema formats
- **Unified Schema**: Common intermediate representation preserving robot structure and properties
- **Command-Line Interface**: Easy-to-use CLI for single file and batch conversions
- **Python API**: Programmatic access for integration into robotics pipelines
- **Format Detection**: Automatic format detection from file extensions and content
- **Validation**: Built-in schema validation and error checking
- **Extensible Architecture**: Easy to add support for new formats
## Supported Formats
| Format | Extension | Read | Write | Description |
|--------|-----------|------|-------|-------------|
| URDF | `.urdf` | ✅ | ✅ | Unified Robot Description Format |
| SDF | `.sdf` | 🚧 | 🚧 | Simulation Description Format |
| MJCF | `.xml` | 🚧 | 🚧 | MuJoCo Modeling Format |
| USD | `.usd`, `.usda` | 🚧 | 🚧 | Universal Scene Description |
| Schema | `.yaml`, `.json` | ✅ | ✅ | Custom unified schema |
*Legend: ✅ Implemented, 🚧 In Development*
## Installation
### From PyPI (Recommended)
```bash
pip install robot-format-converter
```
### From Source
```bash
git clone https://github.com/thanhndv212/robot_format_converter.git
cd robot_format_converter
pip install -e .
```
### Development Installation
```bash
git clone https://github.com/thanhndv212/robot_format_converter.git
cd robot_format_converter
pip install -e .[dev]
```
## Quick Start
### Command Line Interface
**Single File Conversion:**
```bash
# Convert URDF to SDF
robot-convert convert robot.urdf robot.sdf
# Convert with explicit format specification
robot-convert convert --source urdf --target mjcf robot.urdf robot.xml
# Get file information
robot-convert info robot.urdf
```
**Batch Conversion:**
```bash
# Convert all URDF files in a directory to SDF
robot-convert batch-convert models/ output/ urdf sdf
# Convert with file pattern
robot-convert batch-convert models/ output/ urdf sdf --pattern "*.urdf"
```
**Validation:**
```bash
# Validate a schema file
robot-convert validate robot_schema.yaml
# List supported formats
robot-convert list-formats
```
### Python API
**Basic Conversion:**
```python
from robot_format_converter import FormatConverter
# Create converter instance
converter = FormatConverter()
# Convert single file
schema = converter.convert('robot.urdf', 'robot.sdf')
print(f"Converted robot: {schema.metadata.name}")
print(f"Links: {len(schema.links)}, Joints: {len(schema.joints)}")
# Batch convert directory
converted_files = converter.batch_convert(
'input_models/',
'output_models/',
'urdf',
'sdf'
)
print(f"Converted {len(converted_files)} files")
```
**Advanced Usage:**
```python
from robot_format_converter import FormatConverter, CommonSchema
from pathlib import Path
converter = FormatConverter()
# Convert to intermediate schema format
schema = converter.to_schema('robot.urdf', 'robot_schema.yaml')
# Access robot components
for link in schema.links:
print(f"Link: {link.name}")
if link.visual:
print(f" Visual: {link.visual.geometry}")
if link.collision:
print(f" Collision: {link.collision.geometry}")
for joint in schema.joints:
print(f"Joint: {joint.name} ({joint.type})")
print(f" Parent: {joint.parent} -> Child: {joint.child}")
# Convert from schema to target format
converter.from_schema('robot_schema.yaml', 'output.sdf')
```
**Format Detection:**
```python
from robot_format_converter.utils import detect_format, get_format_info
# Detect format from file
format_name = detect_format('robot.urdf')
print(f"Detected format: {format_name}")
# Get format information
info = get_format_info(format_name)
print(f"Format description: {info['description']}")
print(f"Supported features: {info['features']}")
```
## Schema Format
The unified schema format provides a common intermediate representation:
```yaml
metadata:
name: "my_robot"
version: "1.0"
author: "Robot Designer"
description: "A sample robot description"
links:
- name: "base_link"
inertial:
mass: 1.0
center_of_mass: [0, 0, 0]
inertia_matrix: [1, 0, 0, 1, 0, 1]
visual:
geometry:
type: "box"
size: [0.1, 0.1, 0.1]
material:
color: [1, 0, 0, 1]
collision:
geometry:
type: "box"
size: [0.1, 0.1, 0.1]
joints:
- name: "joint1"
type: "revolute"
parent: "base_link"
child: "link1"
origin:
xyz: [0, 0, 0.1]
rpy: [0, 0, 0]
axis: [0, 0, 1]
limits:
lower: -3.14
upper: 3.14
effort: 10
velocity: 1
```
## Architecture
The converter uses a modular architecture with clear separation of concerns:
```
robot_format_converter/
├── __init__.py # Public API
├── core.py # Core conversion engine
├── schema.py # Unified schema definition
├── parsers.py # Format-specific parsers
├── exporters.py # Format-specific exporters
├── utils.py # Utility functions
└── __main__.py # CLI interface
```
**Key Components:**
- **FormatConverter**: Main interface for conversions
- **ConversionEngine**: Orchestrates parsing and exporting
- **CommonSchema**: Unified intermediate representation
- **BaseParser/BaseExporter**: Abstract base classes for format handlers
- **Format-specific parsers/exporters**: Handle individual format details
## Adding New Formats
To add support for a new format:
1. **Create Parser Class:**
```python
from robot_format_converter.core import BaseParser
from robot_format_converter.schema import CommonSchema
class MyFormatParser(BaseParser):
def can_parse(self, file_path: str) -> bool:
return file_path.endswith('.myformat')
def parse(self, file_path: str) -> CommonSchema:
# Implementation here
pass
```
2. **Create Exporter Class:**
```python
from robot_format_converter.core import BaseExporter
from robot_format_converter.schema import CommonSchema
class MyFormatExporter(BaseExporter):
def can_export(self, format_name: str) -> bool:
return format_name == 'myformat'
def export(self, schema: CommonSchema, file_path: str) -> None:
# Implementation here
pass
```
3. **Register with Engine:**
```python
from robot_format_converter import ConversionEngine
engine = ConversionEngine()
engine.register_parser('myformat', MyFormatParser())
engine.register_exporter('myformat', MyFormatExporter())
```
## Contributing
We welcome contributions! Please see our [Contributing Guide](CONTRIBUTING.md) for details.
### Development Setup
```bash
# Clone repository
git clone https://github.com/thanhndv212/robot_format_converter.git
cd robot_format_converter
# Install development dependencies
pip install -e .[dev]
# Install pre-commit hooks
pre-commit install
# Run tests
pytest
# Run linting
flake8 robot_format_converter/
black robot_format_converter/
isort robot_format_converter/
```
### Running Tests
```bash
# Run all tests
pytest
# Run with coverage
pytest --cov=format_converter
# Run specific test
pytest tests/test_urdf_parser.py
```
## Examples
Check out the [examples](examples/) directory for more usage examples:
- [Basic conversion](examples/basic_conversion.py)
- [Batch processing](examples/batch_processing.py)
- [Custom format integration](examples/custom_format.py)
- [Schema validation](examples/schema_validation.py)
## Roadmap
- ✅ URDF parser and exporter
- ✅ Unified schema format
- ✅ Command-line interface
- 🚧 SDF parser and exporter
- 🚧 MJCF parser and exporter
- 🚧 USD parser and exporter
- 📋 ROS2 integration
- 📋 Gazebo integration
- 📋 MuJoCo integration
- 📋 Isaac Sim integration
*Legend: ✅ Complete, 🚧 In Progress, 📋 Planned*
## License
This project is licensed under the Apache License 2.0 - see the [LICENSE](LICENSE) file for details.
## Related Projects
- [FIGAROH](https://github.com/thanhndv212/figaroh): Robot calibration and identification library
- [URDF Parser](https://github.com/ros/urdf_parser_py): ROS URDF parsing library
- [PyBullet](https://pybullet.org/): Physics simulation supporting URDF and SDF
- [MuJoCo](https://mujoco.org/): Physics simulator with MJCF format
## Citation
If you use this package in your research, please cite:
```bibtex
@software{robot_format_converter,
author = {Nguyen, Thanh},
title = {Robot Format Converter: Universal Robot Description Format Converter},
year = {2025},
url = {https://github.com/thanhndv212/robot_format_converter},
version = {1.0.0}
}
```
Raw data
{
"_id": null,
"home_page": null,
"name": "robot-format-converter",
"maintainer": null,
"docs_url": null,
"requires_python": ">=3.8",
"maintainer_email": "Thanh Nguyen <thanh.nguyen@example.com>",
"keywords": "robotics, urdf, sdf, mjcf, robot-description, format-conversion, robot-modeling",
"author": null,
"author_email": "Thanh Nguyen <thanh.nguyen@example.com>",
"download_url": "https://files.pythonhosted.org/packages/6d/21/545d7896261468942b096acab4e0e9450154809f1af90f9cdbd1abdd1c3f/robot_format_converter-1.0.0.tar.gz",
"platform": null,
"description": "# Robot Format Converter\n\n[](https://pypi.org/project/robot-format-converter/)\n[](https://pypi.org/project/robot-format-converter/)\n[](https://opensource.org/licenses/Apache-2.0)\n\nA universal robot description format converter that enables seamless conversion between different robot modeling formats including URDF, SDF, MJCF, USD, and a unified schema format.\n\n## Features\n\n- **Multi-Format Support**: Convert between URDF, SDF, MJCF, USD, and custom schema formats\n- **Unified Schema**: Common intermediate representation preserving robot structure and properties\n- **Command-Line Interface**: Easy-to-use CLI for single file and batch conversions\n- **Python API**: Programmatic access for integration into robotics pipelines\n- **Format Detection**: Automatic format detection from file extensions and content\n- **Validation**: Built-in schema validation and error checking\n- **Extensible Architecture**: Easy to add support for new formats\n\n## Supported Formats\n\n| Format | Extension | Read | Write | Description |\n|--------|-----------|------|-------|-------------|\n| URDF | `.urdf` | \u2705 | \u2705 | Unified Robot Description Format |\n| SDF | `.sdf` | \ud83d\udea7 | \ud83d\udea7 | Simulation Description Format |\n| MJCF | `.xml` | \ud83d\udea7 | \ud83d\udea7 | MuJoCo Modeling Format |\n| USD | `.usd`, `.usda` | \ud83d\udea7 | \ud83d\udea7 | Universal Scene Description |\n| Schema | `.yaml`, `.json` | \u2705 | \u2705 | Custom unified schema |\n\n*Legend: \u2705 Implemented, \ud83d\udea7 In Development*\n\n## Installation\n\n### From PyPI (Recommended)\n\n```bash\npip install robot-format-converter\n```\n\n### From Source\n\n```bash\ngit clone https://github.com/thanhndv212/robot_format_converter.git\ncd robot_format_converter\npip install -e .\n```\n\n### Development Installation\n\n```bash\ngit clone https://github.com/thanhndv212/robot_format_converter.git\ncd robot_format_converter\npip install -e .[dev]\n```\n\n## Quick Start\n\n### Command Line Interface\n\n**Single File Conversion:**\n```bash\n# Convert URDF to SDF\nrobot-convert convert robot.urdf robot.sdf\n\n# Convert with explicit format specification\nrobot-convert convert --source urdf --target mjcf robot.urdf robot.xml\n\n# Get file information\nrobot-convert info robot.urdf\n```\n\n**Batch Conversion:**\n```bash\n# Convert all URDF files in a directory to SDF\nrobot-convert batch-convert models/ output/ urdf sdf\n\n# Convert with file pattern\nrobot-convert batch-convert models/ output/ urdf sdf --pattern \"*.urdf\"\n```\n\n**Validation:**\n```bash\n# Validate a schema file\nrobot-convert validate robot_schema.yaml\n\n# List supported formats\nrobot-convert list-formats\n```\n\n### Python API\n\n**Basic Conversion:**\n```python\nfrom robot_format_converter import FormatConverter\n\n# Create converter instance\nconverter = FormatConverter()\n\n# Convert single file\nschema = converter.convert('robot.urdf', 'robot.sdf')\nprint(f\"Converted robot: {schema.metadata.name}\")\nprint(f\"Links: {len(schema.links)}, Joints: {len(schema.joints)}\")\n\n# Batch convert directory\nconverted_files = converter.batch_convert(\n 'input_models/', \n 'output_models/', \n 'urdf', \n 'sdf'\n)\nprint(f\"Converted {len(converted_files)} files\")\n```\n\n**Advanced Usage:**\n```python\nfrom robot_format_converter import FormatConverter, CommonSchema\nfrom pathlib import Path\n\nconverter = FormatConverter()\n\n# Convert to intermediate schema format\nschema = converter.to_schema('robot.urdf', 'robot_schema.yaml')\n\n# Access robot components\nfor link in schema.links:\n print(f\"Link: {link.name}\")\n if link.visual:\n print(f\" Visual: {link.visual.geometry}\")\n if link.collision:\n print(f\" Collision: {link.collision.geometry}\")\n\nfor joint in schema.joints:\n print(f\"Joint: {joint.name} ({joint.type})\")\n print(f\" Parent: {joint.parent} -> Child: {joint.child}\")\n\n# Convert from schema to target format\nconverter.from_schema('robot_schema.yaml', 'output.sdf')\n```\n\n**Format Detection:**\n```python\nfrom robot_format_converter.utils import detect_format, get_format_info\n\n# Detect format from file\nformat_name = detect_format('robot.urdf')\nprint(f\"Detected format: {format_name}\")\n\n# Get format information\ninfo = get_format_info(format_name)\nprint(f\"Format description: {info['description']}\")\nprint(f\"Supported features: {info['features']}\")\n```\n\n## Schema Format\n\nThe unified schema format provides a common intermediate representation:\n\n```yaml\nmetadata:\n name: \"my_robot\"\n version: \"1.0\"\n author: \"Robot Designer\"\n description: \"A sample robot description\"\n\nlinks:\n - name: \"base_link\"\n inertial:\n mass: 1.0\n center_of_mass: [0, 0, 0]\n inertia_matrix: [1, 0, 0, 1, 0, 1]\n visual:\n geometry:\n type: \"box\"\n size: [0.1, 0.1, 0.1]\n material:\n color: [1, 0, 0, 1]\n collision:\n geometry:\n type: \"box\"\n size: [0.1, 0.1, 0.1]\n\njoints:\n - name: \"joint1\"\n type: \"revolute\"\n parent: \"base_link\"\n child: \"link1\"\n origin:\n xyz: [0, 0, 0.1]\n rpy: [0, 0, 0]\n axis: [0, 0, 1]\n limits:\n lower: -3.14\n upper: 3.14\n effort: 10\n velocity: 1\n```\n\n## Architecture\n\nThe converter uses a modular architecture with clear separation of concerns:\n\n```\nrobot_format_converter/\n\u251c\u2500\u2500 __init__.py # Public API\n\u251c\u2500\u2500 core.py # Core conversion engine\n\u251c\u2500\u2500 schema.py # Unified schema definition\n\u251c\u2500\u2500 parsers.py # Format-specific parsers\n\u251c\u2500\u2500 exporters.py # Format-specific exporters\n\u251c\u2500\u2500 utils.py # Utility functions\n\u2514\u2500\u2500 __main__.py # CLI interface\n```\n\n**Key Components:**\n\n- **FormatConverter**: Main interface for conversions\n- **ConversionEngine**: Orchestrates parsing and exporting\n- **CommonSchema**: Unified intermediate representation\n- **BaseParser/BaseExporter**: Abstract base classes for format handlers\n- **Format-specific parsers/exporters**: Handle individual format details\n\n## Adding New Formats\n\nTo add support for a new format:\n\n1. **Create Parser Class:**\n```python\nfrom robot_format_converter.core import BaseParser\nfrom robot_format_converter.schema import CommonSchema\n\nclass MyFormatParser(BaseParser):\n def can_parse(self, file_path: str) -> bool:\n return file_path.endswith('.myformat')\n \n def parse(self, file_path: str) -> CommonSchema:\n # Implementation here\n pass\n```\n\n2. **Create Exporter Class:**\n```python\nfrom robot_format_converter.core import BaseExporter\nfrom robot_format_converter.schema import CommonSchema\n\nclass MyFormatExporter(BaseExporter):\n def can_export(self, format_name: str) -> bool:\n return format_name == 'myformat'\n \n def export(self, schema: CommonSchema, file_path: str) -> None:\n # Implementation here\n pass\n```\n\n3. **Register with Engine:**\n```python\nfrom robot_format_converter import ConversionEngine\n\nengine = ConversionEngine()\nengine.register_parser('myformat', MyFormatParser())\nengine.register_exporter('myformat', MyFormatExporter())\n```\n\n## Contributing\n\nWe welcome contributions! Please see our [Contributing Guide](CONTRIBUTING.md) for details.\n\n### Development Setup\n\n```bash\n# Clone repository\ngit clone https://github.com/thanhndv212/robot_format_converter.git\ncd robot_format_converter\n\n# Install development dependencies\npip install -e .[dev]\n\n# Install pre-commit hooks\npre-commit install\n\n# Run tests\npytest\n\n# Run linting\nflake8 robot_format_converter/\nblack robot_format_converter/\nisort robot_format_converter/\n```\n\n### Running Tests\n\n```bash\n# Run all tests\npytest\n\n# Run with coverage\npytest --cov=format_converter\n\n# Run specific test\npytest tests/test_urdf_parser.py\n```\n\n## Examples\n\nCheck out the [examples](examples/) directory for more usage examples:\n\n- [Basic conversion](examples/basic_conversion.py)\n- [Batch processing](examples/batch_processing.py)\n- [Custom format integration](examples/custom_format.py)\n- [Schema validation](examples/schema_validation.py)\n\n## Roadmap\n\n- \u2705 URDF parser and exporter\n- \u2705 Unified schema format\n- \u2705 Command-line interface\n- \ud83d\udea7 SDF parser and exporter\n- \ud83d\udea7 MJCF parser and exporter\n- \ud83d\udea7 USD parser and exporter\n- \ud83d\udccb ROS2 integration\n- \ud83d\udccb Gazebo integration\n- \ud83d\udccb MuJoCo integration\n- \ud83d\udccb Isaac Sim integration\n\n*Legend: \u2705 Complete, \ud83d\udea7 In Progress, \ud83d\udccb Planned*\n\n## License\n\nThis project is licensed under the Apache License 2.0 - see the [LICENSE](LICENSE) file for details.\n\n## Related Projects\n\n- [FIGAROH](https://github.com/thanhndv212/figaroh): Robot calibration and identification library\n- [URDF Parser](https://github.com/ros/urdf_parser_py): ROS URDF parsing library\n- [PyBullet](https://pybullet.org/): Physics simulation supporting URDF and SDF\n- [MuJoCo](https://mujoco.org/): Physics simulator with MJCF format\n\n## Citation\n\nIf you use this package in your research, please cite:\n\n```bibtex\n@software{robot_format_converter,\n author = {Nguyen, Thanh},\n title = {Robot Format Converter: Universal Robot Description Format Converter},\n year = {2025},\n url = {https://github.com/thanhndv212/robot_format_converter},\n version = {1.0.0}\n}\n```\n",
"bugtrack_url": null,
"license": "Apache-2.0",
"summary": "Universal robot description format converter",
"version": "1.0.0",
"project_urls": {
"Bug Reports": "https://github.com/thanhndv212/robot_format_converter/issues",
"Documentation": "https://github.com/thanhndv212/robot_format_converter#readme",
"Homepage": "https://github.com/thanhndv212/robot_format_converter",
"Repository": "https://github.com/thanhndv212/robot_format_converter.git"
},
"split_keywords": [
"robotics",
" urdf",
" sdf",
" mjcf",
" robot-description",
" format-conversion",
" robot-modeling"
],
"urls": [
{
"comment_text": null,
"digests": {
"blake2b_256": "3b45795f2cdc532986ee3c7ad87cb399b96ccfcc0dfe55a6d1ba8fff6b095baf",
"md5": "c10f3d83dfb0e061bc9bd33cce3356b4",
"sha256": "176a2a0ce0b9d8b00f9fcc7db71db2e1084b7977b426e4188de7325bc82d6a7b"
},
"downloads": -1,
"filename": "robot_format_converter-1.0.0-py3-none-any.whl",
"has_sig": false,
"md5_digest": "c10f3d83dfb0e061bc9bd33cce3356b4",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": ">=3.8",
"size": 32373,
"upload_time": "2025-09-06T13:56:16",
"upload_time_iso_8601": "2025-09-06T13:56:16.218606Z",
"url": "https://files.pythonhosted.org/packages/3b/45/795f2cdc532986ee3c7ad87cb399b96ccfcc0dfe55a6d1ba8fff6b095baf/robot_format_converter-1.0.0-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": null,
"digests": {
"blake2b_256": "6d21545d7896261468942b096acab4e0e9450154809f1af90f9cdbd1abdd1c3f",
"md5": "3f4b0874a00ad0b8b4daa963c0d1443c",
"sha256": "8373d102a0209caaef7c4f835ee92689d01b64b1e4fb7ea8ba7eddacb60fd624"
},
"downloads": -1,
"filename": "robot_format_converter-1.0.0.tar.gz",
"has_sig": false,
"md5_digest": "3f4b0874a00ad0b8b4daa963c0d1443c",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.8",
"size": 32299,
"upload_time": "2025-09-06T13:56:17",
"upload_time_iso_8601": "2025-09-06T13:56:17.617085Z",
"url": "https://files.pythonhosted.org/packages/6d/21/545d7896261468942b096acab4e0e9450154809f1af90f9cdbd1abdd1c3f/robot_format_converter-1.0.0.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2025-09-06 13:56:17",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "thanhndv212",
"github_project": "robot_format_converter",
"travis_ci": false,
"coveralls": false,
"github_actions": false,
"requirements": [
{
"name": "numpy",
"specs": [
[
">=",
"1.20.0"
]
]
},
{
"name": "lxml",
"specs": [
[
">=",
"4.6.0"
]
]
},
{
"name": "pyyaml",
"specs": [
[
">=",
"5.4.0"
]
]
},
{
"name": "jsonschema",
"specs": [
[
">=",
"3.2.0"
]
]
},
{
"name": "click",
"specs": [
[
">=",
"8.0.0"
]
]
},
{
"name": "pytest",
"specs": [
[
">=",
"6.0"
]
]
},
{
"name": "pytest-cov",
"specs": [
[
">=",
"2.10.0"
]
]
},
{
"name": "black",
"specs": [
[
">=",
"21.0.0"
]
]
},
{
"name": "isort",
"specs": [
[
">=",
"5.0.0"
]
]
},
{
"name": "flake8",
"specs": [
[
">=",
"3.8.0"
]
]
},
{
"name": "mypy",
"specs": [
[
">=",
"0.800"
]
]
},
{
"name": "pre-commit",
"specs": [
[
">=",
"2.10.0"
]
]
},
{
"name": "sphinx",
"specs": [
[
">=",
"4.0.0"
]
]
},
{
"name": "sphinx-rtd-theme",
"specs": [
[
">=",
"0.5.0"
]
]
},
{
"name": "sphinx-autodoc-typehints",
"specs": [
[
">=",
"1.11.0"
]
]
},
{
"name": "setuptools",
"specs": [
[
">=",
"45"
]
]
},
{
"name": "wheel",
"specs": []
},
{
"name": "setuptools_scm",
"specs": [
[
">=",
"6.2"
]
]
},
{
"name": "build",
"specs": []
},
{
"name": "twine",
"specs": []
}
],
"lcname": "robot-format-converter"
}