#### NOTE
This is a **Hugging Face dataset**. For large datasets, ensure `huggingface_hub>=1.1.3` to avoid rate limits. Learn more in the <a href="https://docs.voxel51.com/integrations/huggingface.html#loading-datasets-from-the-hub" target="_blank">Hugging Face integration docs</a>.

<a href="https://huggingface.co/datasets/Voxel51/interndata-a1-close-the-laptop-369ep" target="_blank">![Hugging Face](https://img.shields.io/badge/%F0%9F%A4%97%20Hugging%20Face-Dataset-yellow)</a>

This is a [FiftyOne](https://github.com/voxel51/fiftyone) dataset with 369 samples.

# Installation

If you haven’t already, install FiftyOne:

```bash
pip install -U fiftyone
```

# Usage

```python
import fiftyone as fo
from fiftyone.utils.huggingface import load_from_hub

# Load the dataset
# Note: other available arguments include 'max_samples', etc
dataset = load_from_hub("Voxel51/interndata-a1-close-the-laptop-369ep")

# Launch the App
session = fo.launch_app(dataset)
```

# Dataset Card for InternData-A1 close-the-laptop

![InternData-A1 close-the-laptop preview](https://huggingface.co/datasets/Voxel51/interndata-a1-close-the-laptop-369ep/resolve/main/interndata-a1-close-the-laptop.gif)

## Dataset Details

### Dataset Description

This is a 369-episode subset of the `franka-1/articulation_tasks/close_the_laptop`
task directory from
[griffinlabs/InternData-A1-LeRobot-v3.0-by-embodiment](https://huggingface.co/datasets/griffinlabs/InternData-A1-LeRobot-v3.0-by-embodiment),
itself a re-packaging of [InternRobotics/InternData-A1](https://huggingface.co/datasets/InternRobotics/InternData-A1)
with tarballs extracted and the directory structure reorganized so the top-level
directories are per-embodiment.

The source repo is not a single LeRobot dataset: it contains 1,488 independent
LeRobot v3.0 datasets, one per `<embodiment>/<task_category>/<task>[/<object_variant>]`
directory, each with its own `meta/info.json`, `data/`, and `videos/`. This subset
covers one of those 1,488 task directories: `franka-1` (a Franka arm using the
`franka-1` feature/gripper convention, one of two Franka variants in the source
repo), `articulation_tasks/close_the_laptop`. Every episode in the “shard-0” set
(episodes whose data shard and every video-stream shard are the first file,
`file_index == 0`, of `chunk-000`) was imported — 369 of the task’s 578 total
episodes, the largest complete subset obtainable without downloading every shard.

- **Curated by:** Griffin Labs (source re-packaging); this subset selected and
  exported by a FiftyOne user via the `fiftyone-lerobot-subset-to-hub` skill
- **Language(s):** English (task language instructions)
- **License:** cc-by-nc-sa-4.0 (inherited from the source repo)

### Dataset Sources

- **Repository:** https://huggingface.co/datasets/griffinlabs/InternData-A1-LeRobot-v3.0-by-embodiment
- **Original dataset:** https://huggingface.co/datasets/InternRobotics/InternData-A1

## Uses

### Direct Use

Exploring, filtering, and visualizing Franka “close the laptop” articulation
episodes in the FiftyOne App; prototyping multimodal (video + tabular state/action)
data loaders; small-scale policy debugging or overfitting tests on a single task.

### Out-of-Scope Use

Not suitable for training a policy expecting the task’s full episode coverage — this
is 369 of 578 total episodes available in the source repo for this task. Not
suitable for commercial use without checking the CC BY-NC-SA 4.0 terms. Not
representative of any embodiment or task other than a single Franka arm performing
this one articulation task.

## Dataset Structure

Media type: `multimodal`. One sample = one episode. Each sample’s `media_reference`
points to the episode’s rows in this self-contained, re-exported LeRobot v3.0
Parquet + MP4 export (re-indexed to `episode_index` `0..368`).

### Fields

| Field                             | Type                   | Meaning                                                               |
|-----------------------------------|------------------------|-----------------------------------------------------------------------|
| `id`                              | ObjectIdField          | FiftyOne sample id                                                    |
| `media_reference`                 | MediaReferenceField    | Pointer to the episode’s data/video rows in the LeRobot export        |
| `tags`                            | ListField(StringField) | FiftyOne tags (empty by default)                                      |
| `metadata`                        | EmbeddedDocumentField  | FiftyOne media metadata (unset)                                       |
| `created_at` / `last_modified_at` | DateTimeField          | FiftyOne bookkeeping                                                  |
| `episode_index`                   | IntField               | Episode index within this exported dataset                            |
| `task`                            | StringField            | Task instruction for the episode (“Close the laptop” for all samples) |
| `tasks`                           | ListField(StringField) | All task instruction strings associated with the episode              |
| `length`                          | IntField               | Number of frames in the episode                                       |
| `duration`                        | FloatField             | Episode duration in seconds (`length / fps`)                          |
| `robot_type`                      | StringField            | `Franka` for all samples                                              |
| `fps`                             | FloatField             | Recording frame rate (30.0)                                           |

`task` is a `StringField`, not a `Classification`, because in LeRobot v3 the task
instruction is a free-text string looked up per-frame via `task_index`, not a fixed
label set; all 369 episodes in this subset share the single task instruction
“Close the laptop”.

### Per-frame streams (not sample-level fields)

Per-frame video and tabular data live in the referenced Parquet/MP4 shards and appear
in the FiftyOne App’s Streams / State & Action tabs, not as top-level sample fields:

| Feature                                                                                                                                                                 | dtype   | shape           |
|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------|---------|-----------------|
| `images.rgb.head`                                                                                                                                                       | video   | `[360, 640, 3]` |
| `images.rgb.hand`                                                                                                                                                       | video   | `[480, 640, 3]` |
| `head_camera_intrinsics`                                                                                                                                                | float32 | `[4]`           |
| `hand_camera_intrinsics`                                                                                                                                                | float32 | `[4]`           |
| `head_camera_to_robot_extrinsics`                                                                                                                                       | float32 | `[7]`           |
| `hand_camera_to_robot_extrinsics`                                                                                                                                       | float32 | `[7]`           |
| `states.joint.position`, `actions.joint.position`, `master_actions.joint.position`                                                                                      | float32 | `[7]`           |
| `states.gripper.position`, `actions.gripper.position`                                                                                                                   | float32 | `[1]`           |
| `actions.gripper.openness`, `master_actions.gripper.position`, `master_actions.gripper.openness`                                                                        | float32 | `[1]`           |
| `states.gripper.pose`, `actions.gripper.pose`, `master_actions.gripper.pose`                                                                                            | float32 | `[6]`           |
| `states.ee_to_armbase_pose`, `states.ee_to_robot_pose`, `states.tcp_to_armbase_pose`, `states.tcp_to_robot_pose`, `states.robot_to_env_pose` (and matching `actions.*`) | float32 | `[7]`           |
| `observation.state`                                                                                                                                                     | float32 | `[49]`          |
| `action`                                                                                                                                                                | float32 | `[43]`          |

All declared features are `video` or standard scalar (`float32`/`int64`) dtypes, so
nothing was excluded by the FiftyOne importer.

`observation.state` and `action` are derived columns, added after import by
concatenating the `states.*` and `actions.*` components above (in the fixed order
listed in the table) into single vectors, with a `names` array labeling each
dimension (e.g. `states.joint.position[0]`, …, `states.gripper.position`, …).
FiftyOne’s App only renders its State & Action tile for features literally named
`observation.state` / `action`; InternData-A1’s native per-component naming
(`states.joint.position`, `actions.gripper.pose`, …) isn’t pattern-matched by that
tile. The original per-component columns are left untouched alongside the two new
vectors, so no information from the source is lost or duplicated-away.
`master_actions.*` (the teleop leader-arm commands, distinct from the executed
`actions.*`) was intentionally excluded from the `action` vector and is only
available via its original per-component columns.

### `dataset.info` contents

`ds.info["lerobot"]["skipped_episodes"]` is `[]`, confirming all 369 requested
episodes imported successfully.

### Parsing decisions

- **Why this task:** this repo was originally scoped as a 10-task, 5-embodiment
  “representative mix” spanning Franka, Genie-1, ARX Lift-2, and AgileX Split Aloha.
  Merging those into one Hub push turned out not to be possible: FiftyOne’s
  `LeRobotDatasetExporter` requires all exported episodes to share one `source_id`
  (raises `MediaReferenceError: LeRobotDataset export cannot mix episodes from different sources`), and even independent of that check, the LeRobot v3 format
  requires one fixed feature schema per dataset — the single-arm Franka schema
  (`images.rgb.hand`, `states.joint.position`, …) and the dual-arm Genie-1/Lift-2/
  Split-Aloha schema (`images.rgb.hand_left`/`hand_right`,
  `states.left_joint.position`/`right_joint.position`, …) are incompatible within
  one `info.json`. This repo covers just one of the original 10 candidate tasks,
  `franka-1/articulation_tasks/close_the_laptop`, as a valid, self-contained example.
- **Shard-0, not “all episodes”:** 369 of 578 total episodes for this task were
  imported — every episode whose `data/file_index` and every video stream’s
  `file_index` are `0` within `chunk-000`, the largest complete subset obtainable
  while downloading only the first Parquet/MP4 shard per stream.
- **Metadata repair applied:** the source `meta/tasks.parquet` stored the task text
  as the pandas index (columns `['task_index', '__index_level_0__']`) rather than a
  literal `task` column, which FiftyOne’s exporter requires
  (`_read_source_tasks` raised `MalformedMediaSourceError`). Repaired locally by
  rewriting the file with explicit `task_index`/`task` columns
  (`df.reset_index().rename(columns={"index": "task"})`), then re-importing this
  FiftyOne dataset from the repaired source before exporting.
- **No modalities excluded:** the task declares only `video` and standard scalar
  dtypes, so nothing was dropped by the importer.
- **Re-export re-indexing:** `episode_index` and `task_index` were local to the
  source task directory (`0..577`) before this export; the push remaps the 369
  selected episodes to a contiguous `0..368` range and recomputes aggregate stats
  over just this subset.
- **License:** unchanged from the source (`cc-by-nc-sa-4.0`, non-commercial). Per the
  source README, `franka-1` and `franka-2` (not used here) differ in image shape and
  gripper value range; this subset uses only `franka-1`.
- **`observation.state`/`action` packing:** added post-export (see Fields above) so
  the FiftyOne App’s State & Action tile — which only recognizes those two literal
  feature names — renders this dataset’s proprioception. Verified the packed vectors
  exactly reproduce the original per-component values before pushing.

## Dataset Creation

### Curation Rationale

To provide a small, self-contained, browsable FiftyOne/LeRobot v3 export of a single
Franka articulation task from the very large (2.1 TB, 1,488-task) InternData-A1-
LeRobot-v3.0-by-embodiment collection.

### Source Data

#### Data Collection and Processing

Per the source repo’s card, InternData-A1 was reorganized from
[InternRobotics/InternData-A1](https://huggingface.co/datasets/InternRobotics/InternData-A1)
by extracting the original tarballs and “transposing” the directory structure so the
top-level directories are the embodiments. This FiftyOne subset further selected the
`franka-1/articulation_tasks/close_the_laptop` task directory, imported its shard-0
episode set after repairing `meta/tasks.parquet`, and re-exported as a
self-contained LeRobot v3.0 repository with episodes re-indexed to `0..368`.

### Annotations

#### Annotation process

The task instruction (“Close the laptop”) is a free-text string provided in the
source `meta/tasks.parquet`; no additional annotation was added for this subset.

## Dataset Card Authors

[Harpreet Sahota](https://huggingface.co/harpreetsahota)

## Dataset Card Contact

[Harpreet Sahota](https://huggingface.co/harpreetsahota)
