Skip to content
 
 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

14 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

baumer_ox_scanner

ROS 2 (Humble) package for a Baumer OXP200 laser line-profile scanner mounted on a robot arm. Ported from an earlier ROS 1/catkin package to run the same filter → accumulate/denoise pipeline shape as the pc_scanner RealSense package, so a downstream (e.g. Rhino) process can consume either sensor's output the same way.

Unlike the RealSense (a full-frame depth camera), the OXP200 is a 1D line-profile sensor: each reading is a single scan line (X across, Z forward distance), and a full surface only comes from sweeping the sensor across the part with the robot. Practically, that means:

  • The fixed-frame-count capture_averaged service works the same as in pc_scanner (useful for denoising a single static reading).
  • The real scanning workflow is a sweep: call start_sweep_capture, move the robot while the scanner streams profiles (each one transformed into robot_base_frame as it arrives, since the arm is moving throughout), then call stop_sweep_capture to voxel-fuse everything collected and publish it.

There's no range/region filter node in this package (unlike pc_scanner's pointcloud_range_filter) — the OX200's own field-of-view/distance configuration (set via its web interface) already constrains the raw data well enough, so accumulate_denoise subscribes directly to the driver's output.

Nodes

  • scanner_pointcloud_node — connects to the OX scanner over the network (vendor OxApi C++ SDK, vendored under OxSDK_V2_0_0/) and publishes a raw PointCloud2 per profile in the laser_scanner frame, on /scanner/points.
  • accumulate_denoise.py — same voxel + statistical-outlier fusion as pc_scanner, plus two new services for sweep capture (see below).

Hardware setup

  1. Configure the scanner via its web interface — use Height Mode, not Distance Mode.
  2. Note its IP (default assumed here: 192.168.0.250).

Quick start

ros2 launch baumer_ox_scanner baumer_scanner.launch.py host:=192.168.0.250

This starts: the tool0 -> laser_scanner static transform, the scanner driver, accumulate_denoise (with via_robot:=true by default — see below), and rviz.

Sweep scanning (the normal workflow for this sensor)

ros2 service call /start_sweep_capture std_srvs/srv/Trigger
# ...move the robot through the sweep...
ros2 service call /stop_sweep_capture std_srvs/srv/Trigger

The fused result is published on /scanner/points_accumulated in robot_base_frame, and keeps being republished at republish_rate Hz so late subscribers (or Rhino) still see it.

ros2 service call /reset_accumulation std_srvs/srv/Trigger

clears a running scan (either mode) without restarting the node.

Single static reading (capture_averaged)

ros2 service call /capture_averaged std_srvs/srv/Trigger

Averages num_frames consecutive profiles from the current, stationary pose — a literal port of pc_scanner's snapshot mode, kept in case a static reading is ever useful for this sensor.

Requires: robot_arm_tool0 -> laser_scanner in tf

Both capture modes need tf2 to resolve robot_base_frame -> ... -> robot_arm_tool0 -> laser_scanner. The tool0 -> laser_scanner static transform in launch/baumer_tf.launch.py is currently a placeholder (identity) — measure the actual sensor mount offset (CAD or hand-eye calibration) before trusting fusion results, the same caveat as pc_scanner's camera mount transform.

Key parameters

scanner_pointcloud_node:

Parameter Default Meaning
host 192.168.0.250 Scanner IP address
frame_id laser_scanner Frame the raw cloud is published in
topic_name /scanner/points Raw output topic
rate 50.0 Hz Profile read/publish rate
measurement_distance 0.25 m Nominal standoff distance (z offset)
unit_to_meters_override 0.0 (auto-detect) Force the raw-unit-to-meters factor instead of reading it from the sensor (see below)

Raw units -> meters

Each profile point comes back as (X[i]+XStart)/Z[i] in raw sensor ticks. Per the vendor SDK docs, the actual value is raw / profile.Precision, in whatever unit GetProfileInfo() reports (their own worked example: Precision=10, unit "mm") — Precision is a live, device/configuration-dependent value, not a fixed constant. On each (re)connect, scanner_pointcloud_node calls GetProfileInfo() once, maps the reported unit string (m/mm/cm/nm/um/µm) to a meters factor, and logs what it detected. If the unit string doesn't match any of those (or you want to force a specific value), set unit_to_meters_override explicitly — otherwise it falls back to mm (0.001) with a loud warning.

accumulate_denoise shares the same parameters as pc_scanner's (see its README), just with input_topic defaulting to /scanner/points and output_topic to /scanner/points_accumulated.

Services

Service Type Effect
/capture_averaged std_srvs/srv/Trigger Average num_frames frames from a static pose
/start_sweep_capture std_srvs/srv/Trigger Begin fusing profiles into robot_base_frame as the robot moves
/stop_sweep_capture std_srvs/srv/Trigger End the sweep, voxel-fuse, and publish the result
/reset_accumulation std_srvs/srv/Trigger Clear a running scan (either mode)

Problem solving

"Could not connect to host"

This could be due to not closing the scanner's WebInterface, or another instance of the driver node already running and connected to the scanner.

rviz PointCloud2 display shows nothing on /scanner/points, with a QoS warning

scanner_pointcloud_node publishes the raw topic with SensorDataQoS (best effort), matching the RealSense driver convention pc_scanner already relies on. If you add an rviz PointCloud2 display for /scanner/points directly (e.g. to debug the raw data), rviz's default per-display Reliability is Reliable, which is incompatible with a best-effort publisher — rviz will warn and nothing will render. Set that display's Topic Reliability Policy to Best Effort to fix it. /scanner/points_accumulated (the final fused output from accumulate_denoise) doesn't have this problem — it publishes Reliable by default, matching baumer_scan.rviz's existing display.

About

ROS2 implementation of Baumer OXP200 scanner

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages