Next-Generation Positioning System (NGPS) for high-altitude drone navigation without GPS.
This codebase implements a visual geo-localization system for drones that matches down-facing camera images against satellite reference images using deep learning-based feature matching. The system provides absolute position estimates to correct drift in Visual-Inertial Odometry (VIO) systems.
-
ap_ngps_ros2: ROS2 node that performs visual geo-localization by matching camera images to satellite reference images using LightGlue/SuperPoint deep learning features. Runs at 1-2 Hz.
-
ap_ukf: Unscented Kalman Filter that fuses multiple sensor inputs:
- NGPS absolute position (1-2 Hz)
- VIO relative pose (10-20 Hz)
- IMU data (high frequency)
Outputs fused odometry at 10-20 Hz for flight control.
-
ap_vips: Visual-Inertial Odometry system that provides high-frequency relative pose estimates optimized for high-altitude flight.
- NGPS module matches real-time camera frames to a georeferenced satellite reference image
- Provides absolute position estimates at low frequency (1-2 Hz)
- UKF fuses NGPS absolute positions with high-frequency VIO estimates
- Fused output sent to ArduPilot's EKF for final state estimation
- GSoC 2024: High Altitude Non-GPS Navigation - Initial GSoC project summary
- Transformer & Optimization Based High Altitude GPS-Denied Fusion - Updated implementation and architecture details
- ap_nongps - Earlier prototype implementation with SIFT-based feature matching and optical flow methods
- Add an intereactive initial guess interface
- Add a fallback VO pipeline
- Add global optimisation for fusion
- Update AP to accept position and odometry as separate sources to be fused internally
- Add support for multiple reference images
- Optimize feature matching for faster performance
- Add calibration tools and documentation
- Improve error handling and recovery
- Add more unit tests
- Document configuration parameters
- Add example launch files for different scenarios
- Performance profiling and optimization
- Convert lightglue model to jetson friendly compute capable
- Support for different camera models
- GTSAM and SFM support
Step 1: Install Docker Engine
- Follow the official installation guide: Install Docker Engine.
Setup WSL2 for ubuntu using these instructions: https://learn.microsoft.com/en-us/windows/wsl/install#upgrade-version-from-wsl-1-to-wsl-2 and confirm WSL version is
2.Install Docker for WSL2: https://docs.docker.com/desktop/features/wsl/
Before proceeding, confirm if systemd is enabled in WSL2 environemnt:
$ ps -p 1 -o comm= # Output: should show systemd enabled.Alternatively, check
wsl.confand confirm it showssystemd=true$ cat /etc/wsl.conf # It must be: [boot] systemd=trueIf not, update contents of the
wsl.conffile as shown above to enablesystemdon WSL. Then:
- Exit WSL2
- wsl --shutdown
- wsl --update
- Run WSL again:
wsl --distribution Ubuntuand confirm ifsystemdis enabled this time.Continue with the next steps
- Apply the Linux post-installation configuration as non-root user: Linux post-installation steps for Docker Engine.
Step 2: NVIDIA Container Toolkit
Requires NVIDIA GPU
- Install the toolkit: NVIDIA Container Toolkit.
- Configure Docker to use the NVIDIA runtime and restart the daemon:
sudo nvidia-ctk runtime configure --runtime=docker
sudo systemctl restart dockerStep 3: Clone the repository
Clone into a ROS 2 workspace layout as described below (
~/ngps_ws/src/ngps_flight, not a bare clone anywhere else, else have to modify setup scripts):
mkdir -p ~/ngps_ws/src
cd ~/ngps_ws/src
git clone https://github.com/snktshrma/ngps_flight.gitStep 4: Docker image
Recommended: Pull a prebuilt dev image (for distrobox, with docker as container manager):
docker pull snktshrma/ngps-vps-dev:latest
export NGPS_IMG="snktshrma/ngps-vps-dev:latest"Or build locally:
cd ~/ngps_ws/src/ngps_flight
docker build -f Dockerfile.dev -t vps-dev:latest .
export NGPS_IMG="vps-dev:latest"DOCKER ONLY PATH (not recommended for development): Skip Steps 5–6. Mount the host workspace at
/home/dev/ngps_wsand setHOME=/home/devso~/ngps_wsinsetup.shresolves correctly. Use--entrypoint /bin/bashwith the prebuilt Hub image (it is distrobox-oriented).With NVIDIA GPU (requires Step 2):
docker run -it \ --name vps-dev \ --entrypoint /bin/bash \ --network host \ --privileged \ --ipc host \ --gpus all \ -v ~/ngps_ws:/home/dev/ngps_ws \ -e HOME=/home/dev \ -e DISPLAY=$DISPLAY \ -v /tmp/.X11-unix:/tmp/.X11-unix \ "$NGPS_IMG"To start container again:
docker start vps-dev docker exec -it vps-dev /bin/bashInitialize the workspace (Docker only, from the host):
docker exec -it vps-dev bash -lc 'cd ~/ngps_ws/src/ngps_flight && bash setup.sh'
Step 5: Install Distrobox
For Ubuntu:
sudo apt install distrobox
export DBX_CONTAINER_MANAGER=docker
echo "export DBX_CONTAINER_MANAGER=docker" >> ~/.bashrcStep 6: Create the Distrobox
distrobox create \
--name vps-dev \
--image "$NGPS_IMG" \
--additional-flags "--privileged --ipc=host --gpus all"Step 7: Enter and initialize the workspace
Distrobox (after Steps 5–6):
distrobox enter vps-devInside the container:
bash ~/ngps_ws/src/ngps_flight/setup.sh
# When done,
source ~/.bashrcDistrobox: The host user home directory is mounted; workspace paths such as
~/ngps_wsmatch the host, while binaries and libraries resolve from the container image.Docker only: Run
setup.shas shown in Step 4, thendocker exec -it vps-dev /bin/bashfor an interactive shell.
Step 8: Verify the simulation stack
ros2 launch ardupilot_gz_bringup iris_runway.launch.py- Expected result: ArduPilot DDS and Gazebo Harmonic start with the runway simulation.
Distrobox:
distrobox stop vps-dev
distrobox rm vps-devDocker:
docker stop vps-dev
docker rm vps-devSee individual package READMEs:
export MAPBOX_API_KEY=''ros2 run micro_ros_agent micro_ros_agent udp4 -p 2019./Tools/autotest/sim_vehicle.py -v ArduCopter --enable-DDS -DG --location OSRF0Then in another terminal, after GPS is detected in sitl, run:
python3 ./Tools/autotest/sat_cam_emulator.py --port 14550 --airfield-radius-m 1500 --airfield-zoom 20 --http-mjpeg-port 8090 --no-hud --ros --no-display --ros-compressed --ros-size 640x360 --pose-source simIf want to record bag file:
ros2 bag record -o <location> /camera/image_raw/compressed /ap/imu/experimental/data /ap/clock /ap/tf_static /ap/navsat /ap/gps_global_origin/filtered /ap/geopose/filtered /ap/time /ap/tf /ap/pose/filteredTo replay:
ros2 bag play <bag location>
Now to run our VPS (with bag for debugging or with SITL (with non-GPS EKF params for realtime test),
Set the .tif file location in [config file here](ngps_flight/ap_ngps_ros2/config/ngps_config.yaml)
ros2 launch ap_ngps_ros2 ngps_localization.launch.pyTo change location and get new .tif for that location, please follow steps in the gazebo_terrain_generator fork specifically for this: https://github.com/snktshrma/gazebo_terrain_generator/tree/dev/geotiff
After changing, please change the location for sitl launch as well.
For now the steps to generate a .tif are very manual but addition to sat_camemulator.py already sets a base to automaticallyt manage and autogenerate .TIF using MAPBOX. So in next updates, I'll add that feature as well and that will also help wiith setting initial guess.
- Changelog - Project history and version timeline
- Camera-IMU Calibration - Google Docs
- Non-GPS Navigation Setup - Google Docs
Ofcourse, ChatGPT Gemma4 (running locally) :)
IMPORTANT DISCLAIMER: This software is provided for research and educational applications only. The developers and contributors of this project doesn't promote and are not responsible for any misuse.
See LICENSE file.