Package: yourdfpy
yourdfpyYet 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.InstallationYou can install yourdfpy directly from pip:pip install yourdfpyVisualizationOnce installed, you can visualize a URDF model from the command line:yourdfpy ./my_description/urdf/robot.urdfYou 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 alreadyurdfpyandurdf_parser_pythat 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,yourdfpyis the most robust one when it comes to loading URDFs in the wild.urdfpyurdf_parser_pyyourdfpyDecouple parsing from validation:heavy_check_mark:Decouple parsing from loading meshes:heavy_check_mark::heavy_check_mark:Visualize URDF:heavy_check_mark::heavy_check_mark:Forward Kinematics:heavy_check_mark::heavy_check_mark:Robustness test: loading 12 URDF files fromhere4/126/1212/12Avg. loading time per file (w/ mesh loading)480 ms370 ms(w/o mesh loading)3.2 ms6.2 msTest on 4 URDF files on whichurdfpysucceeds347.5 ms203 msTest on 6 URDF files on whichurdf_parser_pysucceeds2.6 ms3.8 msClick to expand code listing that produces the above table entries.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']importurdfpyimporturdf_parser_pyimportyourdfpyfromfunctoolsimportpartialdefload_urdfs(fnames,load_fn):results={fname:Noneforfnameinfnames}forfnameinfnames:try:x=load_fn(fname)results[fname]=xexcept:print("Problems loading: ",fname)passprint(sum([1forx,yinresults.items()ifyisnotNone]),"/",len(fnames))returnresults# parsing success rateload_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%timeitload_urdfs(robot_assets,urdfpy.URDF.load)%timeitload_urdfs(robot_assets,urdf_parser_py.urdf.URDF.load)%timeitload_urdfs(robot_assets,yourdfpy.URDF.load)%timeitload_urdfs(robot_assets,partial(yourdfpy.URDF.load,load_meshes=False,build_scene_graph=False))# fairer comparison with yourdfpyurdfpy_fnames=[xforx,yinload_urdfs(robot_assets,urdfpy.URDF.load).items()ifyisnotNone]%timeitload_urdfs(urdfpy_fnames,yourdfpy.URDF.load)# fairer comparison with urdf_parser_pyurdfparser_fnames=[xforx,yinload_urdfs(robot_assets,urdf_parser_py.urdf.URDF.from_xml_file).items()ifyisnotNone]%timeitload_urdfs(urdfparser_fnames,functools.partial(yourdfpy.URDF.load,load_meshes=False,build_scene_graph=False))