mirror of
https://github.com/huggingface/lerobot.git
synced 2026-07-01 15:17:05 +00:00
3dd19d043e
* feat(depth): add depth quantization helpers and tests
* feat(video): add ffv1 to supported codecs
* feat(depth): persist depth metadata
* feat(depth): extend quantization tools to better fit the encoding/decoding pipeline
* feat(depth): plumb DepthEncoderConfig through LeRobotDataset and DatasetWriter
* feat(depth): wire StreamingVideoEncoder + writer to depth encoder
* feat(depth): wire DatasetReader to decode_depth_frames
* feat(cameras/realsense): expose async depth in metric meters
* feat(features): route 2D camera shapes to observation.depth.<key>
* feat(robots/so_follower): emit + populate depth keys when use_depth
* feat(record): plumb DepthEncoderConfig through lerobot-record
* feat(viz): render depth observations as rr.DepthImage in Viridis
* feat(depth maps writer): adding support for raw depth maps recording with image writer
* chore(format): format code
* feat(depth shape): ensuring depth maps shape is always including the channel
* feat(is_depth): simplifying is_depth nested name + legacy support
* fix(stop_event): fixing stop_event race condition in camera classes
* fix(plumbing): fixing missing parts in the depth maps pipeline
* chore(typos): fixing typos
* test(fix): fixing exisiting tests to still work with latest features
* tests(depth): adding new tests for depth integration validation
* feat(pix_fmt channels): use PyAv to check get pixel formats number of channels
* feat(refactor): refactor DepthEncoderConfig quantization pipeline, so that the methods do not live in the config class. Add pixel format - channels validation.Move the default pixel format for depth in the config file.
* fix(pre-commit): fixing mutable defautl value
* fix(info): fixing info metadata update when is_depth_map was set
* tests(typos): fixing typos in tests
* fix(realsense): fixing typo in realsense serial number
* fix(normalization): restricting 255 normalization to non depth/uint8 images only
* fix(typo): fixing typo
* fix(TIFF): add missing quantization and cleanup for TIFF files
* feat(batched dequantization): optimizing dequantize_depth for torch based batched dequantization
* feat(tools): adding depth support in LeRobotDataset edition tools
* test(aggregate): extending aggregation tests to depth frames
* test(cleaning): cleaning up tests
* fix(from_video_info): fixing early validation issue in from_video_info
* fix(typo): fixing typo
* fix(is_depth): adding missing doctrings and is_depth arguments in video decoding functions
Co-authored-by: Wensi (Vince) Ai <59036629+wensi-ai@users.noreply.github.com>
* fix(depth units): fixing depth units output for the realsense cameras
* feat(output unit): adding support for output unit specification at dataset reading/training time
Co-authored-by: Wensi (Vince) Ai <59036629+wensi-ai@users.noreply.github.com>
* test(depth): cleaning up depth tests
* test(depth encoding): updating and cleaning video/depth encoding tests
* chore(format): formatting code
* docs(depth): improving depth maps docs
* test(fix): fixing depth tests
* test(dataset tools): adding missing tests for new dataset edition tools features
* chore(format): formatting code
* fix(pyav check): fixing PyAV option validation for integer codec options by normalizing
numeric values before calling `is_integer()`
Co-authored-by: Wensi (Vince) Ai <59036629+wensi-ai@users.noreply.github.com>
* docs(mermaid): fixing mermaid diagram
* fix(rebase): rebase follow up corrections
* feat(dataset tools): adding missing docstrings and features for depth fill support in dataset edition tools
* docs(docstring): updating docstrings
* docs(dataset tools): updating docs
* fix(save images): fixing image saving in dataset tools
* fix(update video info): fixing update video info logic to match the recording and editing use cases
* test(reencode): fixing reencoding monkeypatch
* fix(review): add Claude review
* chore(format): format code
* fix(update video info): ditching the differentiated approahces for video info update - video info are always updated unless for preserved keys.
* chore(rebase): fixing rebase merge conflicts
* test(visualization): fixing visualization tests
* feat(docstrings): adding explicit docstring for encoding parameters. Docstrigns will now show up as description in the CLI --help.
* feat(mm as default): adding a global DEFAULT_DEPTH_UNIT variable setting mm as default depth unit
* fix(RGB <-> camera): renaming camera_encoder to rgb_encoder for clarity
* chore(TODO): removing deprecated TODO
* doc(write_u16_plane): improving docstrings for write_u16_plane
* feat(units): adding constants for depth frames units (m and mm)
* fix(spam): replacing spamming warning but a debug log
* feat(leagcy metadata): adding automatic metadata update for legacy 'video.is_depth_map' feature
* fix(copy&reindex): fixing metadat reshaping for single channel frames
* fix(ImageNet): excluding dpeth frames from ImageNet stats
* fix(PyAV container seek): fixing initial PyAV container seek to be robust againsy codec choice
* feat(lerobot-dataset-viz): adding support for depth in lerobot-dataset-viz
* fix(compress): removing rerun compression for DepthImages
* fix(signle channel squeeze): fixing single channel squeezing
* chore(format): format code
* fix(streaming): adding support for dequantization in streaming_dataset.py
* refactor(read depth): factorizing depth reading methods for realsense camera and adding support for depth-only usage
* chore(renaming): fixing missed RGBEncoderConfig renamings
* docs(renaming): reflecting renamings in a clearer way in the docs
* chore(annotation): excluding depth from the annotation pipeline
* feat(robots): adding depth support in compatible follower robots
* feat(LeSadKiwi): excluding LeKiwi from depth support (for now)
* chore(fail): removing misplaced file
* chore(fail): removing misplaced file
* fix(remove ffv1): removing ffv1 as it does not support MP4
* docs(cheat sheet): adding depth and video encoding to the cheat sheet
* fix(lossless): tuning depth encoding parameters for lossless depth storage
* test(fix): fixing failing tests
* depth(ZMQ): excluding ZMQ from depth support
* Revert "depth(ZMQ): excluding ZMQ from depth support"
This reverts commit b95cf4e4c2.
* fix(image transforms): excluding depth frames from images transforms
* fix(typo): typo
* fix(stats): fixing stats computation for depth frames
* fix(TIFF vs. pytorch): adding an extra uint16 to float32 conversion for depth maps stored as raw TIFF images
* fix(typos): fixing typos
* test(dtype): fixing stats computation typing tests
---------
Signed-off-by: Steven Palma <imstevenpmwork@ieee.org>
Co-authored-by: Wensi (Vince) Ai <59036629+wensi-ai@users.noreply.github.com>
Co-authored-by: Steven Palma <imstevenpmwork@ieee.org>
Co-authored-by: Wensi Ai <wsai@stanford.edu>
284 lines
8.6 KiB
Plaintext
284 lines
8.6 KiB
Plaintext
# HopeJR
|
|
|
|
## Prerequisites
|
|
|
|
- [Hardware Setup](https://github.com/TheRobotStudio/HOPEJr)
|
|
|
|
## Install LeRobot
|
|
|
|
Follow the [installation instructions](https://github.com/huggingface/lerobot#installation) to install LeRobot.
|
|
|
|
Install LeRobot with HopeJR dependencies:
|
|
|
|
```bash
|
|
pip install -e ".[hopejr]"
|
|
```
|
|
|
|
## Device Configuration
|
|
|
|
Before starting calibration and operation, you need to identify the USB ports for each HopeJR component. Run this script to find the USB ports for the arm, hand, glove, and exoskeleton:
|
|
|
|
```bash
|
|
lerobot-find-port
|
|
```
|
|
|
|
This will display the available USB ports and their associated devices. Make note of the port paths (e.g., `/dev/tty.usbmodem58760433331`, `/dev/tty.usbmodem11301`) as you'll need to specify them in the `--robot.port` and `--teleop.port` parameters when recording data, replaying episodes, or running teleoperation scripts.
|
|
|
|
## Step 1: Calibration
|
|
|
|
Before performing teleoperation, HopeJR's limbs need to be calibrated. Calibration files will be saved in `~/.cache/huggingface/lerobot/calibration`
|
|
|
|
### 1.1 Calibrate Robot Hand
|
|
|
|
```bash
|
|
lerobot-calibrate \
|
|
--robot.type=hope_jr_hand \
|
|
--robot.port=/dev/tty.usbmodem58760432281 \
|
|
--robot.id=blue \
|
|
--robot.side=right
|
|
```
|
|
|
|
When running the calibration script, a calibration GUI will pop up. Finger joints are named as follows:
|
|
|
|
**Thumb**:
|
|
|
|
- **CMC**: base joint connecting thumb to hand
|
|
- **MCP**: knuckle joint
|
|
- **PIP**: first finger joint
|
|
- **DIP** : fingertip joint
|
|
|
|
**Index, Middle, Ring, and Pinky fingers**:
|
|
|
|
- **Radial flexor**: Moves base of finger towards the thumb
|
|
- **Ulnar flexor**: Moves base of finger towards the pinky
|
|
- **PIP/DIP**: Flexes the distal and proximal phalanx of the finger
|
|
|
|
Each one of these will need to be calibrated individually via the GUI.
|
|
Note that ulnar and radial flexors should have ranges of the same size (but with different offsets) in order to get symmetric movement.
|
|
|
|
<p align="center">
|
|
<img
|
|
src="https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/lerobot/calibration_gui_1.png"
|
|
alt="Setting boundaries in the hand calibration GUI"
|
|
title="Setting boundaries in the hand calibration GUI"
|
|
width="100%"
|
|
></img>
|
|
</p>
|
|
|
|
Use the calibration interface to set the range boundaries for each joint as shown above.
|
|
|
|
<p align="center">
|
|
<img
|
|
src="https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/lerobot/calibration_gui_2.png"
|
|
alt="Saving calibration values"
|
|
title="Saving calibration values"
|
|
width="100%"
|
|
></img>
|
|
</p>
|
|
|
|
Once you have set the appropriate boundaries for all joints, click "Save" to save the calibration values to the motors.
|
|
|
|
### 1.2 Calibrate Teleoperator Glove
|
|
|
|
```bash
|
|
lerobot-calibrate \
|
|
--teleop.type=homunculus_glove \
|
|
--teleop.port=/dev/tty.usbmodem11201 \
|
|
--teleop.id=red \
|
|
--teleop.side=right
|
|
```
|
|
|
|
Move each finger through its full range of motion, starting from the thumb.
|
|
|
|
```
|
|
Move thumb through its entire range of motion.
|
|
Recording positions. Press ENTER to stop...
|
|
|
|
-------------------------------------------
|
|
NAME | MIN | POS | MAX
|
|
thumb_cmc | 1790 | 1831 | 1853
|
|
thumb_mcp | 1497 | 1514 | 1528
|
|
thumb_pip | 1466 | 1496 | 1515
|
|
thumb_dip | 1463 | 1484 | 1514
|
|
```
|
|
|
|
Continue with each finger:
|
|
|
|
```
|
|
Move middle through its entire range of motion.
|
|
Recording positions. Press ENTER to stop...
|
|
|
|
-------------------------------------------
|
|
NAME | MIN | POS | MAX
|
|
middle_mcp_abduction | 1598 | 1718 | 1820
|
|
middle_mcp_flexion | 1512 | 1658 | 2136
|
|
middle_dip | 1484 | 1500 | 1547
|
|
```
|
|
|
|
Once calibration is complete, the system will save the calibration to `/Users/your_username/.cache/huggingface/lerobot/calibration/teleoperators/homunculus_glove/red.json`
|
|
|
|
### 1.3 Calibrate Robot Arm
|
|
|
|
```bash
|
|
lerobot-calibrate \
|
|
--robot.type=hope_jr_arm \
|
|
--robot.port=/dev/tty.usbserial-1110 \
|
|
--robot.id=white
|
|
```
|
|
|
|
This will open a calibration GUI where you can set the range limits for each motor. The arm motions are organized as follows:
|
|
|
|
- **Shoulder**: pitch, yaw, and roll
|
|
- **Elbow**: flex
|
|
- **Wrist**: pitch, yaw, and roll
|
|
|
|
<p align="center">
|
|
<img
|
|
src="https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/lerobot/calibration_gui_2.png"
|
|
alt="Setting boundaries in the arm calibration GUI"
|
|
title="Setting boundaries in the arm calibration GUI"
|
|
width="100%"
|
|
></img>
|
|
</p>
|
|
|
|
Use the calibration interface to set the range boundaries for each joint. Move each joint through its full range of motion and adjust the minimum and maximum values accordingly. Once you have set the appropriate boundaries for all joints, save the calibration.
|
|
|
|
### 1.4 Calibrate Teleoperator Exoskeleton
|
|
|
|
```bash
|
|
lerobot-calibrate \
|
|
--teleop.type=homunculus_arm \
|
|
--teleop.port=/dev/tty.usbmodem11201 \
|
|
--teleop.id=black
|
|
```
|
|
|
|
The exoskeleton allows one to control the robot arm. During calibration, you'll be prompted to move all joints through their full range of motion:
|
|
|
|
```
|
|
Move all joints through their entire range of motion.
|
|
Recording positions. Press ENTER to stop...
|
|
|
|
-------------------------------------------
|
|
-------------------------------------------
|
|
NAME | MIN | POS | MAX
|
|
shoulder_pitch | 586 | 736 | 895
|
|
shoulder_yaw | 1257 | 1374 | 1390
|
|
shoulder_roll | 449 | 1034 | 2564
|
|
elbow_flex | 3023 | 3117 | 3134
|
|
wrist_roll | 3073 | 3096 | 3147
|
|
wrist_yaw | 2143 | 2171 | 2185
|
|
wrist_pitch | 1975 | 1993 | 2074
|
|
Calibration saved to /Users/your_username/.cache/huggingface/lerobot/calibration/teleoperators/homunculus_arm/black.json
|
|
```
|
|
|
|
## Step 2: Teleoperation
|
|
|
|
Due to global variable conflicts in the Feetech middleware, teleoperation for arm and hand must run in separate shell sessions:
|
|
|
|
### Hand
|
|
|
|
```bash
|
|
lerobot-teleoperate \
|
|
--robot.type=hope_jr_hand \
|
|
--robot.port=/dev/tty.usbmodem58760432281 \
|
|
--robot.id=blue \
|
|
--robot.side=right \
|
|
--teleop.type=homunculus_glove \
|
|
--teleop.port=/dev/tty.usbmodem11201 \
|
|
--teleop.id=red \
|
|
--teleop.side=right \
|
|
--display_data=true \
|
|
--fps=30
|
|
```
|
|
|
|
### Arm
|
|
|
|
```bash
|
|
lerobot-teleoperate \
|
|
--robot.type=hope_jr_arm \
|
|
--robot.port=/dev/tty.usbserial-1110 \
|
|
--robot.id=white \
|
|
--teleop.type=homunculus_arm \
|
|
--teleop.port=/dev/tty.usbmodem11201 \
|
|
--teleop.id=black \
|
|
--display_data=true \
|
|
--fps=30
|
|
```
|
|
|
|
## Step 3: Record, Replay, Train
|
|
|
|
Record, Replay and Train with Hope-JR is still experimental.
|
|
|
|
### Record
|
|
|
|
This step records the dataset, which can be seen as an example [here](https://huggingface.co/datasets/nepyope/hand_record_test_with_video_data/settings).
|
|
|
|
```bash
|
|
lerobot-record \
|
|
--robot.type=hope_jr_hand \
|
|
--robot.port=/dev/tty.usbmodem58760432281 \
|
|
--robot.id=right \
|
|
--robot.side=right \
|
|
--robot.cameras='{"main": {"type": "opencv", "index_or_path": 0, "width": 640, "height": 480, "fps": 30}}' \
|
|
--teleop.type=homunculus_glove \
|
|
--teleop.port=/dev/tty.usbmodem1201 \
|
|
--teleop.id=right \
|
|
--teleop.side=right \
|
|
--dataset.repo_id=<USER>/hand_record_test_with_video_data \
|
|
--dataset.single_task="Hand recording test with video data" \
|
|
--dataset.num_episodes=1 \
|
|
--dataset.episode_time_s=5 \
|
|
--dataset.push_to_hub=true \
|
|
--dataset.private=true \
|
|
--dataset.streaming_encoding=true \
|
|
--dataset.encoder_threads=2 \
|
|
# --dataset.rgb_encoder.vcodec=auto \
|
|
--display_data=true
|
|
```
|
|
|
|
### Replay
|
|
|
|
```bash
|
|
lerobot-replay \
|
|
--robot.type=hope_jr_hand \
|
|
--robot.port=/dev/tty.usbmodem58760432281 \
|
|
--robot.id=right \
|
|
--robot.side=right \
|
|
--dataset.repo_id=<USER>/hand_record_test_with_camera \
|
|
--dataset.episode=0
|
|
```
|
|
|
|
### Train
|
|
|
|
```bash
|
|
lerobot-train \
|
|
--dataset.repo_id=<USER>/hand_record_test_with_video_data \
|
|
--policy.type=act \
|
|
--output_dir=outputs/train/hopejr_hand \
|
|
--job_name=hopejr \
|
|
--policy.device=mps \
|
|
--wandb.enable=true \
|
|
--policy.repo_id=<USER>/hand_test_policy
|
|
```
|
|
|
|
### Evaluate
|
|
|
|
This training run can be viewed as an example [here](https://wandb.ai/tino/lerobot/runs/rp0k8zvw?nw=nwusertino).
|
|
|
|
```bash
|
|
lerobot-record \
|
|
--robot.type=hope_jr_hand \
|
|
--robot.port=/dev/tty.usbmodem58760432281 \
|
|
--robot.id=right \
|
|
--robot.side=right \
|
|
--robot.cameras='{"main": {"type": "opencv", "index_or_path": 0, "width": 640, "height": 480, "fps": 30}}' \
|
|
--display_data=false \
|
|
--dataset.repo_id=<USER>/eval_hopejr \
|
|
--dataset.single_task="Evaluate hopejr hand policy" \
|
|
--dataset.num_episodes=10 \
|
|
--dataset.streaming_encoding=true \
|
|
--dataset.encoder_threads=2 \
|
|
# --dataset.rgb_encoder.vcodec=auto \
|
|
--policy.path=outputs/train/hopejr_hand/checkpoints/last/pretrained_model
|
|
```
|