A Python-based tool for converting SDFormat (SDF) simulation worlds and models into native Godot 4 projects. This converter preserves hierarchy, physics properties, joints, and visual fidelity using Godot's modern 3D nodes.
- Recursive Resolution: Automatically resolves and downloads nested
<include>tags from:- Local file paths
- HTTP/HTTPS URLs
- Gazebo Fuel repositories (
fuel://...)
- Direct Godot 4 Generation: Writes native
.tscnscene files directly, creating a ready-to-use Godot project structure. - Physics Engine Mapping:
RigidBody3D&StaticBody3Dwith correct mass and inertia tensors.- Surface properties: Friction and bounce mapped to
PhysicsMaterial. - Collision shapes: Box, Sphere, Cylinder, Plane, and Mesh colliders.
- Advanced Joint Support:
revolute,continuous,ball,universal,fixed→Generic6DOFJoint3D(precisely configured limits/locks).prismatic→SliderJoint3D.HingeJoint3Dsupport available for specific configurations.
- Visuals & Materials:
- Full PBR material support (Albedo, Normal, Metallic, Roughness, Emission, Ambient Occlusion).
- Texture handling: Downloads and organizes textures into a project-relative
textures/directory.
- Sensors:
- Camera: Generates
Camera3Dwith configurable FOV, clip planes, and resolution metadata. - Lidar: Parsed into
Node3Dstructures containing scan configuration (samples, resolution, range, noise) in metadata.
- Camera: Generates
- Mesh Import:
- Supports
.dae,.obj,.gltf,.glb, and.stl. - Uses
pyassimp(preferred) orassimpCLI for conversion to glTF. - Falls back to Godot's importer for standard formats.
- Supports
- Godot 4 Executable: Required for baking imported meshes into Godot-compatible resources.
- Assimp: Recommended for mesh conversion (install via
sudo apt install assimp-utilsor equivalent).
Core dependencies:
pip install requestsOptional but recommended (for improved mesh/SDF handling):
pip install pyassimp sdformat16(Note: scipy and numpy are NOT required for this version as all math is handled internally via standard library).
Run the converter as a Python module from the repository root:
python3 -m sdf2godot <INPUT_SDF> <OUTPUT_DIR> --godot <PATH_TO_GODOT>INPUT_SDF: Path to the source.sdf,.world, or.urdffile.OUTPUT_DIR: Directory where the Godot project will be created.--godot: (Required) Path to the Godot 4 executable (e.g.,/usr/bin/godotorC:\Godot\godot.exe).
# Linux
python3 -m sdf2godot ./worlds/tugbot_depot.sdf ./godot_project --godot /usr/bin/godot4
# Windows
python3 -m sdf2godot ./worlds/robot.sdf ./godot_project --godot "C:\Program Files\Godot\godot.exe"The tool generates a complete Godot project folder:
output_dir/
├── project.godot # Godot project configuration
├── scenes/ # Generated .tscn files
│ ├── main_world.tscn # The converted world scene
│ ├── sub_model_1.tscn # Scenes created from <include> tags
│ └── ...
├── materials/ # Generated materials and textures
│ └── textures/
├── meshes/ # Imported mesh files (.glb, .dae, etc.)
└── cache/ # Downloaded assets (Fuel/HTTP)
| SDF Tag | Godot Node | Implementation Details |
|---|---|---|
<world> |
Node3D |
Root node of the main scene. |
<model> |
Node3D |
Container for links and joints. Stores sdf_static metadata. |
<include> |
Node3D |
Resolves the external reference. If possible, instantiates the included scene (instance_path). |
<plugin> |
Node3D |
Placeholder node. Stores plugin filename and parameters in metadata for custom script implementation. |
| SDF Tag | Godot Node | Implementation Details |
|---|---|---|
<link> (static) |
StaticBody3D |
Used when <static>true</static> is set on link or model. |
<link> (dynamic) |
RigidBody3D |
Default for links. Sets mass and inertia from <inertial>. |
<inertial> |
Properties | Sets mass. Inertia tensor (ixx, iyy, etc.) stored in metadata/properties. |
<collision> |
CollisionShape3D |
Child of the body. Shape defined by <geometry>. |
<surface> |
PhysicsMaterial |
Friction (mu) and Bounce (restitution_coefficient) mapped to a .tres resource. |
| SDF Joint Type | Godot Joint | Implementation Details |
|---|---|---|
revolute |
Generic6DOFJoint3D |
Primary mapping. Angular X limit enabled/configured. Motor support via angular_motor_x. |
continuous |
Generic6DOFJoint3D |
Same as revolute but with no angular limits. |
prismatic |
SliderJoint3D |
Linear motion allowed along X axis. Limits configured via linear_limit. |
ball |
Generic6DOFJoint3D |
3 degrees of angular freedom enabled. Linear locked. |
universal |
Generic6DOFJoint3D |
2 degrees of angular freedom enabled. |
fixed |
Generic6DOFJoint3D |
All 6 degrees of freedom (linear & angular) locked. |
| Axis Alignment | N/A | Joints are automatically rotated so their primary axis aligns with the SDF <axis> vector. |
| SDF Geometry | Godot Resource | Notes |
|---|---|---|
<box> |
BoxMesh / BoxShape3D |
Size mapped to Godot size/extents. |
<sphere> |
SphereMesh / SphereShape3D |
Radius mapped directly. |
<cylinder> |
CylinderMesh / CylinderShape3D |
Radius and Length mapped. |
<plane> |
PlaneMesh / BoxShape3D |
Plane mesh created. Collision uses a thin BoxShape for stability. |
<mesh> |
File Import |
External files (.dae, .stl, etc.) are converted/imported. <submesh> supported if applicable. |
The converter extracts material properties from <material> tags and maps them to StandardMaterial3D.
| SDF Tag | Godot Property | Notes |
|---|---|---|
<diffuse> |
albedo_color |
Base color. |
<metalness> |
metallic |
Scalar value. |
<roughness> |
roughness |
Scalar value. |
<emissive> |
emission |
Emission color. |
<pbr>/<metal>/<albedo_map> |
albedo_texture |
Texture map. |
<pbr>/<metal>/<normal_map> |
normal_texture |
Normal map enabled. |
<pbr>/<metal>/<metalness_map> |
metallic_texture |
Metallic map. |
<pbr>/<metal>/<roughness_map> |
roughness_texture |
Roughness map. |
Sensors are created as nodes with metadata describing their configuration. Custom scripts (not provided by the converter) are required to implement the actual simulation logic.
| SDF Sensor | Godot Node | Metadata Properties |
|---|---|---|
camera |
Camera3D |
fov, near, far, width, height, lens intrinsics. |
depth |
Camera3D |
Same as camera, with is_depth_sensor=True. |
lidar / ray |
Node3D |
horizontal (samples, resolution, angles), vertical, range, noise. |
imu |
Node3D |
Placeholder. |
gps |
Node3D |
Placeholder. |
-
Coordinate Systems:
- SDF uses Z-up (Right-Handed).
- Godot uses Y-up (Right-Handed).
- The converter automatically applies a root rotation (-90° X) to align the world.
- Individual poses are converted into the Godot frame, preserving relative transforms.
-
Mesh Orientation:
- Meshes with Z-up geometry are automatically rotated during the import process to match Godot's Y-up convention.
- If
assimpis unavailable, complex mesh conversions (like .dae with specific axis definitions) might rely on Godot's default import behavior, which can vary.
-
Simulation Logic:
- While the scene structure, physics, and visuals are fully converted, logic provided by Gazebo plugins (e.g., diff-drive controllers) is not automatically converted to GDScript.
- The converter preserves plugin parameters in metadata to assist in manual reimplementation.