|
| 1 | +URDF Utilities |
| 2 | +============== |
| 3 | + |
| 4 | +There are several URDF tools in `node_helpers` for launching, validating, and testing URDF-based systems, providing a standardized approach to handling URDFs in robotics applications. |
| 5 | + |
| 6 | +Overview |
| 7 | +-------- |
| 8 | + |
| 9 | +The module includes the following components: |
| 10 | +1. **node_helpers.launching.URDFModuleNodeFactory**: Streamlines creation of `joint_state_publisher` and `robot_state_publisher` for URDFs in launch files. |
| 11 | +2. **node_helpers.urdfs.URDFConstant**: Provides consistent access to URDF frames and joints, with validation tools. This is key for accessing 'tf' frames and 'joints' in a standardized way, without having random string constants sprinkled around your codebase. |
| 12 | +3. **node_helpers.testing.URDFModuleFixture**: Facilitates launching URDF modules for integration tests. |
| 13 | + |
| 14 | +URDFConstant |
| 15 | +------------ |
| 16 | + |
| 17 | +The `URDFConstants` class provides a structured way to reference and validate URDF elements, such as joints and frames. It ensures URDF correctness and avoids duplicate names or missing elements. |
| 18 | + |
| 19 | +**Features**: |
| 20 | + |
| 21 | +- Load multiple URDF's but refer to them as a single module in code. |
| 22 | +- Prepend namespaces to avoid conflicts. |
| 23 | +- Validate that joints and frames exist in the URDF. |
| 24 | +- Dynamically adjust URDFs with namespaces. |
| 25 | + |
| 26 | +**Example**: |
| 27 | + |
| 28 | +Below, we create the concept of a "BigBird" robot, which consists of two URDFs. |
| 29 | +We then, at the bottom, create a `BigBirdURDF` object that encapsulates the URDFs and provides access to the joints and frames. |
| 30 | + |
| 31 | +The BigBirdJoint and BigBirdFrames classes define the joints and frames in the URDFs, |
| 32 | +and refer to real URDF elements by their names, prepended with `bird_gantry` or `bird_base` |
| 33 | +to point back to what URDF file they came from. The `urdf_paths` parameter in the `URDFConstants` constructor |
| 34 | +specifies what URDF the prepended names refer to. |
| 35 | + |
| 36 | +.. code-block:: python |
| 37 | +
|
| 38 | + from typing import NamedTuple |
| 39 | +
|
| 40 | + from urdf_data.urdf_constants import URDFConstants |
| 41 | +
|
| 42 | +
|
| 43 | + class BigBirdJoints(NamedTuple): |
| 44 | + X: str = "bird_gantry.xaxis" |
| 45 | + Y: str = "bird_gantry.yaxis" |
| 46 | + Z: str = "bird_gantry.zaxis" |
| 47 | + PAN: str = "bird_gantry.waxis" |
| 48 | +
|
| 49 | +
|
| 50 | + class BigBirdFrames(NamedTuple): |
| 51 | + BASE_LINK: str = "bird_base.gantry_base_link" |
| 52 | +
|
| 53 | + X_AXIS_ORIGIN: str = "bird_gantry.xaxis_parent_datum" |
| 54 | + X_AXIS_CURRENT: str = "bird_gantry.gantry_xlink" |
| 55 | +
|
| 56 | + Y_AXIS_ORIGIN: str = "bird_gantry.yaxis_parent_datum" |
| 57 | + Y_AXIS_CURRENT: str = "bird_gantry.gantry_ylink" |
| 58 | +
|
| 59 | + Z_AXIS_ORIGIN: str = "bird_gantry.zaxis_parent_datum" |
| 60 | + Z_AXIS_CURRENT: str = "bird_gantry.gantry_zlink" |
| 61 | +
|
| 62 | + PAN_ORIGIN: str = "bird_gantry.waxis_parent_datum" |
| 63 | + PAN_CURRENT: str = "bird_gantry.gantry_wlink" |
| 64 | +
|
| 65 | +
|
| 66 | + TOOL_TIP: str = "bird.grasp_point" |
| 67 | +
|
| 68 | +
|
| 69 | + BigBirdURDF = URDFConstants[BigBirdJoints, BigBirdFrames]( |
| 70 | + registration_name="bird_robot", |
| 71 | + urdf_paths=[ |
| 72 | + ("bird_base", "path/to/bird_base/robot.urdf"), |
| 73 | + ("bird_gantry", "path/to/bird_gantry/robot.urdf"), |
| 74 | + joints=BigBirdJoints(), |
| 75 | + frames=BigBirdFrames(), |
| 76 | + ) |
| 77 | +
|
| 78 | +Note that an example URDF constant can be found in ``pkgs/node_helpers_test/integration/urdfs/example_urdf_constants.py`` |
| 79 | +
|
| 80 | +URDFModule |
| 81 | +---------- |
| 82 | +
|
| 83 | +The `URDFModuleNodeFactory` simplifies launching URDF nodes by generating `robot_state_publisher` and `joint_state_publisher` nodes for each URDF file. It applies namespaces to avoid collisions and ensures URDFs are properly loaded and validated. |
| 84 | +
|
| 85 | +In the below example, a ``joint_state_publisher`` will be created under the ``/big_bird_left/`` namespace, |
| 86 | +and multiple ``robot_state_publishers`` will be created for each URDF file in the `BigBirdURDF` constant. |
| 87 | +For example, one will live under ``/big_bird_left/urdf_0/`` and the other under ``/big_bird_left/urdf_1/``. |
| 88 | +
|
| 89 | +They will all publish to the same ``joint_state_publisher`` under the ``/big_bird_left/`` namespace. |
| 90 | +
|
| 91 | +**Example**: |
| 92 | +
|
| 93 | +.. code-block:: python |
| 94 | +
|
| 95 | + from node_helpers.urdfs.urdf_module_launching import URDFModuleNodeFactory |
| 96 | +
|
| 97 | + parameters = URDFModuleNodeFactory.Parameters( |
| 98 | + namespace: "big_bird_left", |
| 99 | + urdf_constant_name: "BigBirdURDF", |
| 100 | + apply_namespace_to_urdf: True, |
| 101 | + ) |
| 102 | + factory = URDFModuleNodeFactory(parameters) |
| 103 | + nodes = factory.create_nodes() # these nodes can be added to a launch description |
| 104 | +
|
| 105 | +
|
| 106 | +URDFModuleFixture |
| 107 | +------------------ |
| 108 | +
|
| 109 | +The ``URDFModuleFixture`` class is a pytest fixture utility for setting up URDF-based tests. It |
| 110 | +will launch the URDF module (and all it's `robot_state_publisher`s and `joint_state_publisher`, |
| 111 | +and ensure that all TF frames are published correctly before yielding the fixture. |
| 112 | +
|
| 113 | +**Example**: |
| 114 | +
|
| 115 | +.. code-block:: python |
| 116 | +
|
| 117 | + from node_helpers.urdfs.urdf_module_fixture import URDFModuleFixture |
| 118 | +
|
| 119 | + @pytest.fixture() |
| 120 | + def big_bird_urdf_module() -> Generator[URDFModuleFixture, None, None]: |
| 121 | + yield from URDFModuleFixture.set_up( |
| 122 | + URDFModuleNodeFactory.Parameters( |
| 123 | + namespace="big_bird_top", urdf_constant_name=BigBirdURDF.registration_name |
| 124 | + ) |
| 125 | + ) |
| 126 | +
|
| 127 | +
|
| 128 | +A full example of how to integration test URDFs can be found under ``pkgs/node_helpers/node_helpers_test/integration/urdfs/test_forklift.py`` |
| 129 | +
|
| 130 | +Note that ``node_helpers`` provides a helpful test URDF in ``pkgs/node_helpers/sample_urdfs/forklift/robot.urdf`` |
0 commit comments