Skip to content

Commit 800b461

Browse files
authored
Merge pull request #128 from hmakelin/nmea
Update NMEA support
2 parents bd5482e + 543e874 commit 800b461

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

48 files changed

+1440
-1193
lines changed

Makefile

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
SHELL := /bin/bash
22

3+
# Default output protocol for mock GPS messages
4+
PROTOCOL=nmea
5+
36
.PHONY: docs
47
docs:
58
@cd docs/sphinx && sphinx-build -M markdown ./source ./build
@@ -62,13 +65,19 @@ format: lint
6265
check: lint test
6366
@echo "Running code quality checks..."
6467

68+
.PHONY: dev
69+
dev:
70+
@echo "Launching GISNav locally using $(PROTOCOL) protocol..."
71+
@ros2 launch gisnav local.launch.py protocol:=$(PROTOCOL)
72+
6573
.PHONY: help
6674
help:
6775
@echo "Available targets:"
6876
@echo " docs - Build the documentation"
6977
@echo " docs preview - Preview the documentation"
7078
@echo " docs dev - Run the documentation development server"
7179
@echo " build - Build the project"
80+
@echo " dev - Run GISNav locally"
7281
@echo " dist - Create a distribution package"
7382
@echo " clean - Clean up all generated files"
7483
@echo " clean docs - Clean up documentation build files only"

docker/.env

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,3 +29,6 @@ GISNAV_VIDEO_BIND_PORT=5600
2929
#TINYOWS_MAPFILE=/etc/mapserver/default.map
3030

3131
SIM_HEADLESS=0
32+
33+
# TCP port for bridging serial output from middleware to simulation container
34+
SOCAT_BRIDGE_PORT=15000

docker/Makefile

Lines changed: 0 additions & 206 deletions
Original file line numberDiff line numberDiff line change
@@ -1,45 +1,3 @@
1-
# This Makefile is used as a Docker container orchestration tool to deploy
2-
# various Docker Compose services that support GISNav.
3-
#
4-
# The terminology used in this Makefile includes the following:
5-
# - FMU: Flight Management Unit, the onboard flight controller computer
6-
# board (e.g., Pixhawk) that runs the autopilot software.
7-
# - HIL: Hardware-In-The-Loop, a simulation mode where the autopilot runs
8-
# onboard the FMU.
9-
# - SITL: Software-In-The-Loop, a simulation mode where the autopilot is
10-
# executed offboard on a separate computer, replicating the drone's
11-
# flight dynamics and sensors, enabling testing and development without
12-
# using actual hardware.
13-
# - Offboard: Refers to services that run on a computer not carried by the
14-
# drone and not powered by the drone battery (e.g., a powerful desktop).
15-
# - Onboard: Refers to services that run on the drone itself, powered by the
16-
# drone's battery, like the FMU and onboard companion computer (e.g.,
17-
# Nvidia Jetson Nano). In the case of GISNav, all onboard services are
18-
# intended to run on the companion computer and not e.g. on the FMU.
19-
# - Middleware: Software that sits between the autopilot and GISNav, enabling
20-
# communication between them.
21-
# - QGC: QGroundControl, a ground control station software used to monitor
22-
# and control drones.
23-
# - Gazebo: A robotics simulator used to simulate the drone's environment and
24-
# its interactions with the world.
25-
#
26-
# The target options in the Makefile are as follows:
27-
# - onboard-hil-*: Targets for onboard hardware-in-the-loop services,
28-
# including GIS server, ROS middleware, autoheal, and GISNav.
29-
# - onboard-sitl-*: Targets for onboard software-in-the-loop services, with
30-
# the same services as onboard HIL but using a different middleware
31-
# configuration.
32-
# - offboard-sitl-*: Targets for offboard software-in-the-loop services,
33-
# including Gazebo simulation and QGroundControl.
34-
# - offboard-sitl-test-*: Targets for SITL testing services, which exclude
35-
# GISNav and QGC for automated testing scenarios. Gazebo in headless mode.
36-
# - offboard-sitl-dev-*: Targets for SITL development services, including
37-
# Gazebo simulation, ROS middleware, mapserver, and QGC, but
38-
# excluding GISNav whose development version is assumed to be run locally.
39-
# - demo-*: Shortcut targets for demo purposes, setting up all SITL services
40-
# offboard, including GIS server, ROS middleware, Gazebo simulation, QGC,
41-
# and GISNav.
42-
431
SHELL := /bin/bash
442

453
# Supported autopilots, must match docker/docker-compose.yaml service name
@@ -48,125 +6,6 @@ AUTOPILOTS := px4 ardupilot
486
# Prefix for Docker Compose service images
497
PROJECT_NAME := gisnav
508

51-
# Define a reusable template for creating Docker Compose targets
52-
# Parameters:
53-
# 1. The prefix for the target name.
54-
# 2. The dependency target.
55-
# 3. The optional Docker Compose override files to include (if any).
56-
# 4. The Docker Compose services to start or build - use $$* here for
57-
# autopilot, the first '$' is to escape the second '$'.
58-
define compose_template
59-
60-
# Create phony create targets with the specified prefix for each autopilot
61-
.PHONY: $(addprefix create-$(1)-, $(AUTOPILOTS))
62-
63-
# Generate rules for the build prefixed targets, depending on the specified build dependency target
64-
$(addprefix create-$(1)-, $(AUTOPILOTS)): $(if $(2),create-$(1)-%: create-$(2)-%,create-$(2)-%)
65-
# Evaluate the additional Docker Compose files
66-
$$(eval compose_files := $(if $(3),-f docker-compose.yaml $(foreach file,$(3),-f $(file))))
67-
# Build the specified Docker Compose services and create the containers
68-
@docker compose -p $(PROJECT_NAME) $$(compose_files) create $(4)
69-
70-
# Create phony build targets with the specified prefix for each autopilot
71-
.PHONY: $(addprefix build-$(1)-, $(AUTOPILOTS))
72-
73-
# Generate rules for the build prefixed targets, depending on the specified build dependency target
74-
$(addprefix build-$(1)-, $(AUTOPILOTS)): $(if $(2),build-$(1)-%: build-$(2)-%,build-$(2)-%)
75-
# Evaluate the additional Docker Compose files
76-
$$(eval compose_files := $(if $(3),-f docker-compose.yaml $(foreach file,$(3),-f $(file))))
77-
# Build the specified Docker Compose services
78-
@docker compose -p $(PROJECT_NAME) $$(compose_files) build $(4)
79-
80-
# Create phony up targets with the specified prefix for each autopilot
81-
.PHONY: $(addprefix up-$(1)-, $(AUTOPILOTS))
82-
83-
# Generate rules for the prefixed up targets, depending on the specified up
84-
# dependency target
85-
# IMPORTANT: Need to depend on create targets here before up targets to first
86-
# expose xhost to containers before running them
87-
$(addprefix up-$(1)-, $(AUTOPILOTS)): $(if $(2),up-$(1)-%: create-$(1)-% expose-xhost up-$(2)-%,up-$(1)-%: create-$(1)-% expose-xhost)
88-
# Evaluate the additional Docker Compose files
89-
$$(eval compose_files := $(if $(3),-f docker-compose.yaml $(foreach file,$(3),-f $(file))))
90-
# Run Docker Compose with the specified services
91-
@docker compose -p $(PROJECT_NAME) $$(compose_files) up -d $(4)
92-
endef
93-
94-
# Define a reusable template for creating Docker Compose middleware targets
95-
#
96-
# Parameters:
97-
# 1. The prefix for the target name.
98-
# 2. The additional Docker Compose options, such as file overrides.
99-
define middleware_template
100-
.PHONY: up-$(1)-% build-$(1)-% create-$(1)-%
101-
102-
up-$(1)-%:
103-
$$(call run_middleware, $(2), up -d)
104-
105-
build-$(1)-%:
106-
$$(call run_middleware, $(2), build)
107-
108-
create-$(1)-%:
109-
$$(call run_middleware, $(2), create)
110-
endef
111-
112-
# The run_middleware function is a helper function for executing middleware
113-
# targets with the necessary Docker Compose options.
114-
#
115-
# Parameters:
116-
# 1. Additional Docker Compose options, such as file overrides.
117-
# 2. The Docker Compose command to execute (either 'up -d' or 'build').
118-
define run_middleware
119-
@if [ "$*" = "px4" ]; then \
120-
docker compose -p $(PROJECT_NAME) $(1) $(2) mavros; \
121-
elif [ "$*" = "ardupilot" ]; then \
122-
docker compose -p $(PROJECT_NAME) $(1) $(2) mavros; \
123-
else \
124-
echo "Unsupported target '$*' (try 'px4' or 'ardupilot')."; \
125-
fi
126-
endef
127-
128-
# The empty argument check for some reason is not working in the compose_template.
129-
# So we will pass a dummy dependency as a dependency target instead of an empty
130-
# argument.
131-
.PHONY: $(addprefix build-dummy-dependency-, $(AUTOPILOTS))
132-
.PHONY: $(addprefix create-dummy-dependency-, $(AUTOPILOTS))
133-
.PHONY: $(addprefix up-dummy-dependency-, $(AUTOPILOTS))
134-
135-
build-dummy-dependency-px4:
136-
137-
create-dummy-dependency-px4:
138-
139-
up-dummy-dependency-px4:
140-
141-
build-dummy-dependency-ardupilot:
142-
143-
create-dummy-dependency-ardupilot:
144-
145-
up-dummy-dependency-ardupilot:
146-
147-
# Define middleware targets
148-
$(eval $(call middleware_template,onboard-hil-middleware,-f docker-compose.yaml -f docker-compose.serial.yaml))
149-
$(eval $(call middleware_template,onboard-sitl-middleware,))
150-
$(eval $(call middleware_template,offboard-sitl-middleware,)) # same as onboard
151-
152-
# onboard HIL services: GIS server, ROS middleware, autoheal, gscam and GISNav
153-
$(eval $(call compose_template,onboard-hil,onboard-hil-middleware,docker-compose.arm64.yaml,mapserver autoheal gscam gisnav))
154-
155-
# onboard SITL services: Same as with HIL but middleware is same as offboard (UDP, not serial)
156-
$(eval $(call compose_template,onboard-sitl,offboard-sitl-middleware,docker-compose.arm64.yaml,mapserver gscam gisnav))
157-
158-
# offboard SITL services: Gazebo simulation, QGC
159-
$(eval $(call compose_template,offboard-sitl,dummy-dependency,,$$* qgc))
160-
161-
# SITL testing services: Gazebo simulation, ROS middleware, mapserver, gscam, but excluding GISNav and QGC
162-
$(eval $(call compose_template,offboard-sitl-test,offboard-sitl-middleware,docker-compose.headless.yaml,$$* gscam mapserver))
163-
164-
# SITL development services: Gazebo simulation, ROS middleware, mapserver, QGC, gscam rviz, but excluding GISNav
165-
$(eval $(call compose_template,offboard-sitl-dev,offboard-sitl-middleware,,$$* qgc gscam mapserver rviz))
166-
167-
# All SITL services offboard: GIS server, ROS middleware, Gazebo simulation, QGC, gscam, gisnav
168-
$(eval $(call compose_template,demo,offboard-sitl-dev,,gisnav))
169-
1709
# List of Docker Compose service names that need GUI access
17110
GUI_SERVICES = px4 ardupilot qgc rviz gisnav fileserver
17211

@@ -182,48 +21,3 @@ expose-xhost:
18221
fi; \
18322
done; \
18423
fi
185-
186-
187-
# shutdown any and all services (stop and remove containers)
188-
.PHONY: down
189-
down:
190-
@docker compose -p $(PROJECT_NAME) down
191-
192-
# start existing containers
193-
# Note: You should create the containers with the "make create-..." first,
194-
# otherwise you will get an error like "no container found for project "gisnav":
195-
# not found"
196-
.PHONY: start
197-
start:
198-
@docker compose -p $(PROJECT_NAME) start
199-
200-
# shutdown any and all services (stop but do not remove containers)
201-
.PHONY: stop
202-
stop:
203-
@docker compose -p $(PROJECT_NAME) stop
204-
205-
# build all services
206-
# Note: This builds many services with overlapping functionality such as px4 and
207-
# arudpilot, you may want to be more specific about what to build
208-
.PHONY: build
209-
build:
210-
@docker compose -p $(PROJECT_NAME) build
211-
212-
.PHONY: dev-nmea
213-
dev-nmea:
214-
@echo "Setting up NMEA output..."
215-
@socat pty,link=/tmp/gisnav-pty-link,raw,echo=0 tcp:localhost:15000 || echo "Could not establish serial-to-TCP bridge" &
216-
@sleep 3 # Give socat time to create the pty
217-
@echo PTS device created at: `readlink /tmp/gisnav-pty-link`
218-
@ros2 launch gisnav local.launch.py protocol:=nmea port:=`readlink /tmp/gisnav-pty-link` baudrate:=9600
219-
220-
.PHONY: dev-uorb
221-
dev-uorb:
222-
@ros2 launch gisnav local.launch.py protocol:=uorb
223-
224-
# shortcut for demo
225-
.PHONY: demo
226-
demo:
227-
docker compose -p gisnav create gisnav
228-
$(MAKE) expose-xhost
229-
docker compose -p gisnav up gisnav px4

docker/docker-compose.commands.yaml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,12 @@ services:
4646
- "-p"
4747
- "camera_info_url:=file:///etc/gscam/camera_calibration.yaml"
4848

49+
ubx:
50+
command: "ros2 run ubx_publisher ubx_publisher_node --ros-args --log-level debug -p serial_port:=/dev/pts/0" # pty created in entrypoint script, TODO try to $(readlink /tmp/gisnav-pty-link) instead of hard-coding /dev/pts/0 here
51+
52+
nmea:
53+
command: "ros2 run nmea_publisher nmea_publisher_node --ros-args --log-level debug -p serial_port:=/dev/pts/0" # pty created in entrypoint script, TODO try to $(readlink /tmp/gisnav-pty-link) instead of hard-coding /dev/pts/0 here
54+
4955
fileserver:
5056
command: apache2ctl -D FOREGROUND
5157

docker/docker-compose.dependencies.yaml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,12 @@ name: gisnav
66

77
services:
88

9+
# TODO: have separate profiles for uros/ubx/nmea middleware
910
gisnav:
1011
depends_on:
1112
- micro-ros-agent
13+
# - ubx
14+
- nmea
1215
- mavros
1316
- gscam
1417
- mapserver

docker/docker-compose.healthcheck.yaml

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,22 @@ services:
1919
]
2020
<<: *settings
2121

22+
ubx:
23+
healthcheck:
24+
test: [ "CMD", "bash", "-c", "
25+
timeout 30 tcpdump -i any -c 1 tcp src port ${SOCAT_BRIDGE_PORT:?empty or not set} > /tmp/tcp_check.log 2>&1 &&
26+
grep -q 'TCP' /tmp/tcp_check.log"
27+
]
28+
<<: *settings
29+
30+
nmea:
31+
healthcheck:
32+
test: [ "CMD", "bash", "-c", "
33+
timeout 30 tcpdump -i any -c 1 tcp src port ${SOCAT_BRIDGE_PORT:?empty or not set} > /tmp/tcp_check.log 2>&1 &&
34+
grep -q 'TCP' /tmp/tcp_check.log"
35+
]
36+
<<: *settings
37+
2238
mavros:
2339
healthcheck:
2440
test: ["CMD", "bash", "-c", "

docker/docker-compose.labels.yaml

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,20 @@ services:
6868
homepage.name: micro-ROS agent
6969
homepage.description: uORB to ROS (PX4) middleware
7070

71+
ubx:
72+
labels:
73+
<<: *labels
74+
homepage.group: Middleware services
75+
homepage.name: UBX agent
76+
homepage.description: UBX to ROS middleware
77+
78+
nmea:
79+
labels:
80+
<<: *labels
81+
homepage.group: Middleware services
82+
homepage.name: NMEA ROS to serial bridge
83+
homepage.description: Publishes ROS NMEA sentences to serial port
84+
7185
qgc:
7286
labels:
7387
<<: *labels

docker/docker-compose.networking.yaml

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,24 @@ services:
2525
environment:
2626
UXRCE_DDS_PRT: ${UXRCE_DDS_PRT:?empty or not set}
2727

28+
ubx:
29+
networks:
30+
- dds
31+
environment:
32+
SOCAT_BRIDGE_PORT: ${SOCAT_BRIDGE_PORT:?empty or not set}
33+
GISNAV_FCU_URL: ${GISNAV_FCU_URL:?empty or not set} # todo TCP bridge only for simulation?
34+
extra_hosts:
35+
- "host.docker.internal:host-gateway" # for socat
36+
37+
nmea:
38+
networks:
39+
- dds
40+
environment:
41+
SOCAT_BRIDGE_PORT: ${SOCAT_BRIDGE_PORT:?empty or not set}
42+
GISNAV_FCU_URL: ${GISNAV_FCU_URL:?empty or not set} # todo TCP bridge only for simulation?
43+
extra_hosts:
44+
- "host.docker.internal:host-gateway" # for socat
45+
2846
qgc:
2947
network_mode: host
3048

@@ -38,6 +56,7 @@ services:
3856
network_mode: host
3957
environment:
4058
UXRCE_DDS_PRT: ${UXRCE_DDS_PRT:?empty or not set}
59+
SOCAT_BRIDGE_PORT: ${SOCAT_BRIDGE_PORT:?empty or not set}
4160
GISNAV_COMPANION_HOST: ${GISNAV_COMPANION_HOST:?empty or not set}
4261
GISNAV_CMP_MAVROS_BIND_PORT: ${GISNAV_CMP_MAVROS_BIND_PORT:?empty or not set}
4362
extra_hosts:

docker/docker-compose.ros.yaml

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,3 +57,15 @@ services:
5757
args:
5858
ROS_DISTRO: humble
5959
<<: *ros
60+
61+
ubx:
62+
build:
63+
args:
64+
ROS_DISTRO: humble
65+
<<: *ros
66+
67+
nmea:
68+
build:
69+
args:
70+
ROS_DISTRO: humble
71+
<<: *ros

docker/docker-compose.yaml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,14 @@ services:
9191
build:
9292
context: gscam
9393

94+
ubx:
95+
build:
96+
context: ubx
97+
98+
nmea:
99+
build:
100+
context: nmea
101+
94102
autoheal:
95103
image: willfarrell/autoheal
96104
restart: always

0 commit comments

Comments
 (0)