https://github.com/clemense/yourdfpy

Python parser for URDFs

https://github.com/clemense/yourdfpy

Science Score: 26.0%

This score indicates how likely this project is to be science-related based on various indicators:

  • CITATION.cff file
  • codemeta.json file
    Found codemeta.json file
  • .zenodo.json file
    Found .zenodo.json file
  • DOI references
  • Academic publication links
  • Committers with academic emails
  • Institutional organization owner
  • JOSS paper metadata
  • Scientific vocabulary similarity
    Low similarity (10.3%) to scientific vocabulary

Keywords

kinematics robotics ros urdf urdf-descriptions urdf-models urdf-parser urdf-visualizer

Keywords from Contributors

legged-robotics
Last synced: 6 months ago · JSON representation

Repository

Python parser for URDFs

Basic Info
  • Host: GitHub
  • Owner: clemense
  • License: mit
  • Language: Python
  • Default Branch: main
  • Homepage:
  • Size: 639 KB
Statistics
  • Stars: 210
  • Watchers: 4
  • Forks: 18
  • Open Issues: 16
  • Releases: 12
Topics
kinematics robotics ros urdf urdf-descriptions urdf-models urdf-parser urdf-visualizer
Created over 4 years ago · Last pushed 8 months ago
Metadata Files
Readme Changelog Contributing License Authors

README.md

Documentation Status Coverage Status PyPI version

yourdfpy

Yet anOther URDF parser for Python. Yup, it's another one. Deal with it.

Yourdfpy is a simpler and easier-to-use library for loading, manipulating, validating, saving, and visualizing URDF files.

Installation

You can install yourdfpy directly from pip: pip install yourdfpy

Visualization

Once installed, you can visualize a URDF model from the command line: yourdfpy ./my_description/urdf/robot.urdf

You can use the following keyboard shortcuts to inspect your model:

  • a: Toggle rendered XYZ/RGB axis markers (off, world frame, every frame)
  • w: Toggle wireframe mode (good for looking inside meshes, off by default)
  • c: Toggle back face culling (on by default but in wireframe mode it is sometimes useful to see the back sides)

But why another one?!?

Why are you wasting not only your but also our time? you might ask. Fair point. There are already urdfpy and urdfparserpy that deal with URDFs. Unfortunately, none of these solutions allow customizable URDF parsing that is fully independent of validation and mesh loading. Dealing with filenames, outdated dependencies, open bug reports, and limited flexibility when it comes to serialization are other disadvantages. As shown in the table below, yourdfpy is the most robust one when it comes to loading URDFs in the wild.

Example URDFs

| | urdfpy | urdfparserpy | yourdfpy | | ---------------------------------------------------------------------------------------------: | :---------------------------------------: | :-----------------------------------------------------: | :----------------: | | Decouple parsing from validation | | | :heavycheckmark: | | Decouple parsing from loading meshes | | :heavycheckmark: | :heavycheckmark: | | Visualize URDF | :heavycheckmark: | | :heavycheckmark: | | Forward Kinematics | :heavycheckmark: | | :heavycheckmark: | | Robustness test: loading 12 URDF files from here | 4/12 | 6/12 | 12/12 | | Avg. loading time per file (w/ mesh loading) | 480 ms | | 370 ms | | (w/o mesh loading) | | 3.2 ms | 6.2 ms | | Test on 4 URDF files on which urdfpy succeeds | 347.5 ms | | 203 ms | | Test on 6 URDF files on which urdf_parser_py succeeds | | 2.6 ms | 3.8 ms |

Click to expand code listing that produces the above table entries. ```python robot_assets = ['robot-assets/urdfs/robots/barret_hand/bhand_model.URDF', 'robot-assets/urdfs/robots/robotiq_gripper/robotiq_arg85_description.URDF', 'robot-assets/urdfs/robots/anymal/anymal.urdf', 'robot-assets/urdfs/robots/franka_panda/panda.urdf', 'robot-assets/urdfs/robots/ginger_robot/gingerurdf.urdf', 'robot-assets/urdfs/robots/halodi/eve_r3.urdf', 'robot-assets/urdfs/robots/kinova/kinova.urdf', 'robot-assets/urdfs/robots/kuka_iiwa/model.urdf', 'robot-assets/urdfs/robots/pr2/pr2.urdf', 'robot-assets/urdfs/robots/ur10/ur10_robot.urdf', 'robot-assets/urdfs/robots/ur5/ur5_gripper.urdf', 'robot-assets/urdfs/robots/yumi/yumi.urdf'] import urdfpy import urdf_parser_py import yourdfpy from functools import partial def load_urdfs(fnames, load_fn): results = {fname: None for fname in fnames} for fname in fnames: try: x = load_fn(fname) results[fname] = x except: print("Problems loading: ", fname) pass print(sum([1 for x, y in results.items() if y is not None]), "/", len(fnames)) return results # parsing success rate load_urdfs(robot_assets, urdfpy.URDF.load) load_urdfs(robot_assets, urdf_parser_py.urdf.URDF.load) load_urdfs(robot_assets, yourdfpy.URDF.load) # parsing times %timeit load_urdfs(robot_assets, urdfpy.URDF.load) %timeit load_urdfs(robot_assets, urdf_parser_py.urdf.URDF.load) %timeit load_urdfs(robot_assets, yourdfpy.URDF.load) %timeit load_urdfs(robot_assets, partial(yourdfpy.URDF.load, load_meshes=False, build_scene_graph=False)) # fairer comparison with yourdfpy urdfpy_fnames = [x for x, y in load_urdfs(robot_assets, urdfpy.URDF.load).items() if y is not None] %timeit load_urdfs(urdfpy_fnames, yourdfpy.URDF.load) # fairer comparison with urdf_parser_py urdfparser_fnames = [x for x, y in load_urdfs(robot_assets, urdf_parser_py.urdf.URDF.from_xml_file).items() if y is not None] %timeit load_urdfs(urdfparser_fnames, functools.partial(yourdfpy.URDF.load, load_meshes=False, build_scene_graph=False)) ```

Owner

  • Name: Clemens Eppner
  • Login: clemense
  • Kind: user
  • Company: NVIDIA

GitHub Events

Total
  • Create event: 3
  • Release event: 1
  • Issues event: 3
  • Watch event: 67
  • Delete event: 1
  • Issue comment event: 6
  • Push event: 5
  • Pull request event: 7
  • Fork event: 4
Last Year
  • Create event: 3
  • Release event: 1
  • Issues event: 3
  • Watch event: 67
  • Delete event: 1
  • Issue comment event: 6
  • Push event: 5
  • Pull request event: 7
  • Fork event: 4

Committers

Last synced: 9 months ago

All Time
  • Total Commits: 194
  • Total Committers: 5
  • Avg Commits per committer: 38.8
  • Development Distribution Score (DDS): 0.134
Past Year
  • Commits: 3
  • Committers: 1
  • Avg Commits per committer: 3.0
  • Development Distribution Score (DDS): 0.0
Top Committers
Name Email Commits
Clemens Eppner c****r@n****m 168
Stéphane Caron s****n@n****g 22
Caelan Garrett c****t@n****m 2
Aaron Gokaslan a****n@g****m 1
Stéphane Caron s****e@s****o 1
Committer Domains (Top 20 + Academic)

Issues and Pull Requests

Last synced: 6 months ago

All Time
  • Total issues: 34
  • Total pull requests: 29
  • Average time to close issues: 4 months
  • Average time to close pull requests: 9 days
  • Total issue authors: 9
  • Total pull request authors: 8
  • Average comments per issue: 0.85
  • Average comments per pull request: 0.24
  • Merged pull requests: 24
  • Bot issues: 0
  • Bot pull requests: 0
Past Year
  • Issues: 2
  • Pull requests: 6
  • Average time to close issues: N/A
  • Average time to close pull requests: 2 months
  • Issue authors: 1
  • Pull request authors: 4
  • Average comments per issue: 0.0
  • Average comments per pull request: 0.0
  • Merged pull requests: 2
  • Bot issues: 0
  • Bot pull requests: 0
Top Authors
Issue Authors
  • stephane-caron (18)
  • nashmit (7)
  • caelan (2)
  • OpenGHz (2)
  • maxspahn (1)
  • amalnanavati (1)
  • Skylion007 (1)
  • clemense (1)
  • TontonTremblay (1)
Pull Request Authors
  • clemense (13)
  • stephane-caron (9)
  • OpenGHz (2)
  • david-dorf (1)
  • sea-bass (1)
  • maxspahn (1)
  • caelan (1)
  • Skylion007 (1)
Top Labels
Issue Labels
enhancement (2)
Pull Request Labels

Dependencies

docs/requirements.txt pypi
  • lxml *
  • numpy *
  • recommonmark *
  • sphinx >=3.2.1
  • sphinx-automodapi *
  • sphinx_rtd_theme *
  • trimesh >=3.11.2
pyproject.toml pypi
setup.py pypi
.github/workflows/python-publish.yml actions
  • actions/checkout v3 composite
  • actions/setup-python v3 composite
  • pypa/gh-action-pypi-publish 27b31702a0e7fc50959f5ad993c78deac1bdfc29 composite