# Work with datasets in Visual Studio Code

> Keep the poses, frames and command routines of your robot programs in Wandelbots NOVA datasets and edit them in Visual Studio Code. Learn how to bind a dataset to a program, teach poses in the Robot Interface, build a command routine and publish a new revision.

A dataset holds the data a robot program moves through: poses, the frames they are taught in and command routines.
Wandelbots NOVA stores each dataset in revisions, so a program can stay on a revision while you teach the next one.
[Datasets](/nova/26.7/nova-api/core-concepts/datasets) explains the concept in detail.

Datasets are the exchange format between the programming touch points of Wandelbots NOVA: created in Isaac Sim, a dataset is reused by NOVA Flow, Python programs and the Robot Interface app — they all read and write the same poses, frames and command routines.

The Python SDK loads a dataset into your program.
The Wandelbots NOVA extension for Visual Studio Code lists the datasets of your instance, shows them on the robot in 3D and saves your edits as a new revision.

## Prerequisites

- Wandelbots NOVA 26.7 or newer. The dataset endpoints are experimental and may change.
- The Python SDK `wandelbots-nova` 6.1.0 or newer in the project of your program.
- The Wandelbots NOVA extension 4.2.0 or newer for Visual Studio Code.

> **Info:** The Visual Studio Code app from the Wandelbots NOVA app store does not ship the extension.
> Install it from the `Extensions` view: search for `Wandelbots NOVA` and click `Install`.

## Connect the extension to your instance

1. Open the settings with `Ctrl+,` and search for `Wandelbots NOVA`.
2. Enter the address of your instance in `wandelbots-nova-viewer.novaApi`, for example `https://abcdefgh.instance.wandelbots.io`.
3. For a cloud instance, enter your access token in `wandelbots-nova-viewer.accessToken`.
4. Optional: Change `wandelbots-nova-viewer.cellName` if your cell is not named `cell`.
5. Click the Wandelbots NOVA logo in the activity bar.\
   → The `Wandelbots NOVA` view shows `Connected`.

The extension only runs in a trusted workspace. Trust the workspace when Visual Studio Code asks.

## Find the datasets of your instance

Open the `Data Sharing Service` from the `Wandelbots NOVA` view, or run `Wandelbots NOVA: Open Data Sharing Service` from the command palette.

![Screenshot of the Data Sharing Service tab in Visual Studio Code with one card per dataset and its latest revision](/assets/nova/programming/vscode-datasets-data-sharing.webp)

The tab lists one card per dataset, with the number of revisions and the latest one.
Click a card to see its revisions. The menu of a revision offers three actions:

- `Open in Robot Interface` shows the revision on the robot.
- `Download dataset` saves it as `<dataset>/dataset.json` into a folder you choose.
- `Delete` deletes this revision.

![Screenshot of the list of dataset revisions with the menu Open in Robot Interface, Download dataset and Delete](/assets/nova/programming/vscode-datasets-versions.webp)

To add a dataset, click the upload button `Import JSON file` and select a dataset file.
The extension takes the identifier from the `dataset` field of the file.
If a dataset with this identifier exists, the file becomes its next revision.

> **Info:** The `Data Sharing Service` shows the name of a dataset, not its identifier.
> Your program needs the identifier. Download the dataset to see it: the extension names the folder after it.

## Bind a dataset to a program

A program declares its dataset in its preconditions.
Then `ctx.dataset` holds the poses, frames and command routines when the program starts.

### Step 1: Declare the dataset

Pass the dataset to `nova.ProgramPreconditions`:

```python
import nova
from nova import api, run_program
from nova import datasets as ds
from nova.actions import cartesian_ptp, joint_ptp
from nova.cell import virtual_controller


@nova.program(
    id="pick_and_place",
    name="Pick and place",
    preconditions=nova.ProgramPreconditions(
        controllers=[
            virtual_controller(
                name="kuka-kr16-r2010",
                manufacturer=api.models.Manufacturer.KUKA,
                type="kuka-kr16_r2010_2",
            )
        ],
        dataset=ds.remote_dataset("default", revision=1),
        cleanup_controllers=False,
    ),
)
async def pick_and_place(ctx: nova.ProgramContext):
    motion_group = (await ctx.cell.controller("kuka-kr16-r2010"))[0]
    tcp = (await motion_group.tcp_names())[0]
    home = await motion_group.joints()

    pick = ctx.dataset.poses["pick"].as_world()
    place = ctx.dataset.poses["place"].as_world()

    actions = [cartesian_ptp(pick), cartesian_ptp(place), joint_ptp(home)]
    trajectory = await motion_group.plan(actions, tcp)
    await motion_group.execute(trajectory, tcp, actions=actions)


if __name__ == "__main__":
    run_program(pick_and_place)
```

Choose where the dataset comes from:

- `ds.remote_dataset("default", revision=1)` loads revision 1 of the dataset `default` from your instance. Leave out `revision` to load the latest revision.
- `ds.local_dataset("pick_and_place.json")` reads a dataset file. The path is relative to the Python file.

Write the identifier and the path as plain strings.
The extension reads them from your code and ignores a variable or an expression such as `Path(__file__).parent`.

### Step 2: Move to the poses

A pose is stored relative to its frame. Call `as_world()` before you move to it:

- `ctx.dataset.poses["pick"].as_world()` returns the pose in world coordinates.
- `ctx.dataset.frames["table"].as_world()` returns the transform from a frame to the world.

`as_world()` follows the chain of frames in your program, without a request to the instance.
Moving to `.pose` instead sends the robot to the wrong place when the pose has a frame.

### Step 3: Run the program

Click `Run` above `@nova.program`.\
→ The program loads the dataset and moves the robot to `pick` and `place`.

![Screenshot of a program in Visual Studio Code with the buttons Run, Debug, Debug path and Robot Interface above the program](/assets/nova/programming/vscode-datasets-codelens.webp)

The extension adds four buttons above every `@nova.program`:

- `Run` runs the program on your instance.
- `Debug` runs it in the Python debugger.
- `Debug path` runs it so you can step through each planned path.
- `Robot Interface` opens the program and its dataset on the robot.

> **Info:** The SDK reads poses, frames and command routines.
> To run a command routine, use the Robot Interface. Running a routine from a program is not part of the SDK yet.

## Teach poses in the Robot Interface

Click `Robot Interface` above your program.
The Robot Interface shows the robot in 3D and the dataset of the program in the panel on the left.

![Screenshot of the Robot Interface with the robot in 3D and the Poses tab listing the frames and poses of the dataset](/assets/nova/programming/vscode-datasets-robot-interface.webp)

### Step 1: Choose the robot

1. In `Motion Group`, select the robot.
2. In `TCP`, select the TCP the poses are taught for.

### Step 2: Edit a pose

1. Select the `Poses` tab.\
   The tree shows the frames of the dataset with their poses inside.
2. Right-click a pose and select `Edit Pose`.
3. Move the robot to the new pose with the `Jogging` panel.\
   To drive the robot to the stored pose first, hold `Move to Pose` in the `Control` panel.
4. In the `Pose` tab, click `Get`.\
   → The coordinates show the current TCP pose, relative to the frame of the pose.
5. Click `Save Changes`.\
   → A dot marks the pose as changed. A grey ghost robot shows the stored pose, a blue one the new pose.

To teach a new pose, right-click a frame and select `Add Pose inside`, or right-click a pose and select `Add Pose before` or `Add Pose after`.
The `Kin. Config` tab sets the robot configuration a pose is reached with.

### Step 3: Save or publish the edits

`Save Changes` keeps the edit in the Robot Interface only.
Click the button in the header of the dataset panel to store it:

- `Publish` creates a new revision of the dataset on your instance.
- `Save` overwrites the dataset file of a program with `ds.local_dataset(...)`.

![Screenshot of the dataset panel with the Publish button in its header and a dot next to the changed pose pick](/assets/nova/programming/vscode-datasets-publish.webp)

![Screenshot of the Edit view of a pose with its coordinates, the Get button and a blue ghost robot at the new pose](/assets/nova/programming/vscode-datasets-edit-pose.webp)

A program bound with a fixed `revision` keeps loading that revision.
Raise the revision in `ds.remote_dataset(...)` once the program should use the new poses.

### Organise frames

Frames group poses, for example per fixture or pallet. Right-click a frame to add, edit or delete frames.

![Screenshot of the context menu of a frame with Edit Frame, Add Pose inside, Add Frame inside, before and after, and Delete Frame](/assets/nova/programming/vscode-datasets-tree-menu.webp)

To move a frame or a pose into another frame, drag it by its grip. The dialog asks how to move it:

- `Keep local values` keeps the stored values, so it moves along with its new frame.
- `Keep world position` recalculates the values, so it stays where it is.

A frame can only be deleted when it is empty.

## Using command routines

A command routine is a sequence of commands: motions to poses of the dataset, waits and I/O.

![Screenshot of the Command Routines tab with the commands of a routine and the button to run it](/assets/nova/programming/vscode-datasets-routines.webp)

With a command routine you can:

- Run entire routines
- Display the robot's paths per routine
- Pause and resume movements along the path, forward and backward

### Build a command routine

Click the routine dropdown and select `Add a new command routine` to append an empty routine to the dataset.

![Screenshot of the routine dropdown with the menu item Add a new command routine](/assets/nova/programming/vscode-datasets-add-new-routine.webp)

Rename the routine id, then start filling the routine with commands.

![Screenshot of a newly created command routine with the button Add command](/assets/nova/programming/vscode-datasets-add-new-command.webp)

Publish the new routine like a pose, with `Publish` in the header of the dataset panel.

### Edit a command routine

Select the `Command Routines` tab and the routine.

- Click the play button `Run routine` to run the routine on the robot.
- Right-click a command and select `Move to this motion command` to drive the robot to its target.
- Right-click a command and select `Edit` to change the motion type, the speed or the blending.
- Right-click a command and select `Add command before` or `Add command after` to insert a command.

In the dialog `Add command`, select the `Command type`.
For a motion, select `New pose at current TCP` to teach a new pose and move to it in one step.

![Screenshot of the Add command dialog with a Cartesian PTP motion to a new pose at the current TCP](/assets/nova/programming/vscode-datasets-add-command.webp)

The Robot Interface draws the changed path before you publish it.

Publish the routine like a pose, with `Publish` in the header of the dataset panel.

## Open points

- The extension cannot create an empty dataset. Start from a dataset file and import it.
- The `Poses` tree has no action to add the first pose to an empty dataset. Add a motion command with `New pose at current TCP` instead.
- Building a command routine in Python is not part of the Python SDK yet.
- A program cannot run a command routine yet. Routines run from the Robot Interface only.
