Removed desktop specific items
Create and publish a Docker image / build-and-push-image (push) Failing after 28s Details
Build Docs / build (push) Failing after 2m20s Details

This commit is contained in:
Alex Davies 2024-09-17 12:30:08 -03:00
parent 824112f661
commit 1011396402
15 changed files with 65 additions and 557 deletions

3
.gitmodules vendored
View File

@ -1,3 +0,0 @@
[submodule "PX4-Autopilot"]
path = PX4-Autopilot
url = https://git.spirirobotics.com/Spiri/PX4-Autopilot.git

@ -1 +0,0 @@
Subproject commit dd0fb2ef11fc6882c005b16801b1ef47b5d8683b

65
docker-compose.yml Normal file
View File

@ -0,0 +1,65 @@
version: '3.8'
services:
ardupilot:
image: git.spirirobotics.com/spiri/ardupilot:spiri-master
command: >
./Tools/autotest/sim_vehicle.py -v copter --no-rebuild
--out=udpin:0.0.0.0:5000
--enable-dds
stdin_open: true
tty: true
mavproxy:
image: git.spirirobotics.com/spiri/services-mavproxy:main
command: >
mavproxy.py --non-interactive
--out=udpbcast:192.168.7.255:14560
--out=tcpin:0.0.0.0:5760
--master=udpout:ardupilot:5000
restart: always
ports:
- 5760:5760
mavros:
#This service bridges our mavlink-based robot-coprosessor into ROS
#In this example it connects to a simulated coprocessor.
image: git.spirirobotics.com/spiri/services-ros1-mavros:master
command: roslaunch mavros px4.launch fcu_url:="udp://:14555@mavproxy:14550" tgt_system:="1"
environment:
- "ROS_MASTER_URI=http://ros-master:11311"
depends_on:
ros-master:
condition: service_healthy
mavproxy:
condition: service_started
restart: always
deploy:
resources:
limits:
# cpus: '0.01'
memory: 200M
ulimits:
nofile:
soft: 1024
hard: 524288
ros-master:
image: git.spirirobotics.com/spiri/services-ros1-core:main
command: stdbuf -o L roscore
environment:
- "ROS_MASTER_URI=http://ros-master:11311"
restart: always
ports:
- "127.0.0.1:11311:11311"
deploy:
resources:
limits:
memory: 1G
# Madness, setting a low ulimit here fixes memory leaks
# https://answers.ros.org/question/336963/rosout-high-memory-usage/
ulimits:
nofile:
soft: 1024
hard: 524288

View File

@ -1,20 +0,0 @@
# Minimal makefile for Sphinx documentation
#
# You can set these variables from the command line, and also
# from the environment for the first two.
SPHINXOPTS ?=
SPHINXBUILD ?= sphinx-build
SOURCEDIR = source
BUILDDIR = build
# Put it first so that "make" without argument is like "make help".
help:
@$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
.PHONY: help Makefile
# Catch-all target: route all unknown targets to Sphinx using the new
# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
%: Makefile
@$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)

View File

@ -1,11 +0,0 @@
If you have a correctly configured sphinx environment you can build this project
using `make html latexpdf`.
You can also use nektos/act to build this project in the same way our build does.
```bash
cd ../ #Make sure you're in the project root, you should have a hidden folder
# named ./.github/workflows available.
act --artifact-server-path ./doc-build
```
Your compiled doc project will now be in the ./doc-build folder.

View File

@ -1,35 +0,0 @@
@ECHO OFF
pushd %~dp0
REM Command file for Sphinx documentation
if "%SPHINXBUILD%" == "" (
set SPHINXBUILD=sphinx-build
)
set SOURCEDIR=source
set BUILDDIR=build
%SPHINXBUILD% >NUL 2>NUL
if errorlevel 9009 (
echo.
echo.The 'sphinx-build' command was not found. Make sure you have Sphinx
echo.installed, then set the SPHINXBUILD environment variable to point
echo.to the full path of the 'sphinx-build' executable. Alternatively you
echo.may add the Sphinx directory to PATH.
echo.
echo.If you don't have Sphinx installed, grab it from
echo.https://www.sphinx-doc.org/
exit /b 1
)
if "%1" == "" goto help
%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%
goto end
:help
%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%
:end
popd

View File

@ -1,34 +0,0 @@
.wy-side-nav-search {
background: #FFFFFF !important;
}
.wy-nav-side {
background-color: #FFFFFF !important;
}
/* Add borders and box-shadow */
.wy-side-nav {
border: 1px solid #899CA3 !important;
}
.logo {
width: 100px !important;
}
.wy-menu-vertical a {
color: #899CA3 !important; /* Change to your desired color */
}
.document-title {
color: #000 !important;
font-size: 24px !important;
text-transform: uppercase !important;
}
.icon-home {
font-weight: bold !important;
text-transform: uppercase !important;
color: #000 !important;
}

View File

@ -1,65 +0,0 @@
# Configuration file for the Sphinx documentation builder.
#
# For the full list of built-in configuration values, see the documentation:
# https://www.sphinx-doc.org/en/master/usage/configuration.html
# -- Project information -----------------------------------------------------
# https://www.sphinx-doc.org/en/master/usage/configuration.html#project-information
import sphinx_rtd_theme
project = "spiri-sdk"
copyright = "2024, Spiri Robotics"
author = "Spiri Robotics"
html_logo = "logos/SPIRI_STLockup_Mixed_RGB.png" # For HTML output
html_logo_width = '200px'
latex_logo = "logos/SPIRI_STLockup_Mixed_RGB.png"
latex_logo_width = '5cm'
# -- General configuration ---------------------------------------------------
# https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration
extensions = [
"sphinx.ext.duration",
"sphinx.ext.doctest",
"sphinx.ext.autodoc",
"sphinx.ext.autosummary",
"sphinx.ext.intersphinx",
"sphinx.ext.todo",
]
numfig = True
todo_include_todos = True
todo_emit_warnings = True
todo_link_only = True
templates_path = ["_templates"]
exclude_patterns = []
# -- Options for HTML output -------------------------------------------------
# https://www.sphinx-doc.org/en/master/usage/configuration.html#options-for-html-output
html_theme = "sphinx_rtd_theme"
html_theme_path = [sphinx_rtd_theme.get_html_theme_path()]
html_static_path = ['_static']
html_css_files = [
'custom.css',
]
html_theme_options = {
'collapse_navigation': True,
'sticky_navigation': True,
'navigation_depth': 4, #could be set to -1 if we want unlimited depth
'includehidden': True,
'titles_only': False
}
latex_engine = "xelatex"
# Configure LaTeX options for PDF generation

View File

@ -1,20 +0,0 @@
.. spiri-sdk documentation master file, created by
sphinx-quickstart on Wed Feb 14 11:51:45 2024.
You can adapt this file completely to your liking, but it should at least
contain the root `toctree` directive.
Welcome to spiri-sdk's documentation!
============================================
.. toctree::
:maxdepth: 2
:caption: Contents:
Indices and tables
==================
* :ref:`genindex`
* :ref:`modindex`
* :ref:`search`

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

View File

View File

@ -1 +0,0 @@
spiri:$5$kasm$bc2Fwutowq1kSiQCv2rNYVgn8.bJeARYMydYCvU1WKC:wo

View File

@ -1,107 +0,0 @@
version: "3.8"
services:
mavros:
image: git.spirirobotics.com/spiri/services-ros1-mavros:master
command: roslaunch mavros px4.launch fcu_url:="udp://:${MAVROS_SIM_FCU_PORT}@127.0.0.1:${MAVROS_SIM_GCS_PORT:-14557}" tgt_system:=${DRONE_SYS_ID:-1}
environment:
- "ROS_MASTER_URI=http://ros-master:${ROS_MASTER_PORT:-11311}"
depends_on:
ros-master:
condition: service_healthy
restart: always
deploy:
resources:
limits:
memory: 200M
ulimits:
nofile:
soft: 1024
hard: 524288
ports:
- "${MAVROS_SIM_FCU_PORT:-14540}:${MAVROS_SIM_FCU_PORT:-14540}/udp"
- "${MAVROS_SIM_GCS_PORT:-14557}:${MAVROS_SIM_GCS_PORT:-14557}/udp"
ros-master:
image: git.spirirobotics.com/spiri/services-ros1-core:main
command: stdbuf -o L roscore --port ${ROS_MASTER_PORT:-11311}
environment:
- "ROS_MASTER_URI=http://ros-master:${ROS_MASTER_PORT:-11311}"
restart: always
ports:
- "127.0.0.1:${ROS_MASTER_PORT:-11311}:${ROS_MASTER_PORT:-11311}"
deploy:
resources:
limits:
memory: 1G
ulimits:
nofile:
soft: 1024
hard: 524288
# gscam:
# image: git.spirirobotics.com/spiri/services-ros1-gscam_all_in_one:main
# runtime: nvidia
# environment:
# ROS_MASTER_URI: http://localhost:11311
# ROS_LOG_LEVEL: DEBUG
# PORT_GSCAM_CONFIG: >
# nvarguscamerasrc sensor-id=0 aelock=true awblock=true ! video/x-raw(memory:NVMM), width=(int)$(arg width), height=(int)$(arg height), format=(string)NV12, framerate=(fraction)$(arg fps)/1 ! nvvidconv flip-method=0 ! video/x-raw, format=(string)BGRx ! videoconvert ! video/x-raw, format=(string)BGR
# STARBOARD_GSCAM_CONFIG: >
# nvarguscamerasrc sensor-id=1 aelock=true awblock=true ! video/x-raw(memory:NVMM), width=(int)$(arg width), height=(int)$(arg height), format=(string)NV12, framerate=(fraction)$(arg fps)/1 ! nvvidconv flip-method=0 ! video/x-raw, format=(string)BGRx ! videoconvert ! video/x-raw, format=(string)BGR
# volumes:
# - /tmp/argus_socket:/tmp/argus_socket
#
# udp-stream:
# image: git.spirirobotics.com/spiri/services-ros1-gscam_all_in_one:main
# privileged: true
# runtime: nvidia
# network_mode: host
# environment:
# DISPLAY: ":0"
# volumes:
# - /tmp/argus_socket:/tmp/argus_socket
# - /tmp/.X11-unix:/tmp/.X11-unix
# - /var/run/xauth/:/var/run/xauth/
# command: >
# gst-launch-1.0
# nvarguscamerasrc sensor-id=0
# ! 'video/x-raw(memory:NVMM), width=(int)1280, height=(int)720, format=(string)NV12, framerate=(fraction)60/1'
# ! tee name=raw
# raw. ! queue
# ! nvegltransform ! nveglglessink sync=false async=false
# raw. ! queue
# ! videorate max-rate=30 drop-only=true
# ! queue max-size-buffers=3 leaky=downstream
# ! nvv4l2h265enc
# bitrate=2000000
# iframeinterval=300
# vbv-size=33333
# insert-sps-pps=true
# control-rate=constant_bitrate
# profile=Main
# num-B-Frames=0
# ratecontrol-enable=true
# preset-level=UltraFastPreset
# EnableTwopassCBR=false
# maxperf-enable=true
# ! rtph265pay name=pay0 pt=96 config-interval=-1 mtu=1400
# ! udpsink host=192.168.1.100 auto-multicast=false port=5600 sync=false async=false
#
# mavproxy:
# image: git.spirirobotics.com/spiri/services-mavproxy:main
# command: >
# mavproxy.py --non-interactive
# --out=udpin:0.0.0.0:14551
# --out=udpin:0.0.0.0:14550
# --out=tcpin:0.0.0.0:5760
# --master=/dev/ttyTHS2 --baudrate 921600
# restart: always
# devices:
# - "/dev/ttyTHS2:/dev/ttyTHS2"
# ports:
# - "14550:14550/udp"
# - "5760:5760/tcp"
#
#

View File

@ -1,229 +0,0 @@
#!/bin/env python3
import typer
import os
import sys
import contextlib
import pathlib
import time
import functools
from typing import List
from loguru import logger
import sh
import atexit
logger.remove()
logger.add(
sys.stdout, format="<green>{time}</green> <level>{level}</level> {extra} {message}"
)
px4Path = os.environ.get("SPIRI_SIM_PX4_PATH", "/opt/spiri-sdk/PX4-Autopilot/")
logger.info(f"SPIRI_SIM_PX4_PATH={px4Path}")
app = typer.Typer()
# This is a list of processes that we need to .kill and .wait for on exit
processes = []
class outputLogger:
"""
Logs command output to loguru
"""
def __init__(self, name, instance):
self.name = name
self.instance = instance
def __call__(self, message):
with logger.contextualize(cmd=self.name, instance=self.instance):
if message.endswith("\n"):
message = message[:-1]
# ToDo, this doesn't work because the output is coloured
if message.startswith("INFO"):
message = message.lstrip("INFO")
logger.info(message)
elif message.startswith("WARN"):
message = message.lstrip("WARN")
logger.warning(message)
elif message.startswith("ERROR"):
message = message.lstrip("ERROR")
logger.error(message)
elif message.startswith("DEBUG"):
message = message.lstrip("DEBUG")
logger.debug(message)
else:
logger.info(message)
@contextlib.contextmanager
def modified_environ(*remove, **update):
"""
Temporarily updates the ``os.environ`` dictionary in-place.
The ``os.environ`` dictionary is updated in-place so that the modification
is sure to work in all situations.
:param remove: Environment variables to remove.
:param update: Dictionary of environment variables and values to add/update.
"""
env = os.environ
update = update or {}
remove = remove or []
# List of environment variables being updated or removed.
stomped = (set(update.keys()) | set(remove)) & set(env.keys())
# Environment variables and values to restore on exit.
update_after = {k: env[k] for k in stomped}
# Environment variables and values to remove on exit.
remove_after = frozenset(k for k in update if k not in env)
try:
env.update(update)
[env.pop(k, None) for k in remove]
yield
finally:
env.update(update_after)
[env.pop(k) for k in remove_after]
def wait_for_gazebo(timeout=60, interval=1):
start_time = time.time()
while time.time() - start_time < timeout:
try:
# Run the 'gz topic list' command
topics = sh.gz("topic", "-l").strip()
if topics:
logger.info("Gazebo Ignition is running.")
return True
except sh.ErrorReturnCode:
# If the command fails, Gazebo might not be running yet
pass
logger.info(
f"Gazebo Ignition is not running. Retrying in {interval} seconds..."
)
time.sleep(interval)
logger.error("Timeout reached. Gazebo Ignition is not running.")
return False
def wait_for_docker_on_port(port, timeout=60, interval=1):
start_time = time.time()
while time.time() - start_time < timeout:
try:
# Check if there's a working docker daemon listening at port
with modified_environ(DOCKER_HOST=f"tcp://localhost:{port}"):
sh.docker("version")
except sh.ErrorReturnCode:
# If the command fails, Gazebo might not be running yet
pass
logger.info(f"Docker port is not running. Retrying in {interval} seconds...")
time.sleep(interval)
logger.error("Timeout reached. Docker port is not running.")
return False
@app.command()
def start(sys_id: int = 1, extra_apps: List[pathlib.Path] = []):
"""Starts the simulated drone with a given sys_id,
each drone must have it's own unique ID.
"""
if sys_id < 1 or sys_id > 254:
logger.error("sys_id must be between 1 and 254")
raise typer.Exit(code=1)
with logger.contextualize(syd_id=sys_id):
DOCKER_INSTANCE = (str(2375 + sys_id),)
with modified_environ(
# PX4_SIM_MODEL=os.environ.get("PX4_SIM_MODEL") or "gz_x500",
# ToDo: pose is not passed to gazebo classic
PX4_GZ_MODEL_POSE=os.environ.get("PX4_GZ_MODEL_POSE") or f"0,{(sys_id-1)}",
PX4_INSTANCE="intance_id",
DOCKER_INSTANCE=DOCKER_INSTANCE,
ROS_MASTER_PORT=str(11310 + sys_id),
MAVROS_SIM_GCS_PORT=str(14556 + sys_id),
MAVROS_SIM_FCU_PORT=str(14539 + sys_id),
DRONE_SYS_ID=str(sys_id),
):
logger.info("Starting drone simulation")
# Run the make px4_sitl gazebo-classic command
px4_command = sh.make(
"px4_sitl",
"gazebo-classic_mu",
_bg=True,
_out=outputLogger("px4", sys_id),
_cwd=px4Path,
)
processes.append(px4_command)
logger.info("Starting drone docker instance")
# Here we start a docker-in-docker instance with the DOCKER_INSTANCE port exposed to localhost
dockerinstance = sh.docker(
"run",
"--privileged",
"--name",
f"simulated_robot_{sys_id}_docker",
"-p",
f"localhost:{DOCKER_INSTANCE}:{DOCKER_INSTANCE}",
# Run the docker command in forground to capture the output
"docker:dind",
_bg=True,
_out=outputLogger("docker", sys_id),
)
processes.append(dockerinstance)
# Wait for the docker daemon to start
logger.info(f"Waiting for docker daemon on port {DOCKER_INSTANCE}")
wait_for_docker_on_port(DOCKER_INSTANCE)
logger.info("Starting drone stack, this may take some time")
docker_stack = sh.docker.compose(
"--project-name",
f"simulated_robot_{sys_id}",
"up",
_out=outputLogger("docker_stack", sys_id),
_err=sys.stderr,
_bg=True,
)
processes.append(docker_stack)
for extra_app in extra_apps:
logger.info(f"Starting app {extra_app}, this may take some time")
app_name = extra_app.stem
app_stack = sh.docker.compose(
"--project-name",
f"simulated_robot_{sys_id}_{app_name}",
"up",
_out=outputLogger(app_name, sys_id),
_err=sys.stderr,
_bg=True,
)
processes.append(app_stack)
@app.command()
def start_group(
count: int = typer.Argument(min=1, max=10), extra_apps: List[pathlib.Path] = []
):
"""Start a group of robots"""
for i in range(count):
logger.info(f"start robot {i}")
start(sys_id=i + 1, extra_apps=extra_apps)
if i == 0:
wait_for_gazebo()
def cleanup():
# Wait for all subprocesses to exit
logger.info("Waiting for commands to exit")
print(processes)
for waitable in processes:
waitable.kill()
waitable.wait()
atexit.register(cleanup)
if __name__ == "__main__":
try:
app()
except KeyboardInterrupt:
logger.info("KeyboardInterrupt caught, exiting...")
cleanup()
sys.exit(0)

View File

@ -1,31 +0,0 @@
#!/usr/bin/env bash
# Function to extract the output file from arguments
extract_output_file() {
while [[ $# -gt 0 ]]; do
key="$1"
case $key in
-o | --output)
output_file="$2"
shift # past argument
shift # past value
;;
*)
shift # past argument
;;
esac
done
}
# Extract the -o argument
extract_output_file "$@"
# Run the docker command
#docker run --rm -it -v /var/run/docker.sock:/var/run/docker.sock --privileged -v "$PWD":/d2vm -w /d2vm vmutil "$@"
docker run --rm -it -v /var/run/docker.sock:/var/run/docker.sock --privileged -v "$PWD":/d2vm -w /d2vm git.spirirobotics.com/spiri/utils-docker_to_ovf:2024-05-21 "$@"
# Change the ownership of the output file to the current user
if [[ -n "$output_file" ]]; then
echo "Setting permissions on file"
sudo chown $(whoami) "$output_file"
fi