Ubuntu22.04 ros2_humble 单目相机标定 及 ros2如何使用usb_cam
利用ros的image_pipeline软件包实现对相机的标定。进入工作目录下载image_pipeline【报错】: 通常是由于网络连接问题,尤其是从 GitHub 克隆大型仓库时,可能会遇到网络不稳定或连接中断的情况。【解决】: 默认情况下,Git 对 HTTP 请求的缓冲区大小有限制,你可以尝试增加缓冲区大小来解决此问题这会将缓冲区大小增加到 500MB,可能有助于解决因缓冲区不足导致的问题
利用ros2的image_pipeline软件包实现对相机的标定。
1.软件包安装
sudo apt install ros-humble-camera-calibration-parsers
sudo apt install ros-humble-camera-info-manager
sudo apt install ros-humble-launch-testing-ament-cmake
进入工作目录下载image_pipeline
cd ~/ros2_ws/src
git clone -b humble https://github.com/ros-perception/image_pipeline.git
【报错】:RPC failed; curl 56 GnuTLS recv error (-9): Error decoding the received TLS packet
通常是由于网络连接问题,尤其是从 GitHub 克隆大型仓库时,可能会遇到网络不稳定或连接中断的情况。
【解决】: 默认情况下,Git 对 HTTP 请求的缓冲区大小有限制,你可以尝试增加缓冲区大小来解决此问题
git config --global http.postBuffer 524288000
这会将缓冲区大小增加到 500MB,可能有助于解决因缓冲区不足导致的问题。
然后再次尝试克隆仓库:
git clone -b humble https://github.com/ros-perception/image_pipeline.git
编译软件包,添加环境变量 :
cd ~/ros2_ws
colcon build
source install/setup.bash
2.相机标定
启动相机节点:
cam2image 节点发布图像的topic为 /image,为了将topic重映射为/camera/iamge_raw,采用如下命令
ros2 run image_tools cam2image --ros-args -p width:=640 -p height:=480 -p frequency:=30.0 -p device_id:=-1 -r /image:=/camera/image_raw
启动相机标定节点:
ros2 run camera_calibration cameracalibrator --size 11x8 --square 0.020 image:=/camera/image_raw camera:=/camera
【注意】:棋盘格内部角点和棋盘格行列数不相等,比如我的棋盘格是12*9,但是内部角点为11*8,其次根据自己棋盘格的大小更改square的值,我的是20mm。
标定板的参数需根据自己的实际情况设置。节点启动后会弹出一个窗口,窗口右侧有x,y,size,skew显示条,以及calibrate,save,commit按钮。
在相机视野范围内不断移动棋盘格,变化棋盘格姿态,使得棋盘到达相机视野左侧、右侧、顶部和底部。x,y,size分别对应标定板相对于相机的运动:x对应左右方向的运动,y对应上下方向的运动,size对应接近/靠近相机,skew对应倾斜姿态。
随着棋盘格的不断移动和变换姿态,标定窗口右侧x,y,size,skew对应的4个横条的长度会不断增长。当横条都变成绿色表示数据满足标定条件,此时,“CALIBRATE”按钮将会变亮,单击进行标定。标定完成后保存和提交按钮变亮。点击保存按钮后,结果自动保存到/tmp/calibrationdata.tar.gz中。
3.usb_cam的使用
安装usb_cam
sudo apt-get install ros-humble-usb-cam
启动usb_cam
ros2 launch usb_cam camera.launch.py
报错:
Caught exception in launch (see debug for traceback): Caught exception when trying to load file of format [py]: No module named 'pydantic'
解决:下载pydantic库
pip install pydantic -i https://pypi.tuna.tsinghua.edu.cn/simple some-package
继续启动:
ros2 launch usb_cam camera.launch.py
报错:
Pydantic 版本要求 @root_validator
使用时必须指定 skip_on_failure=True
,因为默认的 pre=False
设定可能会导致验证失败。
解决:
sudo vim /opt//ros/humble/share/usb_cam/launch/camera_config.py
原来的代码:
from pathlib import Path
from typing import List, Optional
from ament_index_python.packages import get_package_share_directory
from pydantic import BaseModel, root_validator, validator
USB_CAM_DIR = get_package_share_directory('usb_cam')
class CameraConfig(BaseModel):
name: str = 'camera1'
param_path: Path = Path(USB_CAM_DIR, 'config', 'params_1.yaml')
remappings: Optional[List]
namespace: Optional[str]
@validator('param_path')
def validate_param_path(cls, value):
if value and not value.exists():
raise FileNotFoundError(f'Could not find parameter file: {value}')
return value
@root_validator
def validate_root(cls, values):
name = values.get('name')
remappings = values.get('remappings')
if name and not remappings:
# Automatically set remappings if name is set
remappings = [
('image_raw', f'{name}/image_raw'),
('image_raw/compressed', f'{name}/image_compressed'),
('image_raw/compressedDepth', f'{name}/compressedDepth'),
('image_raw/theora', f'{name}/image_raw/theora'),
('camera_info', f'{name}/camera_info'),
]
values['remappings'] = remappings
return values
修改后:
# Copyright 2023 usb_cam Authors
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
#
# * Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
#
# * Neither the name of the usb_cam Authors nor the names of its
# contributors may be used to endorse or promote products derived from
# this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
from pathlib import Path
from typing import List, Optional
from ament_index_python.packages import get_package_share_directory
#from pydantic import BaseModel, root_validator, validator
from pydantic import BaseModel, model_validator, validator
USB_CAM_DIR = get_package_share_directory('usb_cam')
class CameraConfig(BaseModel):
name: str = 'camera1'
param_path: Path = Path(USB_CAM_DIR, 'config', 'params_1.yaml')
remappings: Optional[List[str]] = []
namespace: Optional[str] = None
@validator('param_path')
def validate_param_path(cls, value):
if value and not value.exists():
raise FileNotFoundError(f'Could not find parameter file: {value}')
return value
# @root_validator
# def validate_root(cls, values):
# name = values.get('name')
# remappings = values.get('remappings')
# if name and not remappings:
# # Automatically set remappings if name is set
# remappings = [
# ('image_raw', f'{name}/image_raw'),
# ('image_raw/compressed', f'{name}/image_compressed'),
# ('image_raw/compressedDepth', f'{name}/compressedDepth'),
# ('image_raw/theora', f'{name}/image_raw/theora'),
# ('camera_info', f'{name}/camera_info'),
# ]
# values['remappings'] = remappings
# return value
@validator('name')
def validate_name(cls, value):
if not value:
raise ValueError("Name is required")
return value
def __init__(self, **data):
super().__init__(**data)
if self.name:
# Automatically set remappings if name is set
self.remappings.extend([
('image_raw', f'{self.name}/image_raw'),
('image_raw/compressed', f'{self.name}/image_compressed'),
('image_raw/compressedDepth', f'{self.name}/compressedDepth'),
('image_raw/theora', f'{self.name}/image_raw/theora'),
('camera_info', f'{self.name}/camera_info'),
])
继续启动:
ros2 launch usb_cam camera.launch.py
报错:[ERROR] [usb_cam_node_exe-1]: process has died [pid 17787, exit code -11]
说明 usb_cam_node_exe
节点崩溃了,返回了 exit code -11
(通常是段错误或内存访问错误)
可能是参数配置文件出现问题,查看相机支持的格式
修改 sudo vim /opt/ros/humble/share/usb_cam/config/params_1.yaml当中的pixel_format:改为相机支持的模式
修改后可正常运行launch文件
此后,如若需要修改相机参数,可打开/opt/ros/humble/share/usb_cam/config/params_1.yaml来修改
————————————————
参考:
https://blog.csdn.net/weixin_60864335/article/details/130263861
更多推荐
所有评论(0)