# Create a tool

> Create a reusable tool in NVIDIA Isaac Sim and connect it to Wandelbots NOVA.

In this section you will learn how to create a reusable tool in Isaac Sim and connect it to Wandelbots NOVA.
First time using OmniGraph (OGN)? Check out the [OmniGraph Nodes documentation](/simulation/omnigraph-nodes/connect-ios) to learn more about the basics of OGN.

Creating tools from CAD files is not in the scope of this section.

> **Warning:** Tool configuration via the Robot Pad is deprecated since Wandelbots NOVA Isaac Sim extension 2.0.
> Use OmniGraph Nodes to configure tools as described in the following article.

You'll need a scene containing a tool. Check out our asset package provided in [NOVA Cloud downloads](/nova-cloud/downloads) to get started.

### Step 1: Open tool and add function attributes

Open the desired tool which only contains the tool which can be attached to the robot later on. In case there are any other elements (xform, mesh, lights etc.) in the stage of your tool which should not be imported into the robot scene, please remove them.

In the first step the interface of the tool needs to be defined. This will be done via custom attributes.
In the video below the workflow is shown for a boolean open attribute which indicates the gripper open state (true or false).
Additionally a finger distance attribute (float) is added which indicates the distance between the gripper fingers.
This is used to calculate the target position of the gripper fingers later on. This attribute is added like the boolean attribute, with `float` as type selected.

Using attributes to abstract the internal logic allows users to connect the node to different scene logic without modifying its implementation.

Video: [/video/omniservice/tool\_creation/add\_tool\_api\_attributes.webm](/video/omniservice/tool_creation/add_tool_api_attributes.webm)

> **Info:** Adding I/O logic right to the tool decreases the flexibility of the tool and makes it harder to use in different scenarios.

### Step 2: Add OGN trigger for attribute changes

Next up, the tool needs an action graph. An action graph allows for modifying the gripper fingers on
attribute change (open to true or false). [On USD object change](https://docs.omniverse.nvidia.com/kit/docs/omni.graph.action_nodes/latest/GeneratedNodeDocumentation/OgnOnObjectChange.html)
enables listening for changes to the created `open` property. Once a change is detected for `open`, the node will trigger a
changed execution which can be used in action graphs to call other nodes and change properties of the tool prims.

![Trigger execution on attribute change](/assets/nova/omniservice/tool_creation/ogn_root_prim_state_change.webp)

### Step 3: Read the attributes to change tool prims

Before writing anything to the tool prims, the values of the `open` and `finger_distance` attributes
need to be read. This can be done with the [Read Prim Attribute](https://docs.omniverse.nvidia.com/extensions/latest/ext_omnigraph/node-library/nodes/omni-graph-nodes/readprimattribute-3.html) node.

![Read finger distance attribute](/assets/nova/omniservice/tool_creation/ogn_root_prim_read_finger_distance.webp)

Based on the `open` attribute, `finger_distance` value is selected.
If the gripper state `open` is true, the distance is read from the prim attribute. Otherwise a constant value of zero is used.

![Read open state attribute](/assets/nova/omniservice/tool_creation/ogn_root_prim_read_open_state.webp)

With the right distance values passed, the values can be updated via a [Write Prim Attribute](https://docs.omniverse.nvidia.com/extensions/latest/ext_omnigraph/node-library/nodes/omni-graph-nodes/writeprimattribute-2.html)
node. In this case the tool has one prismatic joint for each finger.
These joints are controlled using their `targetPosition` attribute.
One joint needs to move in the opposite direction of the other joint,
so the `finger_distance` value is negated for one of the joints with a multiply node which takes minus one as one constant input.

You can see one of the two linear drives which target position is updated based on the `finger_distance` value.
Both fingers are written sequentially by chaining the execution pins of the `Write Prim Attribute` nodes.

> **Info:** Replicator offers a [Write Prim Attribute](https://docs.omniverse.nvidia.com/extensions/latest/ext_omnigraph/node-library/nodes/omni-replicator-core/ognwriteprimattribute-1.html) as well.
> The input requires an array and the node from `omni.graph.nodes` offers
> a dropdown to select the right attribute which smooths the workflow.

![Write target position attribute](/assets/nova/omniservice/tool_creation/ogn_write_target_position.webp)

### Step 4: Testing the tool

Now the tool graph should look something like this:

![Full tool graph](/assets/nova/omniservice/tool_creation/ogn_full_graph.webp)

For debugging a print text node was added to print a string once the `open` attribute is changed.

To test the setup, start the simulation and change the `open` attribute of the tool prim.

In this example the tool is already mounted to a motion group. If you have a blank scene with just a tool attached,
switch to camera light and disable the rigid body's gravity to enable testing in the scene.

Video: [/video/omniservice/tool\_creation/ogn\_test\_tool\_graph.webm](/video/omniservice/tool_creation/ogn_test_tool_graph.webm)

→ The gripper fingers move to the target position based on the `finger_distance` value.
→ The tool is ready to be added to the robot scene and connected to the robot.

Save the scene and close it.

### Step 5: Add the tool to the scene

To explain how to add the created tool to a robot scene, the explanatory video uses a minimal scene with a UR5e robot.

Drag and drop the tool scene into the robot scene. The tool will be added as a child of the `flange_tcp` prim. This way the tool will receive
the right offsets once its moved to be a child of the robot root node.

Once the tool is at the right position, link the rigid body of the tool to the flange rigid body, usually at `link_6`.

Video: [/video/omniservice/tool\_creation/add\_gripper\_to\_scene.webm](/video/omniservice/tool_creation/add_gripper_to_scene.webm)

→ The tool is attached to the flange and will move with any robot motion if properly connected.

### Step 6: Connect the tool to the robot

You have tested the tool functionality with toggling the `open` attribute. You can do the same with the provided Input/Output nodes.
Create an `On IO Change` node which is connected to a `Write Prim Attribute` node.
The `Write Prim Attribute` node will write the value of the `open` attribute to the tool prim.
The `On IO Change` node will listen to the `bool/digital` `tool_out[0]` Input/Output from the scene UR5e robot.

Video: [/video/omniservice/tool\_creation/ogn\_connect\_io\_change\_to\_tool\_attribute.webm](/video/omniservice/tool_creation/ogn_connect_io_change_to_tool_attribute.webm)

### Step 7: Use the tool via Input/Output changes

If everything is set up correctly, you can toggle the gripper state via Python
by writing `true` or `false` to the `tool_out[0]` Input/Output of the UR5e robot.

```python
controller = await cell.controller("ur5e")
await controller.write("tool_out[0]", True)
```

Video: [/video/omniservice/tool\_creation/ogn\_on\_io\_change\_gripper\_move.webm](/video/omniservice/tool_creation/ogn_on_io_change_gripper_move.webm)

### Troubleshooting

#### Wrong write prim attribute node

If you picked the replicator read/write prim attribute nodes, you might get this error:

```
[Error] [omni.graph.core.plugin] /World/ActionGraph/write_prim_attribute_01: [/World/ActionGraph] OmniGraph Error: WritePrimAttribute Error: object of type 'float' has no len()". .................I am still unable to close the grippers
```

The attribute nodes look similar, but expect values as an array. The recommended nodes from `omni.graph.nodes` provide a dropdown to select the attribute.
