diff --git a/README.md b/README.md index 4625b2c..ea5679e 100644 --- a/README.md +++ b/README.md @@ -2230,6 +2230,22 @@ history = client.import_robotics_contents_file( ) ``` +#### Import mcap + +Import an mcap zip file into an existing robotics task. + +This method uploads the zip file and starts the import. The import runs **asynchronously** on the server, so the call returns as soon as the import is accepted — it does **not** wait for the import to finish. + +```python +result = client.import_robotics_mcap( + project="YOUR_PROJECT_SLUG", + task_id="YOUR_TASK_ID", + file_path="ZIP_FILE_PATH", # Supported extension is .zip +) +``` + +There is no API to poll the import progress. Check the import status (and any errors) on the import history screen (`/imports`) in the FastLabel application. + #### Import LeRobot Dataset Import a [LeRobot](https://github.com/huggingface/lerobot) dataset (v3) into a FastLabel robotics project. diff --git a/examples/import_robotics_mcap.py b/examples/import_robotics_mcap.py new file mode 100644 index 0000000..f185be0 --- /dev/null +++ b/examples/import_robotics_mcap.py @@ -0,0 +1,19 @@ +""" +Import an mcap zip file into an existing FastLabel robotics task. + +This starts an import pipeline, uploads the zip via a signed URL, +and triggers the batch import. +""" + +from pprint import pprint + +import fastlabel + +client = fastlabel.Client() + +result = client.import_robotics_mcap( + project="YOUR_PROJECT_SLUG", + task_id="YOUR_TASK_ID", + file_path="ZIP_FILE_PATH", # Supported extension is .zip +) +pprint(result) diff --git a/fastlabel/__init__.py b/fastlabel/__init__.py index 0155359..8969895 100644 --- a/fastlabel/__init__.py +++ b/fastlabel/__init__.py @@ -2451,6 +2451,55 @@ def import_robotics_contents_file( return self.api.post_request(endpoint, payload=payload) + def import_robotics_mcap(self, project: str, task_id: str, file_path: str) -> dict: + """ + Import robotics mcap zip file. + project is slug of your project (Required). + task_id is a id of the robotics task to import contents (Required). + file_path is a path to data. Supported extensions are zip (Required). + """ + if not file_path.endswith(".zip"): + raise FastLabelInvalidException( + "Supported extensions are zip (Required).", 422 + ) + history_id = self._start_pipeline(project=project, task_id=task_id) + self._upload_zip_with_signed_url( + history_id=history_id, + file_path=file_path, + ) + return self._trigger_batch_import(history_id=history_id) + + def _start_pipeline( + self, + project: str, + task_id: str, + ) -> str: + history: dict = self.api.post_request( + "data-lake/robotics/import-pipeline/start", + payload={ + "project": project, + "taskId": task_id, + }, + ) + logger.info(f"Started data lake pipeline with history ID: {history['id']}") + return history["id"] + + def _upload_zip_with_signed_url(self, history_id: str, file_path: str) -> None: + signed_url_data = self.api.get_request( + "data-lake/robotics/import-pipeline/signed-url", + params={"historyId": history_id}, + ) + res = self.api.upload_zipfile(url=signed_url_data["url"], file_path=file_path) + res.raise_for_status() + + def _trigger_batch_import(self, history_id: str) -> dict: + return self.api.post_request( + "data-lake/robotics/import-pipeline/run", + payload={ + "historyId": history_id, + }, + ) + # Task Update def update_task(