-
Notifications
You must be signed in to change notification settings - Fork 516
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
3 changed files
with
188 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,181 @@ | ||
# Copyright (c) 2022, NVIDIA CORPORATION & AFFILIATES, ETH Zurich, and University of Toronto | ||
# All rights reserved. | ||
# | ||
# SPDX-License-Identifier: BSD-3-Clause | ||
|
||
""" | ||
Utility to convert a URDF into USD format. | ||
Unified Robot Description Format (URDF) is an XML file format used in ROS to describe all elements of | ||
a robot. For more information, see: http://wiki.ros.org/urdf | ||
This script uses the URDF importer extension from Isaac Sim (``omni.isaac.urdf_importer``) to convert a | ||
URDF asset into USD format. It is designed as a convenience script for command-line use. For more | ||
information on the URDF importer, see the documentation for the extension: | ||
https://docs.omniverse.nvidia.com/app_isaacsim/app_isaacsim/ext_omni_isaac_urdf.html | ||
positional arguments: | ||
input The path to the input URDF file. | ||
output The path to store the USD file. | ||
optional arguments: | ||
-h, --help show this help message and exit | ||
--headless Force display off at all times. (default: False) | ||
--merge_joints, -m Consolidate links that are connected by fixed joints. (default: False) | ||
--fix_base, -f Fix the base to where it is imported. (default: False) | ||
--gym, -g Make the asset instanceable for efficient cloning. (default: False) | ||
""" | ||
|
||
"""Launch Isaac Sim Simulator first.""" | ||
|
||
|
||
import argparse | ||
import contextlib | ||
|
||
# omni-isaac-orbit | ||
from omni.isaac.kit import SimulationApp | ||
|
||
# add argparse arguments | ||
parser = argparse.ArgumentParser("Utility to convert a URDF into USD format.") | ||
parser.add_argument("input", type=str, help="The path to the input URDF file.") | ||
parser.add_argument("output", type=str, help="The path to store the USD file.") | ||
parser.add_argument("--headless", action="store_true", default=False, help="Force display off at all times.") | ||
parser.add_argument( | ||
"--merge_joints", | ||
"-m", | ||
action="store_true", | ||
default=False, | ||
help="Consolidate links that are connected by fixed joints.", | ||
) | ||
parser.add_argument( | ||
"--fix_base", "-f", action="store_true", default=False, help="Fix the base to where it is imported." | ||
) | ||
parser.add_argument( | ||
"--gym", "-g", action="store_true", default=False, help="Make the asset instanceable for efficient cloning." | ||
) | ||
args_cli = parser.parse_args() | ||
|
||
# launch omniverse app | ||
config = {"headless": args_cli.headless} | ||
simulation_app = SimulationApp(config) | ||
|
||
|
||
"""Rest everything follows.""" | ||
|
||
import os | ||
|
||
import carb | ||
import omni.isaac.core.utils.stage as stage_utils | ||
import omni.kit.commands | ||
from omni.isaac.core.simulation_context import SimulationContext | ||
|
||
from omni.isaac.orbit.utils.assets import check_file_path | ||
|
||
_DRIVE_TYPE = { | ||
"none": 0, | ||
"position": 1, | ||
"velocity": 2, | ||
} | ||
"""Mapping from drive name to URDF importer drive number.""" | ||
|
||
_NORMALS_DIVISION = { | ||
"catmullClark": 0, | ||
"loop": 1, | ||
"bilinear": 2, | ||
"none": 3, | ||
} | ||
"""Mapping from normals division name to URDF importer normals division number.""" | ||
|
||
|
||
def main(): | ||
# check valid file path | ||
urdf_path = args_cli.input | ||
if not os.path.isabs(urdf_path): | ||
urdf_path = os.path.abspath(urdf_path) | ||
if not check_file_path(urdf_path): | ||
raise ValueError(f"Invalid file path: {urdf_path}") | ||
# create destination path | ||
dest_path = args_cli.output | ||
if not os.path.isabs(dest_path): | ||
dest_path = os.path.abspath(dest_path) | ||
if os.path.exists(dest_path): | ||
carb.log_warn(f"Destination file already exists: {dest_path}. Overwriting...") | ||
if not os.path.exists(os.path.dirname(dest_path)): | ||
os.makedirs(os.path.dirname(dest_path)) | ||
|
||
# Import URDF config | ||
_, urdf_config = omni.kit.commands.execute("URDFCreateImportConfig") | ||
|
||
# Set URDF config | ||
# -- stage settings -- dont need to change these. | ||
urdf_config.set_distance_scale(1.0) | ||
urdf_config.set_up_vector(0, 0, 1) | ||
urdf_config.set_create_physics_scene(False) | ||
urdf_config.set_make_default_prim(True) | ||
# -- instancing settings | ||
urdf_config.set_make_instanceable(args_cli.gym) | ||
urdf_config.set_instanceable_usd_path("Props/instanceable_meshes.usd") | ||
# -- asset settings | ||
urdf_config.set_density(0.0) | ||
urdf_config.set_import_inertia_tensor(True) | ||
urdf_config.set_convex_decomp(False) | ||
urdf_config.set_subdivision_scheme(_NORMALS_DIVISION["bilinear"]) | ||
# -- physics settings | ||
urdf_config.set_fix_base(args_cli.fix_base) | ||
urdf_config.set_self_collision(False) | ||
urdf_config.set_merge_fixed_joints(args_cli.merge_joints) | ||
# -- drive settings | ||
# note: we set these to none because we want to use the default drive settings. | ||
urdf_config.set_default_drive_type(_DRIVE_TYPE["none"]) | ||
# urdf_config.set_default_drive_strength(1e7) | ||
# urdf_config.set_default_position_drive_damping(1e5) | ||
|
||
# Print info | ||
print("-" * 80) | ||
print("-" * 80) | ||
print(f"Input URDF file: {urdf_path}") | ||
print(f"Saving USD file: {dest_path}") | ||
print("URDF importer config:") | ||
for key in dir(urdf_config): | ||
if not key.startswith("__"): | ||
try: | ||
# get attribute | ||
attr = getattr(urdf_config, key) | ||
# check if attribute is a function | ||
if callable(attr): | ||
continue | ||
# print attribute | ||
print(f"\t{key}: {attr}") | ||
except TypeError: | ||
# this is only the case for subdivison scheme | ||
pass | ||
print("-" * 80) | ||
print("-" * 80) | ||
|
||
# Import URDF file | ||
omni.kit.commands.execute( | ||
"URDFParseAndImportFile", urdf_path=urdf_path, import_config=urdf_config, dest_path=dest_path | ||
) | ||
|
||
# Simulate scene (if not headless) | ||
if not args_cli.headless: | ||
# Open the stage with USD | ||
stage_utils.open_stage(dest_path) | ||
# Load kit helper | ||
sim = SimulationContext(stage_units_in_meters=1.0) | ||
# stage_utils.add_reference_to_stage(dest_path, "/Robot") | ||
# Reinitialize the simulation | ||
# Run simulation | ||
with contextlib.suppress(KeyboardInterrupt): | ||
while True: | ||
# perform step | ||
sim.step() | ||
|
||
|
||
if __name__ == "__main__": | ||
# Run cloning example | ||
main() | ||
# Close the simulator | ||
simulation_app.close() |