add humble-navigation2

This commit is contained in:
X-lanni
2025-05-27 19:03:40 +08:00
parent 974abb5e1e
commit e74ec539c2
1280 changed files with 204114 additions and 0 deletions
+132
View File
@@ -0,0 +1,132 @@
# Snippet for global matchers and variables
# to logically expression request conditions
# E.g. for conditionally changing redirects
(globals) {
# Use gzip compression for all responses
encode gzip
# Matcher for http request scheme. E.g. "http" or "https"
@http_scheme {
expression {http.request.scheme}=="https" || {header.X-Forwarded-Scheme}=="https" || {header.X-Forwarded-Proto}=="https"
}
# If any http scheme is "https", then use "wss"
vars @http_scheme WsScheme "wss"
# Else default to "ws"
vars WsScheme "ws"
# Matcher for forwarded request headers
@host_forwarded {
header X-Forwarded-Host *
}
# If http headers exists, then use them
vars @host_forwarded ReqHost {header.X-Forwarded-Host}
# Else default to host in request
vars ReqHost {http.request.hostport}
# Matcher for websocket connection upgrade requests
@websockets {
# Avoid case sensitivity issues when matching field values
# E.g. when values are rewritten by Codespace port forwarding
header_regexp Connection (?i)(Upgrade)
header Upgrade websocket
}
}
# Snippet for redirect with given URL queries values
# to simplify remote development with web apps
# E.g auto redirect websocket URL to match request scheme
(redirect) {
# Configure redirect to match request scheme
vars LayoutUrl "/assets/foxglove/nav2_layout.json"
vars DataSourceUrl "{vars.WsScheme}://{vars.ReqHost}{args.0}/"
redir /autoconnect "{args.0}/?ds=foxglove-websocket&ds.url={vars.DataSourceUrl}"
redir /autolayout "{args.0}/?ds=foxglove-websocket&ds.url={vars.DataSourceUrl}&layoutUrl={vars.LayoutUrl}"
}
# Snippet for dummy imports
(dummy) {
}
# Snippet for enabling mobile web app features
# to improve user experience on small screen devices
# E.g. for enabling fullscreen mode on iOS and Android
(mobile) {
# Match for directory redirects to index.html
route / {
# Inject link to manifest just after <head> tag
# https://developer.mozilla.org/docs/Web/Manifest
replace `<head>` `<head><link rel="manifest" href="manifest.json" crossorigin="use-credentials"/>`
}
# Redirect relative handle_path'ed manifest.json to /manifests directory
redir /manifest.json /assets{http.request.orig_uri.path.dir}manifest.json
}
# Snippet for hosted web app using websockets
# to serve static files and reverse proxying connections
# E.g. for serving GzWeb and Foxglove web apps
(app) {
# handle and strip path prefix from redirect
handle_path {args.0}/* {
# Set root directory for static files
root * {http.vars.root}{args.0}
# Enable mobile web app features
import mobile
# Reverse proxy websockets to backend address
reverse_proxy @websockets {args.1}
# Import custom snippets
import {args.2} {args.0}
}
}
# Listen for http requests on port 8080
# regardless of hostname or domain address
# E.g. whatever Codespaces assigns to host
:8080 {
# Include global matchers and variables
import globals
root * {$ROOT_SRV:/srv}
file_server browse
# Handle root content
# I.e. assets internal to workspace
handle /* {
# Template manifest.json files
templates */manifest.json {
mime application/json
}
}
# Handle nav2 web app
# I.e. main landing page
handle_path /nav2/* {
root * {http.vars.root}/nav2
import mobile
# Render markdown files as html
templates
}
# Matcher for requests without browse query
@no_browse {
path /
not query browse=true
}
# Redirect to nav2 web app by default
redir @no_browse /nav2/
# Import app snippets for web apps
import app "/gzweb" "localhost:9090" "dummy"
import app "/foxglove" "localhost:8765" "redirect"
# Handle glances web app
redir /glances /glances/
handle_path /glances/* {
import mobile
# Reverse proxy to glances backend
reverse_proxy * "localhost:61208"
}
# For debugging
# log {
# output file /var/log/caddy/server.log
# }
}
@@ -0,0 +1,40 @@
{
"name": "Foxglove: {{placeholder "http.vars.ReqHost"}}",
"short_name": "Foxglove: {{placeholder "http.vars.ReqHost"}}",
"icons": [
{
"src": "/media/icons/foxglove/any_icon_x512.webp",
"sizes": "512x512",
"type": "image/webp",
"purpose": "any"
},
{
"src": "/media/icons/foxglove/maskable_icon_x512.webp",
"sizes": "512x512",
"type": "image/webp",
"purpose": "maskable"
}
],
"id": "/foxglove/",
"start_url": "/foxglove/autoconnect",
"theme_color": "#6F3BE8",
"background_color": "#6F3BE8",
"display": "fullscreen",
"shortcuts" : [
{
"name": "Auto Connect",
"url": "/foxglove/autoconnect",
"description": "Auto connect to default data source"
},
{
"name": "Auto Layout",
"url": "/foxglove/autolayout",
"description": "Auto connect using default layout"
},
{
"name": "Manual Connect",
"url": "/foxglove/",
"description": "Manually connect to data source"
}
]
}
@@ -0,0 +1,463 @@
{
"configById": {
"3D!18i6zy7": {
"layers": {
"845139cb-26bc-40b3-8161-8ab60af4baf5": {
"visible": true,
"frameLocked": true,
"label": "Grid",
"instanceId": "845139cb-26bc-40b3-8161-8ab60af4baf5",
"layerId": "foxglove.Grid",
"size": 10,
"divisions": 10,
"lineWidth": 1,
"color": "#A0A0A4ff",
"position": [
0,
0,
0
],
"rotation": [
0,
0,
0
],
"order": 1
}
},
"cameraState": {
"perspective": true,
"distance": 21.05263157877764,
"phi": 38.925517117715195,
"thetaOffset": -138.92710744521386,
"targetOffset": [
-2.6847696124888896,
0.2191229688744439,
3.6086809432821955e-16
],
"target": [
0,
0,
0
],
"targetOrientation": [
0,
0,
0,
1
],
"fovy": 45,
"near": 0.5,
"far": 5000
},
"followMode": "follow-pose",
"scene": {
"transforms": {
"showLabel": false,
"editable": false,
"labelSize": 0.049999999999999975,
"enablePreloading": false,
"lineWidth": 2
}
},
"transforms": {
"frame:camera_link": {
"visible": false
},
"frame:camera_depth_frame": {
"visible": false
},
"frame:camera_depth_optical_frame": {
"visible": false
},
"frame:camera_rgb_frame": {
"visible": false
},
"frame:camera_rgb_optical_frame": {
"visible": false
},
"frame:imu_link": {
"visible": false
},
"frame:caster_back_right_link": {
"visible": false
},
"frame:caster_back_left_link": {
"visible": false
},
"frame:odom": {
"visible": true
},
"frame:base_footprint": {
"visible": true
},
"frame:wheel_left_link": {
"visible": false
},
"frame:wheel_right_link": {
"visible": false
},
"frame:base_link": {
"visible": false
},
"frame:base_scan": {
"visible": false
},
"frame:map": {
"visible": true
}
},
"topics": {
"/scan": {
"visible": true,
"colorField": "intensity",
"colorMode": "flat",
"colorMap": "turbo",
"pointSize": 5,
"flatColor": "#ff0000"
},
"/global_costmap/costmap": {
"visible": true,
"maxColor": "#E800174d",
"unknownColor": "#5700ff4d",
"minColor": "#ffffff4d",
"invalidColor": "#ff00ff4d",
"colorMode": "costmap",
"alpha": 0.3
},
"/global_costmap/obstacle_layer": {
"visible": false
},
"/global_costmap/voxel_marked_cloud": {
"visible": false
},
"/goal_pose": {
"visible": false
},
"/local_costmap/costmap": {
"visible": false
},
"/local_costmap/voxel_layer": {
"visible": false
},
"/local_costmap/clearing_endpoints": {
"visible": false,
"colorField": "x",
"colorMode": "colormap",
"colorMap": "turbo"
},
"/map": {
"visible": true,
"minColor": "#ffffff",
"maxColor": "#000000",
"unknownColor": "#708986ff",
"frameLocked": false,
"colorMode": "map"
},
"/amcl_pose": {
"visible": false
},
"/local_plan": {
"visible": true,
"lineWidth": 0.01,
"gradient": [
"#c8ff00c7",
"#00c8ffba"
]
},
"/plan": {
"visible": false,
"gradient": [
"rgba(124, 107, 255, 1)",
"#ff6b6b"
],
"lineWidth": 1
},
"/plan_smoothed": {
"visible": false
},
"/received_global_plan": {
"visible": true,
"gradient": [
"#ff0000c7",
"#6b70ffc2"
],
"lineWidth": 0.02,
"type": "line",
"arrowScale": [
0.02,
0.0015,
0.0015
]
},
"/transformed_global_plan": {
"visible": false
},
"/robot_description": {
"visible": false
},
"/cost_cloud": {
"visible": false
},
"/initialpose": {
"visible": false
}
},
"publish": {
"type": "pose_estimate",
"poseTopic": "/move_base_simple/goal",
"pointTopic": "",
"poseEstimateTopic": "/initialpose",
"poseEstimateXDeviation": 0.5,
"poseEstimateYDeviation": 0.5,
"poseEstimateThetaDeviation": 0.26179939
},
"followTf": "map"
},
"DiagnosticSummary!3bo4e39": {
"minLevel": 0,
"pinnedIds": [],
"hardwareIdFilter": "",
"topicToRender": "/diagnostics",
"sortByLevel": true
},
"RosOut!1iib9dq": {
"searchTerms": [],
"minLogLevel": 1
},
"3D!2agiaqk": {
"layers": {
"845139cb-26bc-40b3-8161-8ab60af4baf5": {
"visible": false,
"frameLocked": true,
"label": "Grid",
"instanceId": "845139cb-26bc-40b3-8161-8ab60af4baf5",
"layerId": "foxglove.Grid",
"size": 10,
"divisions": 10,
"lineWidth": 1,
"color": "#A0A0A4ff",
"position": [
0,
0,
0
],
"rotation": [
0,
0,
0
],
"order": 1
}
},
"cameraState": {
"perspective": true,
"distance": 4.078136514883917,
"phi": 56.068374260572,
"thetaOffset": 92.50000000000723,
"targetOffset": [
0.03816360663426963,
0.15755079607173259,
7.341598429161142e-18
],
"target": [
0,
0,
0
],
"targetOrientation": [
0,
0,
0,
1
],
"fovy": 45,
"near": 0.5,
"far": 5000
},
"followMode": "follow-pose",
"scene": {
"transforms": {
"showLabel": true,
"editable": false,
"labelSize": 0.049999999999999975,
"enablePreloading": false,
"lineWidth": 2
}
},
"transforms": {
"frame:camera_link": {
"visible": false
},
"frame:camera_depth_frame": {
"visible": false
},
"frame:camera_depth_optical_frame": {
"visible": false
},
"frame:camera_rgb_frame": {
"visible": false
},
"frame:camera_rgb_optical_frame": {
"visible": false
},
"frame:imu_link": {
"visible": false
},
"frame:caster_back_right_link": {
"visible": false
},
"frame:caster_back_left_link": {
"visible": false
},
"frame:odom": {
"visible": true
},
"frame:base_footprint": {
"visible": true
},
"frame:wheel_left_link": {
"visible": false
},
"frame:wheel_right_link": {
"visible": false
},
"frame:base_link": {
"visible": false
},
"frame:base_scan": {
"visible": false
},
"frame:map": {
"visible": true
}
},
"topics": {
"/scan": {
"visible": true,
"colorField": "intensity",
"colorMode": "flat",
"colorMap": "turbo",
"pointSize": 5,
"flatColor": "#ff0000"
},
"/global_costmap/costmap": {
"visible": true,
"maxColor": "#E800174d",
"unknownColor": "#5700ff4d",
"minColor": "#ffffff4d",
"invalidColor": "#ff00ff4d",
"colorMode": "costmap",
"alpha": 0.3
},
"/global_costmap/obstacle_layer": {
"visible": false
},
"/global_costmap/voxel_marked_cloud": {
"visible": false
},
"/goal_pose": {
"visible": false
},
"/local_costmap/costmap": {
"visible": false
},
"/local_costmap/voxel_layer": {
"visible": false
},
"/local_costmap/clearing_endpoints": {
"visible": false,
"colorField": "x",
"colorMode": "colormap",
"colorMap": "turbo"
},
"/map": {
"visible": true,
"minColor": "#ffffff",
"maxColor": "#000000",
"unknownColor": "#708986ff",
"frameLocked": false,
"colorMode": "map"
},
"/amcl_pose": {
"visible": false
},
"/local_plan": {
"visible": true,
"lineWidth": 0.01,
"gradient": [
"#c8ff00c7",
"#00c8ffba"
]
},
"/plan": {
"visible": false,
"gradient": [
"rgba(124, 107, 255, 1)",
"#ff6b6b"
],
"lineWidth": 1
},
"/plan_smoothed": {
"visible": false
},
"/received_global_plan": {
"visible": true,
"gradient": [
"#ff0000c7",
"#6b70ffc2"
],
"lineWidth": 0.02,
"type": "line",
"arrowScale": [
0.02,
0.0015,
0.0015
]
},
"/transformed_global_plan": {
"visible": false
},
"/robot_description": {
"visible": true
},
"/cost_cloud": {
"visible": false
},
"/initialpose": {
"visible": false
}
},
"publish": {
"type": "pose_estimate",
"poseTopic": "/move_base_simple/goal",
"pointTopic": "",
"poseEstimateTopic": "/initialpose",
"poseEstimateXDeviation": 0.5,
"poseEstimateYDeviation": 0.5,
"poseEstimateThetaDeviation": 0.26179939
},
"followTf": "base_link"
}
},
"globalVariables": {},
"userNodes": {},
"playbackConfig": {
"speed": 1
},
"layout": {
"first": "3D!18i6zy7",
"second": {
"first": "DiagnosticSummary!3bo4e39",
"second": {
"first": "RosOut!1iib9dq",
"second": "3D!2agiaqk",
"direction": "column"
},
"direction": "column",
"splitPercentage": 28.227360308285164
},
"direction": "row",
"splitPercentage": 74.87855655794587
}
}
@@ -0,0 +1,40 @@
{
"name": "Glances: {{placeholder "http.vars.ReqHost"}}",
"short_name": "Glances: {{placeholder "http.vars.ReqHost"}}",
"icons": [
{
"src": "/media/icons/glances/any_icon_x512.webp",
"sizes": "512x512",
"type": "image/webp",
"purpose": "any"
},
{
"src": "/media/icons/glances/maskable_icon_x512.webp",
"sizes": "512x512",
"type": "image/webp",
"purpose": "maskable"
}
],
"id": "/glances/",
"start_url": "/glances/",
"theme_color": "#2C363F",
"background_color": "#2C363F",
"display": "fullscreen",
"shortcuts" : [
{
"name": "Refresh 1sec",
"url": "/glances/1",
"description": "Refresh page every 1 second"
},
{
"name": "Refresh 5sec",
"url": "/glances/5",
"description": "Refresh page every 5 seconds"
},
{
"name": "Refresh 10sec",
"url": "/glances/10",
"description": "Refresh page every 10 seconds"
}
]
}
@@ -0,0 +1,23 @@
{
"name": "Gzweb: {{placeholder "http.vars.ReqHost"}}",
"short_name": "Gzweb: {{placeholder "http.vars.ReqHost"}}",
"icons": [
{
"src": "/media/icons/gzweb/any_icon_x512.webp",
"sizes": "512x512",
"type": "image/webp",
"purpose": "any"
},
{
"src": "/media/icons/gzweb/maskable_icon_x512.webp",
"sizes": "512x512",
"type": "image/webp",
"purpose": "maskable"
}
],
"id": "/gzweb/",
"start_url": "/gzweb/",
"theme_color": "#ffffff",
"background_color": "#ffffff",
"display": "fullscreen"
}
@@ -0,0 +1,23 @@
{
"name": "Nav2: {{placeholder "http.vars.ReqHost"}}",
"short_name": "Nav2: {{placeholder "http.vars.ReqHost"}}",
"icons": [
{
"src": "/media/icons/nav2/any_icon_x512.webp",
"sizes": "512x512",
"type": "image/webp",
"purpose": "any"
},
{
"src": "/media/icons/nav2/maskable_icon_x512.webp",
"sizes": "512x512",
"type": "image/webp",
"purpose": "maskable"
}
],
"id": "/nav2/",
"start_url": "/nav2/",
"theme_color": "#ffffff",
"background_color": "#ffffff",
"display": "standalone"
}
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,36 @@
{{$pathParts := splitList "/" .OriginalReq.URL.Path}}
{{$markdownFilename := default "index" (slice $pathParts 2 | join "/")}}
{{$markdownFilePath := printf "/%s.md" $markdownFilename}}
{{if not (fileExists $markdownFilePath)}}{{httpError 404}}{{end}}
{{$markdownFile := (include $markdownFilePath | splitFrontMatter)}}
{{$title := default $markdownFilename $markdownFile.Meta.title}}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, minimal-ui">
<title>{{$title}}</title>
<meta name="color-scheme" content="light dark">
<link rel="stylesheet" href="github-markdown.css">
<link rel="icon" type="image/webp" href="/media/icons/nav2/any_icon_x512.webp">
<style>
body {
box-sizing: border-box;
min-width: 200px;
max-width: 980px;
margin: 0 auto;
padding: 45px;
}
@media (prefers-color-scheme: dark) {
body {
background-color: #0d1117;
}
}
</style>
</head>
<body>
<article class="markdown-body">{{markdown $markdownFile.Body}}</article>
</body>
</html>
@@ -0,0 +1,51 @@
{
"title": "Nav2 App"
}
## Progressive Web Apps
| PWAs | Shortcuts |
|-|-|
| [<img src="/media/icons/foxglove/any_icon_x512.webp" height="64">](/foxglove/autoconnect)<br>**Foxglove** | [**Auto Connect**](/foxglove/autoconnect)<br>[Auto Layout](/foxglove/autolayout)<br>[Manual](/foxglove/) |
| [<img src="/media/icons/gzweb/any_icon_x512.webp" height="64">](/gzweb/)<br>**Gzweb** | [**Auto Connect**](/gzweb/) |
| [<img src="/media/icons/glances/any_icon_x512.webp" height="64">](/glances/)<br>**Glances** | [**System Monitor**](/glances/)<br>[Refresh 1sec](/glances/1)<br>[Refresh 10sec](/glances/10) |
| [<img src="/media/icons/nav2/any_icon_x512.webp" height="64">](/nav2/)<br>**Nav2** | [**App Launcher**](/nav2/)<br>[File Browser](/?browse=true) |
## External Resources
For more related documentation:
- [Nav2 Documentation](https://navigation.ros.org)
- [Development Guides](https://navigation.ros.org/development_guides)
- [Dev Containers](https://navigation.ros.org/development_guides/devcontainer_docs)
## Session Info
Useful information about host server and remote client:
|Key | Value |
|-|-|
| Host | `{{.Host}}` |
| Remote IP | `{{placeholder "http.request.remote.host"}}` |
| Date | `{{now}}` |
### Server Diagnostics
<details>
<summary>Websocket Debug</summary>
For troubleshooting websocket connections:
|Key | Value |
|-|-|
| `header.X-Forwarded-Host` | `{{placeholder "http.request.header.X-Forwarded-Host"}}` |
| `http.request.hostport` | `{{placeholder "http.request.hostport"}}` |
| `http.vars.ReqHost` | `{{placeholder "http.vars.ReqHost"}}` |
|Key | Value |
|-|-|
| `http.request.scheme` | `{{placeholder "http.request.scheme"}}` |
| `header.X-Forwarded-Scheme` | `{{placeholder "http.request.header.X-Forwarded-Scheme"}}` |
| `header.X-Forwarded-Proto` | `{{placeholder "http.request.header.X-Forwarded-Proto"}}` |
| `http.vars.WsScheme` | `{{placeholder "http.vars.WsScheme"}}` |
</details>
@@ -0,0 +1,61 @@
{
"name": "Nav2",
"build": {
"dockerfile": "../Dockerfile",
"context": "..",
"target": "visualizer",
"cacheFrom": "ghcr.io/ros-planning/navigation2:humble"
},
"runArgs": [
// "--cap-add=SYS_PTRACE", // enable debugging, e.g. gdb
// "--ipc=host", // shared memory transport with host, e.g. rviz GUIs
// "--network=host", // network access to host interfaces, e.g. eth0
// "--pid=host", // DDS discovery with host, without --network=host
// "--privileged", // device access to host peripherals, e.g. USB
// "--security-opt=seccomp=unconfined", // enable debugging, e.g. gdb
],
"workspaceFolder": "/opt/overlay_ws/src/navigation2",
"workspaceMount": "source=${localWorkspaceFolder},target=${containerWorkspaceFolder},type=bind",
"onCreateCommand": ".devcontainer/on-create-command.sh",
"updateContentCommand": ".devcontainer/update-content-command.sh",
"postCreateCommand": ".devcontainer/post-create-command.sh",
"remoteEnv": {
"OVERLAY_MIXINS": "release ccache lld",
"CCACHE_DIR": "/tmp/.ccache"
},
"mounts": [
{
"source": "ccache-${devcontainerId}",
"target": "/tmp/.ccache",
"type": "volume"
},
{
"source": "overlay-${devcontainerId}",
"target": "/opt/overlay_ws",
"type": "volume"
}
],
"features": {
// "ghcr.io/devcontainers/features/desktop-lite:1": {},
"ghcr.io/devcontainers/features/github-cli:1": {}
},
"customizations": {
"codespaces": {
"openFiles": [
"doc/development/codespaces.md"
]
},
"vscode": {
"settings": {},
"extensions": [
"althack.ament-task-provider",
"eamodio.gitlens",
"esbenp.prettier-vscode",
"GitHub.copilot",
"ms-iot.vscode-ros",
"streetsidesoftware.code-spell-checker",
"twxs.cmake"
]
}
}
}
+12
View File
@@ -0,0 +1,12 @@
#!/bin/bash
# Immediately catch all errors
set -eo pipefail
# Uncomment for debugging
# set -x
# env
git config --global --add safe.directory "*"
.devcontainer/update-content-command.sh
+18
View File
@@ -0,0 +1,18 @@
#!/bin/bash
# Immediately catch all errors
set -eo pipefail
# Uncomment for debugging
# set -x
# env
# Enable autocomplete for user
cp /etc/skel/.bashrc ~/
# Check if srv folder exists
if [ -d "$ROOT_SRV" ]; then
# Setup Nav2 web app
for dir in $OVERLAY_WS/src/navigation2/.devcontainer/caddy/srv/*; \
do if [ -d "$dir" ]; then ln -s "$dir" $ROOT_SRV; fi done
fi
+60
View File
@@ -0,0 +1,60 @@
#!/bin/bash
# Immediately catch all errors
set -eo pipefail
# Uncomment for debugging
# set -x
# env
cd $OVERLAY_WS
colcon cache lock
BUILD_UNFINISHED=$(
colcon list \
--names-only \
--packages-skip-build-finished \
| xargs)
echo BUILD_UNFINISHED: $BUILD_UNFINISHED
BUILD_FAILED=$(
colcon list \
--names-only \
--packages-select-build-failed \
| xargs)
echo BUILD_FAILED: $BUILD_FAILED
BUILD_INVALID=$(
colcon list \
--names-only \
--packages-select-cache-invalid \
--packages-select-cache-key build \
| xargs)
echo BUILD_INVALID: $BUILD_INVALID
BUILD_PACKAGES=""
if [ -n "$BUILD_UNFINISHED" ] || \
[ -n "$BUILD_FAILED" ] || \
[ -n "$BUILD_INVALID" ]
then
BUILD_PACKAGES=$(
colcon list \
--names-only \
--packages-above \
$BUILD_UNFINISHED \
$BUILD_FAILED \
$BUILD_INVALID \
| xargs)
fi
echo BUILD_PACKAGES: $BUILD_PACKAGES
# colcon clean packages --yes \
# --packages-select ${BUILD_PACKAGES} \
# --base-select install
. $UNDERLAY_WS/install/setup.sh
colcon build \
--symlink-install \
--mixin $OVERLAY_MIXINS \
--packages-select ${BUILD_PACKAGES}