Adds a rate-limiting shim between raw /cmd_vel and the drive stack to prevent wheel slip, tipping, and jerky motion from step velocity inputs. Core library — _velocity_ramp.py (pure Python, no ROS2 deps) - VelocityRamp: applies independent accel/decel limits to linear-x and angular-z with configurable max_lin_accel, max_lin_decel, max_ang_accel, max_ang_decel - _ramp_axis(): per-axis rate limiter with correct accel/decel selection (decel when |target| < |current| or sign reversal; accel otherwise) - Emergency stop: step(0.0, 0.0) bypasses ramp → immediate zero output - Asymmetric limits supported (e.g. faster decel than accel) ROS2 node — velocity_ramp_node.py - Subscribes /cmd_vel, publishes /cmd_vel_smooth at configurable rate_hz - Parameters: max_lin_accel (0.5 m/s²), max_lin_decel (0.5 m/s²), max_ang_accel (1.0 rad/s²), max_ang_decel (1.0 rad/s²), rate_hz (50) Tests — test/test_velocity_ramp.py: 50/50 passing - _ramp_axis: accel/decel selection, sign reversal, overshoot prevention - Construction: invalid params raise ValueError, defaults verified - Linear/angular ramp-up: step size, target reached, no overshoot - Deceleration: asymmetric limits, partial decel (non-zero target) - Emergency stop: immediate zero, state cleared, resume from zero - Sign reversal: passes through zero without jumping - Reset: state cleared, next ramp starts from zero - Monotonicity: linear and angular outputs are monotone toward target - Rate accuracy: 50Hz/10Hz step sizes, 100-step convergence verified Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
73 lines
3.6 KiB
Python
73 lines
3.6 KiB
Python
from setuptools import setup
|
|
import os
|
|
from glob import glob
|
|
|
|
package_name = 'saltybot_bringup'
|
|
|
|
setup(
|
|
name=package_name,
|
|
version='0.1.0',
|
|
packages=[package_name],
|
|
data_files=[
|
|
('share/ament_index/resource_index/packages',
|
|
['resource/' + package_name]),
|
|
('share/' + package_name, ['package.xml']),
|
|
(os.path.join('share', package_name, 'launch'),
|
|
glob('launch/*.launch.py')),
|
|
(os.path.join('share', package_name, 'config'),
|
|
glob('config/*.yaml')),
|
|
(os.path.join('share', package_name, 'behavior_trees'),
|
|
glob('behavior_trees/*.xml')),
|
|
],
|
|
install_requires=['setuptools'],
|
|
zip_safe=True,
|
|
maintainer='sl-perception',
|
|
maintainer_email='sl-perception@saltylab.local',
|
|
description='SaltyBot sensor bringup and SLAM launch files',
|
|
license='MIT',
|
|
tests_require=['pytest'],
|
|
entry_points={
|
|
'console_scripts': [
|
|
'depth_confidence_filter = saltybot_bringup.depth_confidence_filter_node:main',
|
|
'camera_health_monitor = saltybot_bringup.camera_health_node:main',
|
|
'scan_height_filter = saltybot_bringup.scan_height_filter_node:main',
|
|
# LIDAR object clustering + RViz visualisation (Issue #239)
|
|
'lidar_clustering = saltybot_bringup.lidar_clustering_node:main',
|
|
# Floor surface type classifier (Issue #249)
|
|
'floor_classifier = saltybot_bringup.floor_classifier_node:main',
|
|
# Visual odometry drift detector (Issue #260)
|
|
'vo_drift_detector = saltybot_bringup.vo_drift_node:main',
|
|
# Depth image hole filler (Issue #268)
|
|
'depth_hole_fill = saltybot_bringup.depth_hole_fill_node:main',
|
|
# HSV color object segmenter (Issue #274)
|
|
'color_segmenter = saltybot_bringup.color_segment_node:main',
|
|
# Motion blur detector (Issue #286)
|
|
'blur_detector = saltybot_bringup.blur_detect_node:main',
|
|
# Terrain roughness estimator (Issue #296)
|
|
'terrain_roughness = saltybot_bringup.terrain_rough_node:main',
|
|
# Sky detector for outdoor navigation (Issue #307)
|
|
'sky_detector = saltybot_bringup.sky_detect_node:main',
|
|
# Wheel encoder differential drive odometry (Issue #184)
|
|
'wheel_odom = saltybot_bringup.wheel_odom_node:main',
|
|
# Appearance-based person re-identification (Issue #322)
|
|
'person_reid = saltybot_bringup.person_reid_node:main',
|
|
# Dynamic obstacle velocity estimator (Issue #326)
|
|
'obstacle_velocity = saltybot_bringup.obstacle_velocity_node:main',
|
|
# Lane/path edge detector (Issue #339)
|
|
'path_edges = saltybot_bringup.path_edges_node:main',
|
|
# Depth-based obstacle size estimator (Issue #348)
|
|
'obstacle_size = saltybot_bringup.obstacle_size_node:main',
|
|
# Audio scene classifier (Issue #353)
|
|
'audio_scene = saltybot_bringup.audio_scene_node:main',
|
|
# Face emotion classifier (Issue #359)
|
|
'face_emotion = saltybot_bringup.face_emotion_node:main',
|
|
# Person tracking for follow-me mode (Issue #363)
|
|
'person_tracking = saltybot_bringup.person_tracking_node:main',
|
|
# UWB DW3000 anchor/tag ranging (Issue #365)
|
|
'uwb_node = saltybot_bringup.uwb_node:main',
|
|
# Smooth velocity ramp controller (Issue #350)
|
|
'velocity_ramp = saltybot_bringup.velocity_ramp_node:main',
|
|
],
|
|
},
|
|
)
|