Skip to content

troubleshooting common issues #40

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 8 commits into from
Jan 2, 2025
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
103 changes: 70 additions & 33 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,57 +2,65 @@

This ROS 2 node provides support for a variety of cameras via [libcamera](https://libcamera.org). Amongst others, this node supports V4L2 and [Raspberry Pi cameras](https://www.raspberrypi.com/documentation/computers/camera_software.html).

## Install

### Binary
## Installation

Binary packages are available via the ROS package repository for some Linux and ROS distributions (check with `rosdep resolve camera_ros`). If it's available, you can install the DEB or RPM packages via:
```sh
# source ROS distribution
source /opt/ros/humble/setup.bash
# source a ROS distribution
source /opt/ros/$ROS_DISTRO/setup.bash
# DEB package
sudo apt install ros-$ROS_DISTRO-camera-ros
# RPM package
sudo dnf install ros-$ROS_DISTRO-camera-ros
```

### Source
> [!NOTE]
> This also installs the package [`libcamera`](https://index.ros.org/r/libcamera/) as dependency. This is the bloomed version of the official upstream repo at https://git.libcamera.org/libcamera/libcamera.git and may not contain full support for all Raspberry Pi camera modules. If you need full camera module support on Raspberry Pi, you have to build the "raspberrypi" fork from https://github.com/raspberrypi/libcamera manually.

#### libcamera dependency

The `camera_ros` node depends on libcamera version 0.1 or later.
## Build Instructions

Some Linux and ROS distributions provide binary libcamera packages. Check your package manager for `libcamera` and `rosdep resolve libcamera` to see if binary packages are available.
### libcamera

If your distribution does not provide a binary libcamera package, you have to compile libcamera from source either independent of the colcon workspace according to the [official build instructions](https://libcamera.org/getting-started.html) or as part of the colcon workspace. Either way, you have to install libcamera's build dependencies manually:
```sh
# DEB
sudo apt install pkg-config python3-yaml python3-ply python3-jinja2 openssl libyaml-dev libssl-dev libudev-dev libatomic1 meson
# RPM
sudo dnf install pkgconfig python3-yaml python3-ply python3-jinja2 openssl libyaml-devel openssl-devel libudev-devel libatomic meson
```
The `camera_ros` node depends on libcamera version 0.1 or later. There are different ways to install this dependency:

- __System Package:__ Most Linux distributions provide a binary libcamera package. However, the Raspberry Pi OS uses a [custom libcamera fork](https://github.com/raspberrypi/libcamera) with additional support for newer camera modules. When using the distribution packages, you have to skip the `libcamera` rosdep key when resolving dependencies (`rosdep install [...] --skip-keys=libcamera`).

#### build camera_ros
- __ROS Package:__ You can also install a newer version from the ROS repo (package `ros-$ROS_DISTRO-libcamera`). This package will be installed by default when building `camera_ros` from source and resolving the rosdep keys.

The `camera_ros` package is built in a colcon workspace. The following instructions assume that you are building libcamera from source in the colcon workspace.
- __Source:__ Finally, you can always build libcamera from source. This is currently the only option for using the "raspberrypi" fork on Ubuntu. You can build libcamera as part of the ROS workspace using `colcon-meson`. This is recommended over a system-wide installation as it avoids conflicts with the system package. You will need to install the following dependencies:
1. Install the libcamera build dependencies according to https://libcamera.org/getting-started.html#dependencies.
2. Install `colcon-meson` via the package manager, `sudo apt install -y python3-colcon-meson`, or pip, `pip install colcon-meson`.


### camera_ros

The `camera_ros` package is built together with libcamera in a colcon workspace:
```sh
# create workspace with camera_ros package
mkdir -p ~/camera_ws/
cd ~/camera_ws/
git clone https://github.com/christianrauch/camera_ros.git src/camera_ros
# create workspace
mkdir -p ~/camera_ws/src
cd ~/camera_ws/src

# optional: build libcamera in colcon workspace
pip install colcon-meson
git clone https://git.libcamera.org/libcamera/libcamera.git src/libcamera
# check out libcamera
# Option A: official upstream
git clone https://git.libcamera.org/libcamera/libcamera.git
# Option B: raspberrypi fork with support for newer camera modules
# git clone https://github.com/raspberrypi/libcamera.git

# check out this camera_ros repository
git clone https://github.com/christianrauch/camera_ros.git

# resolve binary dependencies and build workspace
source /opt/ros/humble/setup.bash
source /opt/ros/$ROS_DISTRO/setup.bash
cd ~/camera_ws/
rosdep install --from-paths src --ignore-src --skip-keys=libcamera
colcon build
```

If you installed libcamera externally, you can omit the `colcon-meson` and `libcamera` steps. Additionally, if there is a binary package and a rosdep entry for libcamera (check with `rosdep resolve libcamera`) you can also omit `--skip-keys=libcamera` and have this binary dependency resolved automatically.
If you are using a binary distribution of libcamera, you can skip adding this to the workspace. Additionally, if you want to use the bloomed libcamera package in the ROS repos, you can also omit `--skip-keys=libcamera` and have this binary dependency resolved automatically.



## Launching the Node

Expand All @@ -69,9 +77,10 @@ and an example launch file for the composable node:
ros2 launch camera_ros camera.launch.py
```


## Interfaces

The camera node interfaces are compatible with the `image_pipeline` stack. The node publishes the camera images and camera parameters and provides a service to set the camera parameters.
The camera node interfaces are compatible with the [`image_pipeline`](https://github.com/ros-perception/image_pipeline) stack. The node publishes the camera images and camera parameters and provides a service to set the camera parameters.

### Topics

Expand Down Expand Up @@ -107,12 +116,12 @@ or dynamically via the [ROS parameter API](https://docs.ros.org/en/rolling/Conce

The camera stream is configured once when the node starts via the following static read-only parameters:

| name | type | description |
| ----------------- | --------------------- | ---------- |
| `camera` | `integer` or `string` | selects the camera by index (e.g. `0`) or by name (e.g. `/base/soc/i2c0mux/i2c@1/ov5647@36`) [default: `0`]
| `role` | `string` | configures the camera with a `StreamRole` (possible choices: `raw`, `still`, `video`, `viewfinder`) [default: `video`]
| `format` | `string` | a `PixelFormat` that is supported by the camera [default: auto]
| `width`, `height` | `integer` | desired image resolution [default: auto]
| name | type | description |
| ----------------- | --------------------- | --------------------------------------------------------------------------------------------------------------------------- |
| `camera` | `integer` or `string` | selects the camera by index (e.g. `0`) or by name (e.g. `/base/soc/i2c0mux/i2c@1/ov5647@36`) [default: `0`] |
| `role` | `string` | configures the camera with a `StreamRole` (possible choices: `raw`, `still`, `video`, `viewfinder`) [default: `viewfinder`] |
| `format` | `string` | a `PixelFormat` that is supported by the camera [default: auto] |
| `width`, `height` | `integer` | desired image resolution [default: auto] |


The configuration is done in the following order:
Expand Down Expand Up @@ -159,3 +168,31 @@ and then run the node with libcamera and ROS debug information in `gdb`:
```sh
LIBCAMERA_LOG_LEVELS=*:DEBUG ros2 run --prefix 'gdb -ex run --args' camera_ros camera_node --ros-args --log-level debug -p width:=640 -p height:=480
```


### Common Issues

#### No camera is detected (exception `no cameras available`)

For standard V4L2 camera devices, check that its connection is detected (`lsusb`) and that it is also detected by V4L2 (`v4l2-ctl --list-devices`).

On the Raspberry Pi, use `sudo vclog --msg` to inspect the VideoCore log messages for detected cameras. `vclog` is part of Raspberry Pi's `utils` repo at https://github.com/raspberrypi/utils. If this is not available in your distribution, such as Ubuntu, you have to build it from source:
```sh
# install build dependencies
sudo apt -y install --no-install-recommends wget ca-certificates gcc libc6-dev
# download vclog and build
wget https://raw.githubusercontent.com/raspberrypi/utils/refs/heads/master/vclog/vclog.c
gcc vclog.c -o vclog
# show VideoCore log messages
sudo ./vclog --msg
```

In the VideoCore log, you should find something like `Found camera 'ov5647' []` or `Found camera 'imx708' [...]`, which indicates the connected sensor, in these cases the _OmniVision OV5647_ and _Sony IMX708_. Look up this sensor in the [Raspberry Pi camera modules _Hardware Specification_](https://www.raspberrypi.com/documentation/accessories/camera.html#hardware-specification) and match the detected sensor with with the camera module. In this case, the _OmniVision OV5647_ image sensor belongs to the Camera Module 1 and the _Sony IMX708_ to the Camera Module 3.

If you are using a Raspberry Pi Camera Module, make sure that it is supported by the libcamera variant that you have installed. For example, the official upstream libcamera supports the Camera Module 1 (OmniVision OV5647), while the Camera Module 3 (Sony IMX708) is currently only supported by the "raspberrypi" fork of libcamera. To verify that your camera is working with libcamera, build the `cam` example from the libcamera repo and list the camera devices with `cam -l`. For a camera with the _OmniVision OV5647_ sensor, this will show something like `'ov5647' (/base/axi/pcie@120000/rp1/i2c@88000/ov5647@36)` and for the _Sony IMX708_ something like `'imx708_wide' (/base/axi/pcie@120000/rp1/i2c@88000/imx708@1a)`.

#### Buffer allocation issues (exception `Failed to allocate buffers`)

If the node fails to allocate buffers, you are probably running out of video memory. This is most likely the case on resource constrained devices with limited memory, such as the Raspberry Pi Zero.

To avoid this, either increase the video memory via `raspi-config`, or decrease the buffer size by reducing the image resolution (parameters `width` and `height`) and/or selecting a chroma subsampled or compressed pixel format that uses less bits per pixel (parameter `format`). For example, a raw format like `XRGB8888` uses 32 bits for each individual pixel, while a chroma subsampled format like `YUYV` only uses 32 bits per two pixels due to the subsampling of the colour components. For details on pixel formats, see the [Linux Kernel Image Formats documentation](https://www.kernel.org/doc/html/latest/userspace-api/media/v4l/pixfmt.html).