sl-perception e0987fcec8 feat: outdoor nav — OSM routing + GPS waypoints + geofence (#59)
Implements Phase 2d outdoor autonomous navigation for SaltyBot.
GPS source: SIM7600X /gps/fix from PR #65 (saltybot_cellular).

saltybot_outdoor package:
- osm_router_node: Overpass API + A* haversine graph + Douglas-Peucker
  simplification, /outdoor/route (Path) + /outdoor/waypoints (PoseArray)
- gps_waypoint_follower_node: GPS->Nav2 navigate_through_poses bridge,
  quality-adaptive tolerances (2m cellular / 0.30m RTK)
- geofence_node: ray-casting polygon safety, emergency stop on violation
- outdoor_nav.launch.py: dual-EKF + navsat_transform + all nodes
- outdoor_nav_params.yaml: 1.5m/s, no static_layer, 2m GPS tolerance
- ekf_outdoor.yaml: robot_localization dual-EKF + navsat_transform
- geofence_vertices.yaml: template with usage instructions

docker-compose.yml: fix malformed saltybot-surround block; add
saltybot-outdoor service (depends on saltybot-nav2, OSM NVMe cache)

SLAM-SETUP-PLAN.md: Phase 2d done

RTK upgrade: SIM7600X (+-2.5m) -> ZED-F9P (+-2cm), set use_rtk:=true

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-01 00:52:54 -05:00

35 lines
1.1 KiB
Python

import os
from glob import glob
from setuptools import find_packages, setup
package_name = 'saltybot_outdoor'
setup(
name=package_name,
version='0.1.0',
packages=find_packages(exclude=['test']),
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/*.py')),
(os.path.join('share', package_name, 'config'),
glob('config/*.yaml')),
],
install_requires=['setuptools'],
zip_safe=True,
maintainer='seb',
maintainer_email='seb@saltylab.io',
description='Outdoor navigation: OSM routing, GPS waypoint following, geofence',
license='MIT',
tests_require=['pytest'],
entry_points={
'console_scripts': [
'osm_router_node = saltybot_outdoor.osm_router_node:main',
'gps_waypoint_follower = saltybot_outdoor.gps_waypoint_follower_node:main',
'geofence_node = saltybot_outdoor.geofence_node:main',
],
},
)