Importing a robot arm multibody model from a URDF file

Importing a robot arm multibody model from a URDF file#

The purpose of this notebook is to

  • demonstrate the creation of a Karana.Dynamics.Multibody instance for a robot arm from a URDF model file

  • show the structure of the loaded model

  • show a 3D visualization of the robot arm

  • serve as a hello world script for verifying a proper kdFlex installation

Resources

Acknowledgements The Barrett WAM urdf is sourced from the public repository barrett-ros2-pkg. Thank you to the authors and contributors.

Import kdFlex Python modules objects for use later

from pathlib import Path
import atexit

import Karana.Core as kc
import Karana.Frame as kf
import Karana.Dynamics.SOADyn_types as kdt
import Karana.KUtils.BasicPrefab as kub
from Karana.KUtils.Sim import Sim

Build the filepath to the URDF file we will import

resources = Path().absolute().parent / "resources"
urdf_file = resources / "wam7dof" / "wam7dof_hand.urdf"

Import the URDF file to create a BasicPrefabDS. The “DS” is short for “Data Structure”. This is kdFlex’s native, file-format agnostic way of specifying a multibody and associated KModels. We’ll use this next to create our simulation.

basic_prefab_ds = kub.BasicPrefabDS.fromFile(urdf_file)

Instantiate and configure the Karana.Dynamics.Multibody based on the BasicPrefabDS description.

sim, prefab = Sim.fromBasicPrefabDS(basic_prefab_ds)
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
Cell In[4], line 1
----> 1 sim, prefab = Sim.fromBasicPrefabDS(basic_prefab_ds)

File ~/src/sboxes/sbox/x86_64-ubuntu24.04/install/lib/PYTHON/Karana/KUtils/Sim.py:354, in Sim.fromBasicPrefabDS(cls, basic_prefab_ds)
    351 fc = FrameContainer("root")
    352 bc.at_exit_fns[f"_discard_fc_{fc.id()}"] = _discard(fc)
--> 354 bp, sp = BasicPrefab[ExtraInfoType].createStandalone(basic_prefab_ds, fc)
    355 mb = sp.getSubTree().multibody()
    356 bc.at_exit_fns[f"_discard_mb_{mb.id()}"] = _discard(mb)

File ~/src/sboxes/sbox/x86_64-ubuntu24.04/install/lib/PYTHON/Karana/KUtils/BasicPrefab.py:1056, in BasicPrefab.createStandalone(cls, basic_prefab_ds, fc)
   1054 # Create the BasicPrefab
   1055 basic_prefab_ds.context.model_manager = sp
-> 1056 bp = cast(Self, basic_prefab_ds.toPrefab(None))
   1058 sp = cast(StatePropagator, basic_prefab_ds.context.model_manager)
   1060 return bp, sp

File ~/src/sboxes/sbox/x86_64-ubuntu24.04/install/lib/PYTHON/Karana/KUtils/Prefab.py:221, in PrefabDS.toPrefab(self, parent_or_top, context)
    219     obj = klass(self.name, self.config, context, self.params, parent)  # pyright: ignore - Pyright false positive.
    220 else:
--> 221     obj = klass(self.name, self.config, self.context, self.params, parent)  # pyright: ignore - Pyright false positive.
    223 # Add children
    224 for c in self.children:

File ~/src/sboxes/sbox/x86_64-ubuntu24.04/install/lib/PYTHON/Karana/KUtils/Prefab.py:302, in Prefab.__init__(self, name, config, context, params, parent_prefab)
    300 if self.parent is None or (self.parent is not None and self.parent._initialized):
    301     self._addChildPrefabs()
--> 302     self._addMultibodyObjects()
    303     self._addKModels()
    304     self._connectKModels()

File ~/src/sboxes/sbox/x86_64-ubuntu24.04/install/lib/PYTHON/Karana/KUtils/Prefab.py:482, in Prefab._addMultibodyObjects(self)
    480 def _addMultibodyObjects(self) -> None:
    481     """Call addMultibodyObjects on this and all children recursively."""
--> 482     self.addMultibodyObjects()
    484     for c in self._children:
    485         c._addMultibodyObjects()

File ~/src/sboxes/sbox/x86_64-ubuntu24.04/install/lib/PYTHON/Karana/KUtils/BasicPrefab.py:885, in BasicPrefab.addMultibodyObjects(self)
    882     if self.params.subtree_state_info is not None:
    883         self.params.subtree_state_info.toSubTree(st)
--> 885 discard(st)

AttributeError: 'Handle' object has no attribute '__dict__'

Finalize the model to get it ready for use.

sim.mb.ensureHealthy()
sim.mb.resetData()

Set up the 3D graphics.

_, graphics = sim.setupGraphics(port=0)
graphics.defaultCamera().pointCameraAt(
    offset=[0.2, 0.5, 1.7],
    target=[0, 0, 1],
    up=[1, 0, 0],
)
del graphics

Display the bodies in the multibody model.

sim.mb.displayModel()

Display the topological structure of the multibody system

sim.mb.dumpTree()

Animate the graphics by articulating the individual joints.

sim.mb.articulateBodies()

Cleanup

def cleanup():
    """Cleanup the simulation."""
    global basic_prefab_ds, prefab, sim
    del basic_prefab_ds, prefab, sim


atexit.register(cleanup)