Deploying wandering on Clearpath Jackal#
This software reference details how to deploy and run the wandering mobile robot application on a Clearpath Robotics Jackal robot upgraded with an Intel® Core™ Ultra Series 3 onboard compute board (e.g., Intel® Core™ Ultra X7 358H reference platform).
The pipeline combines RealSense depth camera sensing, RTAB-Map visual SLAM, multi-sensor point cloud fusion (adbscan_sensor_fusion), fast 3D clustering obstacle perception (adbscan_ros2), Nav2 navigation with custom costmap layers (nav2_adbscan_layer), and autonomous frontier exploration (wandering_app).
Architecture#
The Intel® Core™ Ultra Series 3 onboard compute board handles on-robot perception, SLAM, costmap marking, and autonomous navigation:
flowchart TD
subgraph Hardware["Onboard Hardware (Clearpath Jackal + Intel® Core™ Ultra Series 3)"]
RS["RealSense Camera\n(RGB-D PointCloud2 & Depth)"]
LiDAR3D["360° 3D LiDAR (e.g. Velodyne Puck)\n(PointCloud2)"]
BaseServices["Clearpath Base Services / MCU\n(Encoders, IMU, Teleop Mux)"]
end
subgraph Perception["Onboard Perception & SLAM (Intel® Core™ Ultra Series 3)"]
D2L["depthimage_to_laserscan\n(/scan)"]
Fusion["adbscan_sensor_fusion\n(Time-sync & Voxel filter)"]
ADBSCAN["ADBSCAN Node\n(3D Clustering)"]
RTAB["RTAB-Map Visual SLAM\n(RGB-D Mapping & TF)"]
end
subgraph Navigation["Nav2 Navigation Stack"]
Costmap["Nav2 Costmaps\n(ADBScanLayer + Standard Layers)"]
NavServer["Nav2 Planner & Controller\n(FollowPath, Recovery)"]
end
subgraph Application["wandering_app Package"]
WanderApp["wandering_app\n(Frontier Exploration)"]
end
RS --> D2L
RS -.->|"Default point cloud"| Fusion
LiDAR3D -.->|"Alternative 360° cloud"| Fusion
D2L --> Fusion
RS --> RTAB
D2L --> RTAB
Fusion -->|"/adbscan/points"| ADBSCAN
ADBSCAN -->|"/obstacle_array"| Costmap
RTAB -->|"/map & TF"| Navigation
BaseServices -->|"odom, TF"| Navigation
Costmap --> NavServer
Costmap -->|"/global_costmap/costmap"| WanderApp
WanderApp -->|"NavigateToPose action"| NavServer
NavServer -->|"/cmd_vel"| BaseServices
Prerequisites#
Before deploying the pipeline:
Hardware Setup: Follow the Clearpath Robotics Jackal setup guide to install the Intel® Core™ Ultra Series 3 onboard compute board, mount and connect the RealSense camera (e.g. D435i), and configure the robot network and MCU firmware.
Clearpath Base Services: Verify that the Clearpath systemd services (
clearpath-platform.service,clearpath-sensors.service,clearpath-robot.service) are active and publishing topics under the robot’s namespace.Motor Control: Verify motor control and drive commands following the Validate Motor Control section.
Target Environment: Ensure Ubuntu 24.04 LTS with ROS 2 Jazzy (or Ubuntu 22.04 LTS with ROS 2 Humble) is installed on the Intel® Core™ Ultra Series 3 board along with OpenVINO™ packages and Intel NPU drivers (if applicable for Intel® Core™ Ultra).
Install the Application#
Install the wandering metapackage for your installed ROS 2 distribution:
sudo apt update
sudo apt install ros-jazzy-wandering
sudo apt update
sudo apt install ros-humble-wandering
If building from source, build the application using the make build target:
ROS_DISTRO=jazzy make build
source install/setup.bash
ROS_DISTRO=humble make build
source install/setup.bash
Run the Deployment#
Configure the Robot Namespace#
Clearpath Jackal base services publish transforms and topics under a robot namespace (default: /j100_0812). Set the ROBOT_NAMESPACE environment variable to match your robot’s configured namespace in /etc/clearpath/robot.yaml:
export ROBOT_NAMESPACE=/j100_0812
Autonomous Exploration Mode (Default: RealSense Depth Sensing)#
Launch the complete autonomous pipeline using the RealSense depth camera:
export ROBOT_NAMESPACE=/j100_0812
ros2 launch wandering_bringup wandering_jackal.launch.py
What this starts:
depthimage_to_laserscan: Derives 2D/scanfrom the RealSense depth image.dep_rtabmap_jackal: Starts RTAB-Map visual SLAM and RGB-D synchronization.dep_navigation_jackal: Starts the Jackal Nav2 stack configured withADBScanLayerin both local and global costmaps.dep_adbscan_perception: Fuses the scan and RealSense point cloud, performs 3D ADBSCAN obstacle clustering, and publishes/obstacle_array.wandering_app: Frontier-exploration node (wandering_mapper) that evaluates unexplored frontiers on the costmap and sendsNavigateToPosegoals to Nav2.RViz visualization windows (when a display session or remote X11 forwarding is available).
After startup, the robot begins autonomously exploring its surroundings, mapping the environment while avoiding obstacles.

To stop the pipeline, press Ctrl-c in the launch terminal.
Alternative Launch Path: 360-Degree 3D LiDAR (Velodyne Puck) Input#
When the Jackal robot is equipped with a 360-degree 3D LiDAR (such as a Velodyne Puck VLP-16, Ouster OS1, or equivalent 3D LiDAR), you can route the full 360-degree point cloud directly into the ADBSCAN perception pipeline as an alternative to the forward-facing RealSense depth camera point cloud.
How perception behaves in this path:
adbscan_sensor_fusiontransforms the 360-degree LiDAR cloud intobase_link, crops it to the robot’s near-field driveable envelope, filters out floor-level returns, and voxel-downsamples the points before streaming them on/adbscan/points.The Velodyne preset intentionally does not append planar
/scanpoints into this 3D point cloud; this avoids planar scan returns bridging distinct 3D objects into single oversized clusters. The 2D/scantopic remains independently active and continuously fed to RTAB-Map SLAM, standard Nav2 obstacle clearing layers, and collision monitoring.adbscan_ros2clusters the filtered 360-degree cloud in 3D mode, publishing detected object-sized 3D obstacles around the robot to/obstacle_array.
Step 1: Identify and verify the streaming 3D LiDAR topic and frame
Common Clearpath topic names for 3D LiDAR point clouds include /sensors/lidar3d_0/points or /velodyne_points. Check that your robot’s LiDAR driver service is actively streaming data by monitoring the publication rate:
ros2 topic hz /sensors/lidar3d_0/points
# or if using /velodyne_points:
ros2 topic hz /velodyne_points
Confirm that the header frame resolves to base_link through the robot’s namespaced TF tree:
ros2 topic echo --once /sensors/lidar3d_0/points header
ros2 run tf2_ros tf2_echo base_link <lidar_frame_id>
Step 2: Launch with the 3D LiDAR configuration preset
Pass the prepared Velodyne parameter presets and point cloud topic override:
export ROBOT_NAMESPACE=/j100_0812
export LIDAR3D_TOPIC=/sensors/lidar3d_0/points
ros2 launch wandering_bringup wandering_jackal.launch.py \
fusion_params_file:=$(ros2 pkg prefix wandering_bringup)/share/wandering_bringup/params/pointcloud_fusion_jackal_velodyne.yaml \
adbscan_params_file:=$(ros2 pkg prefix wandering_bringup)/share/wandering_bringup/params/adbscan_velodyne.yaml \
pointcloud_topic:=$LIDAR3D_TOPIC
The stack starts up with full 360-degree obstacle clustering around the robot while maintaining visual SLAM mapping and autonomous frontier exploration.
Perception Pipeline Tuning & Configuration Options#
The perception pipeline is composed of three interconnected stages: point cloud fusion and ground removal (adbscan_sensor_fusion), 3D density-based obstacle clustering (adbscan_ros2), and costmap marking (nav2_adbscan_layer). Tuning parameters across these stages allows optimizing obstacle detection sensitivity, cluster sizes, and false-positive rejection for different sensors and robot environments.
1. Point Cloud Fusion & Filtering (adbscan_sensor_fusion)#
Configured via pointcloud_fusion_jackal.yaml (RealSense) or pointcloud_fusion_jackal_velodyne.yaml (3D LiDAR). This node prepares and cleans point clouds before passing them to ADBSCAN:
Parameter |
Default (RealSense / Velodyne) |
Description & Tuning Impact |
|---|---|---|
|
|
Edge length of the 3D voxel grid filter. Larger values downsample more aggressively, reducing downstream clustering computation and clustering latency on dense sensors; smaller values preserve fine geometric details of small obstacles. |
|
|
Radial distance cropping bounds relative to |
|
Unbounded / |
Height window (metres) in |
|
|
Enables RANSAC planar ground segmentation. Essential for 3D LiDAR sensors whose lowest rings intersect the ground. |
|
|
Distance threshold in metres for points classified as ground plane inliers. Points closer than this to the estimated ground plane are stripped away. |
|
|
Maximum tilt angle allowed for the estimated ground plane normal. Prevents steep walls from being erroneously classified as ground. |
|
|
Maximum allowed timestamp skew when synchronizing 2D scan and 3D point cloud topics. |
2. 3D Spatial Clustering (adbscan_ros2)#
Configured via adbscan_fused.yaml (RealSense) or adbscan_velodyne.yaml (Velodyne Puck). These parameters dictate how points are clustered into distinct obstacles:
Parameter |
Default (Fused / Velodyne) |
Description & Tuning Impact |
|---|---|---|
|
|
Maximum distance behind the robot (in metres) to include points for obstacle clustering. |
|
|
Lateral region-of-interest bounds (metres) to the left and right of the robot’s longitudinal centerline. |
|
|
Subsampling ratio applied to incoming points before clustering. A ratio of |
|
|
Scaling coefficient for density-adaptive clustering radius calculation. Lower values enforce tighter clusters; higher values allow sparser, wider clusters to merge. |
|
|
Minimum neighborhood radius ($\epsilon$) in metres for a point to be linked to an adjacent point in 3D clustering. Increase if sparse sensor returns fragment single objects into separate clusters; decrease if nearby objects bridge across empty space. |
|
Adaptive polynomial |
Quadratic distance-adaptive coefficients ($r = \text{base} + \text{coeff}_1 \cdot d + \text{coeff}_2 \cdot d^2$) that scale clustering radius as a function of object distance $d$. Accounts for angular divergence in LiDAR beams or camera depth dispersion at greater ranges. |
|
|
Secondary floor height gate to discard points beneath floor level in |
Advanced Configuration#
Persistent RTAB-Map Database#
To preserve or extend an existing RTAB-Map SLAM database across multiple sessions, specify a database file path:
ros2 launch wandering_bringup wandering_jackal.launch.py \
rtabmap_database_path:=/data/maps/site_jackal.db
Velocity Command Stamping (Twist vs TwistStamped)#
Depending on your robot’s Clearpath base driver version and ROS 2 distribution:
Set
enable_stamped_cmd_vel: truein the Nav2 parameter file (jackal_nav_adbscan.param.yaml) when the platform driver or teleop multiplexer acceptsgeometry_msgs/msg/TwistStamped.Set
enable_stamped_cmd_vel: falsefor unstampedgeometry_msgs/msg/Twistdrivers.If adapting mismatched driver types, the
twist_stamperROS 2 package can convert betweenTwistandTwistStampedtopics.
To inspect the velocity topic expected by your robot:
ros2 topic info /${ROBOT_NAMESPACE#/}/cmd_vel -v
Camera Topic Overrides#
If your RealSense camera is configured with custom topic names, override them at launch:
ros2 launch wandering_bringup wandering_jackal.launch.py \
camera_namespace:=/sensors/camera_0 \
depth_image_topic:=/sensors/camera_0/camera/depth/image_rect_raw \
rgb_image_topic:=/sensors/camera_0/camera/color/image_raw
Troubleshooting#
1. Robot Does Not Move Despite Active Exploration Goals#
Symptom:
wandering_apppicks frontiers and sendsNavigateToPosegoals to Nav2, but the robot remains stationary.Root Cause: Stamped vs. unstamped velocity command mismatch between Nav2 and the Clearpath base multiplexer (
twist_mux), or an incorrect topic namespace.Verification: Check what message type the robot’s base controller is subscribing to:
ros2 topic info /cmd_vel -v # or under the robot namespace: ros2 topic info /${ROBOT_NAMESPACE#/}/cmd_vel -v
Remedy:
If the base driver expects unstamped
geometry_msgs/msg/Twist, setenable_stamped_cmd_vel: falseundercontroller_serverinjackal_nav_adbscan.param.yaml.If the base driver expects
geometry_msgs/msg/TwistStamped, setenable_stamped_cmd_vel: true.Alternatively, use the
twist_stamperROS 2 node to bridge unstamped and stamped velocity topics.
2. Missing RealSense Point Cloud (/sensors/camera_0/points Not Publishing)#
Symptom:
adbscan_pointcloud_fusionwaits indefinitely without publishing/adbscan/points, even though camera image topics are active.Root Cause: The RealSense camera ROS 2 driver was launched without point cloud generation enabled, or the USB connection fell back to USB 2.0.
Verification:
ros2 topic hz /sensors/camera_0/points lsusb -t | grep -i uvcvideo
Remedy:
In
/etc/clearpath/robot.yamlunder the camera device parameters, ensurepointcloud.enable: trueis configured.Verify that the camera is plugged into a USB 3.0 / 3.1 port providing SuperSpeed (5000M) throughput. USB 2.0 connections lack sufficient bandwidth for simultaneous RGB, depth, and point cloud streams.
3. Sensor Fusion Synchronization Dropouts (adbscan_sensor_fusion)#
Symptom: Warning logs indicating dropped messages or timestamp skew in
adbscan_pointcloud_fusion.Root Cause: The approximate-time message synchronizer cannot pair RealSense depth point clouds and derived
/scanframes within the skew tolerance window (sync_max_interval).Remedy: In
pointcloud_fusion_jackal.yaml, increase the synchronizer queue and tolerance window:sync_queue_size: 30 sync_max_interval: 0.20
4. Floor Returns Clustered as Ghost Obstacles#
Symptom: The robot stops or oscillates in place because lethal costmap obstacles are falsely marked on the clear floor directly in front of the robot.
Root Cause: Camera pitch angle deflection, vehicle chassis pitch under acceleration, or floor points falling above the ground filter cutoff.
Verification: Echo
/obstacle_arrayor inspect RViz/adbscan/obstacle_markersto verify if obstacles have $z \approx 0$:ros2 topic echo /obstacle_array --once
Remedy:
Adjust the height cutoff
z_filter: -0.10inadbscan_fused.yaml(ormin_zin the fusion parameter file).For 3D LiDAR deployments, verify that
remove_ground: trueis active and tuneground_distance_threshold(e.g.0.08m to0.10m) andground_max_tilt_degrees.
5. Namespaced TF Lookup Failures#
Symptom: Nodes log errors like
ExtrapolationExceptionorCould not transform from camera_0_link to base_link.Root Cause: Clearpath Jackal publishes TF transforms under
/<robot_namespace>/tfand/<robot_namespace>/tf_static. IfROBOT_NAMESPACEis unset or mismatched, nodes listen on the root/tftopic instead.Verification:
echo $ROBOT_NAMESPACE ros2 topic list | grep tf ros2 run tf2_tools view_frames
Remedy: Export
ROBOT_NAMESPACEto match the exact prefix defined in/etc/clearpath/robot.yaml(e.g.export ROBOT_NAMESPACE=/j100_0812) before executing any launch commands.
6. High Perception Latency or Stuttering on 360-Degree LiDAR#
Symptom: Laggy costmap updates, delayed obstacle avoidance, or high CPU utilization during 3D clustering.
Root Cause: Raw 3D point cloud is overly dense or the spatial region of interest is excessively large for real-time clustering.
Remedy:
Increase
voxel_leaf_sizeinpointcloud_fusion_jackal_velodyne.yamlfrom0.05to0.07or0.08.Increase
subsample_ratioinadbscan_velodyne.yamlfrom1.0to2.0or3.0.Reduce
max_rangein the fusion parameters (e.g., to2.5m) to restrict clustering to the immediate driveable envelope.
General Troubleshooting#
No topics visible: Verify that the
ROS_DOMAIN_IDenvironment variable matches thedomain_idconfigured in/etc/clearpath/robot.yaml.Missing sensor topics: Check the status of the Clearpath systemd services:
sudo systemctl status clearpath-platform.service clearpath-sensors.service clearpath-robot.service
For general system issues, refer to the troubleshooting guide.
Next Steps#
Now that you’ve deployed the wandering workflow on physical hardware:
Visit Optimized Solutions to explore further AMR-specific components, including OpenVINO™-accelerated workloads.
See the Clearpath Robotics Jackal blueprint for more hardware configuration details.