Experimental ROS2 node for access to Basler camera via pylon CBaslerUniversalInstantCamera API.
Supports USB and GigE cameras. Tested with a Basler daA1280-54uc camera.
Known to work on Ubuntu 22.04 "Jammy" with ROS2 "humble".
Supports low-latency, high-speed, arbitrary framerate, free-running mode.
At time of writing, the official driver does not support "acquisition overlap".
Usage of the software trigger is hard-coded, effectively halving the maximum frame-rate.
Some background information and discussion:
- magazino/pylon_camera#25
- basler/pylon-ros-camera#21
- basler/pylon-ros-camera#28
- basler/pylon-ros-camera#29
- basler/pylon-ros-camera#147
- basler/pylon-ros-camera#200
If the camera provides pixels in bayer pattern (raw), the default topic name is image_raw
.
If the camera provides pixels in RGB (color) or MONO (grayscale), the default topic name is image
.
Starts a node which publishes image data on topic /image
.
The camera will be opened using its default parameters:
ros2 run pylon_instant_camera node
Starts a node which publishes image data on topic /pylon_camera/image_raw
.
The camera will be opened and configured with the feature-set stored in settings.pfs
.
Camera calibration data will be loaded from camera_calibration.yaml
and published at /pylon_camera/camera_info
for image rectification.
ros2 run pylon_instant_camera node --ros-args \
-r __ns:=/pylon_camera \
--param camera_settings_pfs:=settings_bayer.pfs \
--param camera_info_yaml:=camera_calibration.yaml
Launch file based on this example, with software debayer and camera image rectification:
import launch
from launch_ros.actions import ComposableNodeContainer
from launch_ros.descriptions import ComposableNode
def generate_launch_description():
"""Use composition for all image-processing nodes.
Keeps overhead low since image data can – theoretically – reside in shared memory."""
image_processing = ComposableNodeContainer(
name = 'container',
namespace = 'pylon_camera_node',
package = 'rclcpp_components',
executable = 'component_container',
composable_node_descriptions = [
ComposableNode(
name = 'pylon_camera',
namespace = 'pylon_camera_node',
package = 'pylon_instant_camera',
plugin = 'pylon_instant_camera::PylonCameraNode',
parameters = [{
'camera_settings_pfs': 'settings.pfs',
'camera_info_yaml': 'camera_calibration.yaml'
}]
),
ComposableNode(
package='image_proc',
plugin='image_proc::DebayerNode',
name='debayer_node',
namespace='pylon_camera_node'
),
ComposableNode(
package='image_proc',
plugin='image_proc::RectifyNode',
name='pylon_camera_rectify_color',
namespace='pylon_camera_node'
),
ComposableNode(
package='image_proc',
plugin='image_proc::RectifyNode',
name='pylon_camera_rectify_mono',
namespace='pylon_camera_node',
remappings=[
('image', 'image_mono')
],
)
]
)
return launch.LaunchDescription([image_processing])
Viewing the unprocessed camera image is possible by manually loading the ShowImage tool like this:
ros2 component load /pylon_camera_node/container image_tools image_tools::ShowImage --node-namespace /pylon_camera_node
The pylon Viewer included in the pylon SDK stores all the settings in one file of tab-separated key-value-pairs. Set the pixel type like this:
# {05D8C294-F295-4dfb-9D01-096BD04049F4}
# GenApi persistence file (version 3.1.0)
PixelFormat RGB8
With the pixel format RGB8, you do not need the DebayerNode and remappings mentioned in the example above.
In order to select one of multiple cameras, you may supply one or more parameter to identify the particular camera:
serial_number
– Can be viewed in the pylon Viewer.user_defined_name
– Can be set via the pylon Viewer.ip_address
– For ethernet cameras.full_name
– For USB cameras. This value may change upon device re-connect. Use with caution.
These values are also displayed in the log.
You may also want to remap the namespace so the output topic will not clash:
ros2 run pylon_instant_camera node --ros-args --param serial_number:="123456789" -r __ns:=/front_camera
This warning can be emitted:
Payload data has been discarded. Payload data can be discarded by the camera device if the available bandwidth is insufficient.
This is normal for USB connections and should only happen once after camera start.
ROS 2 does not offer a true zero-copy communication mechanism – not even via shared memory – see discussion here.