mirror of
https://github.com/huggingface/lerobot.git
synced 2026-05-21 03:30:10 +00:00
docs(cameras): revising and improving docs on cameras (#2878)
* docs(cameras): revising and improving docs on cameras * resolving copilot comments
This commit is contained in:
@@ -7,8 +7,6 @@
|
|||||||
- sections:
|
- sections:
|
||||||
- local: il_robots
|
- local: il_robots
|
||||||
title: Imitation Learning for Robots
|
title: Imitation Learning for Robots
|
||||||
- local: cameras
|
|
||||||
title: Cameras
|
|
||||||
- local: bring_your_own_policies
|
- local: bring_your_own_policies
|
||||||
title: Bring Your Own Policies
|
title: Bring Your Own Policies
|
||||||
- local: integrate_hardware
|
- local: integrate_hardware
|
||||||
@@ -108,6 +106,10 @@
|
|||||||
- local: phone_teleop
|
- local: phone_teleop
|
||||||
title: Phone
|
title: Phone
|
||||||
title: "Teleoperators"
|
title: "Teleoperators"
|
||||||
|
- sections:
|
||||||
|
- local: cameras
|
||||||
|
title: Cameras
|
||||||
|
title: "Sensors"
|
||||||
- sections:
|
- sections:
|
||||||
- local: torch_accelerators
|
- local: torch_accelerators
|
||||||
title: PyTorch accelerators
|
title: PyTorch accelerators
|
||||||
|
|||||||
+95
-81
@@ -1,12 +1,22 @@
|
|||||||
# Cameras
|
# Cameras
|
||||||
|
|
||||||
LeRobot offers multiple options for video capture, including phone cameras, built-in laptop cameras, external webcams, and Intel RealSense cameras. To efficiently record frames from most cameras, you can use either the `OpenCVCamera` or `RealSenseCamera` class. For additional compatibility details on the `OpenCVCamera` class, refer to the [Video I/O with OpenCV Overview](https://docs.opencv.org/4.x/d0/da7/videoio_overview.html).
|
LeRobot offers multiple options for video capture:
|
||||||
|
|
||||||
### Finding your camera
|
| Class | Supported Cameras |
|
||||||
|
| ----------------- | ----------------------------------- |
|
||||||
|
| `OpenCVCamera` | Phone, built-in laptop, USB webcams |
|
||||||
|
| `ZMQCamera` | Network-connected cameras |
|
||||||
|
| `RealSenseCamera` | Intel RealSense (with depth) |
|
||||||
|
| `Reachy2Camera` | Reachy 2 robot cameras |
|
||||||
|
|
||||||
To instantiate a camera, you need a camera identifier. This identifier might change if you reboot your computer or re-plug your camera, a behavior mostly dependant on your operating system.
|
> [!TIP]
|
||||||
|
> For `OpenCVCamera` compatibility details, see the [Video I/O with OpenCV Overview](https://docs.opencv.org/4.x/d0/da7/videoio_overview.html).
|
||||||
|
|
||||||
To find the camera indices of the cameras plugged into your system, run the following script:
|
### Find your camera
|
||||||
|
|
||||||
|
Every camera requires a unique identifier to be instantiated, allowing you to distinguish between multiple connected devices.
|
||||||
|
|
||||||
|
`OpenCVCamera` and `RealSenseCamera` support auto-discovery. Run the command below to list available devices and their identifiers. Note that these identifiers may change after rebooting your computer or re-plugging the camera, depending on your operating system.
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
lerobot-find-cameras opencv # or realsense for Intel Realsense cameras
|
lerobot-find-cameras opencv # or realsense for Intel Realsense cameras
|
||||||
@@ -14,7 +24,7 @@ lerobot-find-cameras opencv # or realsense for Intel Realsense cameras
|
|||||||
|
|
||||||
The output will look something like this if you have two cameras connected:
|
The output will look something like this if you have two cameras connected:
|
||||||
|
|
||||||
```
|
```bash
|
||||||
--- Detected Cameras ---
|
--- Detected Cameras ---
|
||||||
Camera #0:
|
Camera #0:
|
||||||
Name: OpenCV Camera @ 0
|
Name: OpenCV Camera @ 0
|
||||||
@@ -33,13 +43,37 @@ Camera #0:
|
|||||||
> [!WARNING]
|
> [!WARNING]
|
||||||
> When using Intel RealSense cameras in `macOS`, you could get this [error](https://github.com/IntelRealSense/librealsense/issues/12307): `Error finding RealSense cameras: failed to set power state`, this can be solved by running the same command with `sudo` permissions. Note that using RealSense cameras in `macOS` is unstable.
|
> When using Intel RealSense cameras in `macOS`, you could get this [error](https://github.com/IntelRealSense/librealsense/issues/12307): `Error finding RealSense cameras: failed to set power state`, this can be solved by running the same command with `sudo` permissions. Note that using RealSense cameras in `macOS` is unstable.
|
||||||
|
|
||||||
## Use Cameras
|
`ZMQCamera` and `Reachy2Camera` do not support auto-discovery. They must be configured manually by providing their network address and port or robot SDK settings.
|
||||||
|
|
||||||
Below are two examples, demonstrating how to work with the API.
|
## Use cameras
|
||||||
|
|
||||||
- **Asynchronous frame capture** using an OpenCV-based camera
|
### Frame access modes
|
||||||
|
|
||||||
|
All camera classes implement three access modes for capturing frames:
|
||||||
|
|
||||||
|
| Method | Behavior | Blocks? | Best For |
|
||||||
|
| ------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------- | ---------------------------------------- |
|
||||||
|
| `read()` | Waits for the camera hardware to return a frame. May block for a long time depending on the camera and SDK. | Yes | Simple scripts, sequential capture |
|
||||||
|
| `async_read(timeout_ms)` | Returns the latest unconsumed frame from background thread. Blocks only if buffer is empty, up to `timeout_ms`. Raises `TimeoutError` if no frame arrives. | With a timeout | Control loops synchronized to camera FPS |
|
||||||
|
| `read_latest(max_age_ms)` | Peeks at the most recent frame in buffer (may be stale). Raises `TimeoutError` if frame is older than `max_age_ms`. | No | UI visualization, logging, monitoring |
|
||||||
|
|
||||||
|
### Usage examples
|
||||||
|
|
||||||
|
The following examples show how to use the camera API to configure and capture frames from different camera types.
|
||||||
|
|
||||||
|
- **Blocking and non-blocking frame capture** using an OpenCV-based camera
|
||||||
- **Color and depth capture** using an Intel RealSense camera
|
- **Color and depth capture** using an Intel RealSense camera
|
||||||
|
|
||||||
|
> [!WARNING]
|
||||||
|
> Failing to cleanly disconnect cameras can cause resource leaks. Use the context manager protocol to ensure automatic cleanup:
|
||||||
|
>
|
||||||
|
> ```python
|
||||||
|
> with OpenCVCamera(config) as camera:
|
||||||
|
> ...
|
||||||
|
> ```
|
||||||
|
>
|
||||||
|
> You can also call `connect()` and `disconnect()` manually, but always use a `finally` block for the latter.
|
||||||
|
|
||||||
<hfoptions id="shell_restart">
|
<hfoptions id="shell_restart">
|
||||||
<hfoption id="Open CV Camera">
|
<hfoption id="Open CV Camera">
|
||||||
|
|
||||||
@@ -60,16 +94,30 @@ config = OpenCVCameraConfig(
|
|||||||
)
|
)
|
||||||
|
|
||||||
# Instantiate and connect an `OpenCVCamera`, performing a warm-up read (default).
|
# Instantiate and connect an `OpenCVCamera`, performing a warm-up read (default).
|
||||||
camera = OpenCVCamera(config)
|
with OpenCVCamera(config) as camera:
|
||||||
camera.connect()
|
|
||||||
|
# Read a frame synchronously — blocks until hardware delivers a new frame
|
||||||
|
frame = camera.read()
|
||||||
|
print(f"read() call returned frame with shape:", frame.shape)
|
||||||
|
|
||||||
|
# Read a frame asynchronously with a timeout — returns the latest unconsumed frame or waits up to timeout_ms for a new one
|
||||||
|
try:
|
||||||
|
for i in range(10):
|
||||||
|
frame = camera.async_read(timeout_ms=200)
|
||||||
|
print(f"async_read call returned frame {i} with shape:", frame.shape)
|
||||||
|
except TimeoutError as e:
|
||||||
|
print(f"No frame received within timeout: {e}")
|
||||||
|
|
||||||
|
# Instantly return a frame - returns the most recent frame captured by the camera
|
||||||
|
try:
|
||||||
|
initial_frame = camera.read_latest(max_age_ms=1000)
|
||||||
|
for i in range(10):
|
||||||
|
frame = camera.read_latest(max_age_ms=1000)
|
||||||
|
print(f"read_latest call returned frame {i} with shape:", frame.shape)
|
||||||
|
print(f"Was a new frame received by the camera? {not (initial_frame == frame).any()}")
|
||||||
|
except TimeoutError as e:
|
||||||
|
print(f"Frame too old: {e}")
|
||||||
|
|
||||||
# Read frames asynchronously in a loop via `async_read(timeout_ms)`
|
|
||||||
try:
|
|
||||||
for i in range(10):
|
|
||||||
frame = camera.async_read(timeout_ms=200)
|
|
||||||
print(f"Async frame {i} shape:", frame.shape)
|
|
||||||
finally:
|
|
||||||
camera.disconnect()
|
|
||||||
```
|
```
|
||||||
<!-- prettier-ignore-end -->
|
<!-- prettier-ignore-end -->
|
||||||
|
|
||||||
@@ -111,10 +159,10 @@ finally:
|
|||||||
</hfoption>
|
</hfoption>
|
||||||
</hfoptions>
|
</hfoptions>
|
||||||
|
|
||||||
## Use your phone
|
## Use your phone's camera
|
||||||
|
|
||||||
<hfoptions id="use phone">
|
<hfoptions id="use phone">
|
||||||
<hfoption id="Mac">
|
<hfoption id="iPhone & macOS">
|
||||||
|
|
||||||
To use your iPhone as a camera on macOS, enable the Continuity Camera feature:
|
To use your iPhone as a camera on macOS, enable the Continuity Camera feature:
|
||||||
|
|
||||||
@@ -124,83 +172,49 @@ To use your iPhone as a camera on macOS, enable the Continuity Camera feature:
|
|||||||
|
|
||||||
For more details, visit [Apple support](https://support.apple.com/en-gb/guide/mac-help/mchl77879b8a/mac).
|
For more details, visit [Apple support](https://support.apple.com/en-gb/guide/mac-help/mchl77879b8a/mac).
|
||||||
|
|
||||||
Your iPhone should be detected automatically when running the camera setup script in the next section.
|
|
||||||
|
|
||||||
</hfoption>
|
</hfoption>
|
||||||
<hfoption id="Linux">
|
<hfoption id="OBS virtual camera">
|
||||||
|
|
||||||
If you want to use your phone as a camera on Linux, follow these steps to set up a virtual camera
|
If you want to use your phone as a camera using OBS, follow these steps to set up a virtual camera.
|
||||||
|
|
||||||
1. _Install `v4l2loopback-dkms` and `v4l-utils`_. Those packages are required to create virtual camera devices (`v4l2loopback`) and verify their settings with the `v4l2-ctl` utility from `v4l-utils`. Install them using:
|
1. _(Linux only) Install `v4l2loopback-dkms` and `v4l-utils`_. These packages create virtual camera devices and verify their settings. Install with:
|
||||||
|
|
||||||
<!-- prettier-ignore-start -->
|
```bash
|
||||||
```python
|
|
||||||
sudo apt install v4l2loopback-dkms v4l-utils
|
sudo apt install v4l2loopback-dkms v4l-utils
|
||||||
```
|
```
|
||||||
<!-- prettier-ignore-end -->
|
|
||||||
|
|
||||||
2. _Install [DroidCam](https://droidcam.app) on your phone_. This app is available for both iOS and Android.
|
2. _Install the [DroidCam app](https://droidcam.app) on your phone_. This app is available for both iOS and Android.
|
||||||
3. _Install [OBS Studio](https://obsproject.com)_. This software will help you manage the camera feed. Install it using [Flatpak](https://flatpak.org):
|
3. _Download and install [OBS Studio](https://obsproject.com)_.
|
||||||
|
4. _Download and install the [DroidCam OBS plugin](https://droidcam.app/obs)_.
|
||||||
|
5. _Start OBS Studio_.
|
||||||
|
|
||||||
<!-- prettier-ignore-start -->
|
6. _Add your phone as a source_. Follow the instructions [here](https://droidcam.app/obs/usage). Be sure to set the resolution to `640x480` to avoid the watermarks.
|
||||||
```python
|
7. _Adjust resolution settings_. In OBS Studio, go to `File > Settings > Video` or `OBS > Preferences... > Video`. Change the `Base(Canvas) Resolution` and the `Output(Scaled) Resolution` to `640x480` by manually typing it.
|
||||||
flatpak install flathub com.obsproject.Studio
|
|
||||||
```
|
|
||||||
<!-- prettier-ignore-end -->
|
|
||||||
|
|
||||||
4. _Install the DroidCam OBS plugin_. This plugin integrates DroidCam with OBS Studio. Install it with:
|
|
||||||
|
|
||||||
<!-- prettier-ignore-start -->
|
|
||||||
```python
|
|
||||||
flatpak install flathub com.obsproject.Studio.Plugin.DroidCam
|
|
||||||
```
|
|
||||||
<!-- prettier-ignore-end -->
|
|
||||||
|
|
||||||
5. _Start OBS Studio_. Launch with:
|
|
||||||
|
|
||||||
<!-- prettier-ignore-start -->
|
|
||||||
```python
|
|
||||||
flatpak run com.obsproject.Studio
|
|
||||||
```
|
|
||||||
<!-- prettier-ignore-end -->
|
|
||||||
|
|
||||||
6. _Add your phone as a source_. Follow the instructions [here](https://droidcam.app/obs/usage). Be sure to set the resolution to `640x480`.
|
|
||||||
7. _Adjust resolution settings_. In OBS Studio, go to `File > Settings > Video`. Change the `Base(Canvas) Resolution` and the `Output(Scaled) Resolution` to `640x480` by manually typing it in.
|
|
||||||
8. _Start virtual camera_. In OBS Studio, follow the instructions [here](https://obsproject.com/kb/virtual-camera-guide).
|
8. _Start virtual camera_. In OBS Studio, follow the instructions [here](https://obsproject.com/kb/virtual-camera-guide).
|
||||||
9. _Verify the virtual camera setup_. Use `v4l2-ctl` to list the devices:
|
9. _Verify the virtual camera setup and resolution_.
|
||||||
|
- **Linux**: Use `v4l2-ctl` to list devices and check resolution:
|
||||||
|
```bash
|
||||||
|
v4l2-ctl --list-devices # find VirtualCam and note its /dev/videoX path
|
||||||
|
v4l2-ctl -d /dev/videoX --get-fmt-video # replace with your VirtualCam path
|
||||||
|
```
|
||||||
|
You should see `VirtualCam` listed and resolution `640x480`.
|
||||||
|
- **macOS**: Open Photo Booth or FaceTime and select "OBS Virtual Camera" as the input.
|
||||||
|
- **Windows**: The native Camera app doesn't support virtual cameras. Use a video conferencing app (Zoom, Teams) or run `lerobot-find-cameras opencv` directly to verify.
|
||||||
|
|
||||||
<!-- prettier-ignore-start -->
|
<details>
|
||||||
```python
|
<summary><strong>Troubleshooting</strong></summary>
|
||||||
v4l2-ctl --list-devices
|
|
||||||
```
|
|
||||||
<!-- prettier-ignore-end -->
|
|
||||||
|
|
||||||
You should see an entry like:
|
> The virtual camera resolution is incorrect.
|
||||||
|
|
||||||
```
|
Delete the virtual camera source and recreate it. The resolution cannot be changed after creation.
|
||||||
VirtualCam (platform:v4l2loopback-000):
|
|
||||||
/dev/video1
|
|
||||||
```
|
|
||||||
|
|
||||||
10. _Check the camera resolution_. Use `v4l2-ctl` to ensure that the virtual camera output resolution is `640x480`. Change `/dev/video1` to the port of your virtual camera from the output of `v4l2-ctl --list-devices`.
|
> Error reading frame in background thread for OpenCVCamera(X): OpenCVCamera(X) frame width=640 or height=480 do not match configured width=1920 or height=1080.
|
||||||
|
|
||||||
<!-- prettier-ignore-start -->
|
This error is caused by OBS Virtual Camera advertising a `1920x1080` resolution despite rescaling. The only fix for now is to comment out the width and height check in `_postprocess_image()`.
|
||||||
```python
|
|
||||||
v4l2-ctl -d /dev/video1 --get-fmt-video
|
|
||||||
```
|
|
||||||
<!-- prettier-ignore-end -->
|
|
||||||
|
|
||||||
You should see an entry like:
|
</details>
|
||||||
|
|
||||||
```
|
|
||||||
>>> Format Video Capture:
|
|
||||||
>>> Width/Height : 640/480
|
|
||||||
>>> Pixel Format : 'YUYV' (YUYV 4:2:2)
|
|
||||||
```
|
|
||||||
|
|
||||||
Troubleshooting: If the resolution is not correct you will have to delete the Virtual Camera port and try again as it cannot be changed.
|
|
||||||
|
|
||||||
If everything is set up correctly, you can proceed with the rest of the tutorial.
|
|
||||||
|
|
||||||
</hfoption>
|
</hfoption>
|
||||||
</hfoptions>
|
</hfoptions>
|
||||||
|
|
||||||
|
If everything is set up correctly, your phone will appear as a standard OpenCV camera and can be used with `OpenCVCamera`.
|
||||||
|
|||||||
Reference in New Issue
Block a user