feat(simulation): qualify D-only stock rover smoke

This commit is contained in:
DCCONSTRUCTIONS
2026-07-24 16:51:39 +03:00
parent 81761067e9
commit 6290fcb2ce
8 changed files with 545 additions and 60 deletions
+27 -27
View File
@@ -4,8 +4,10 @@ profile_id: ai-worker-px4-gazebo-v1
target_host:
windows_release: windows-11
virtualization: wsl2
wsl_distribution: MissionCore-Sim
linux_distribution: ubuntu-24.04
architecture: x86_64
container_runtime: none
storage:
windows_root: 'D:\NDC_MISSIONCORE'
@@ -15,11 +17,8 @@ storage:
forbid_windows_system_drive: true
mutable_paths:
- id: wsl
windows_path: 'D:\NDC_MISSIONCORE\wsl'
wsl_path: /mnt/d/NDC_MISSIONCORE/wsl
- id: docker
windows_path: 'D:\NDC_MISSIONCORE\docker'
wsl_path: /mnt/d/NDC_MISSIONCORE/docker
windows_path: 'D:\NDC_MISSIONCORE\simulation\wsl'
wsl_path: /mnt/d/NDC_MISSIONCORE/simulation/wsl
- id: source
windows_path: 'D:\NDC_MISSIONCORE\simulation\source'
wsl_path: /mnt/d/NDC_MISSIONCORE/simulation/source
@@ -56,24 +55,24 @@ authority:
- rover-speed-yaw-rate/v1
ros:
domain_id: 42
domain_id: 0
namespace: /missioncore/polygon/s0
components:
- id: ros2
source_url: https://docs.ros.org/en/jazzy/
requested_ref: jazzy
resolved_version:
resolved_version: ros-base=0.11.0-1noble.20260616.084325;ros-gz=1.0.22-1noble.20260616.074726
resolved_commit:
license: mixed-apache-2.0-bsd
qualification_state: pending-worker-resolution
qualification_state: candidate
- id: gazebo
source_url: https://gazebosim.org/docs/harmonic/
requested_ref: harmonic
resolved_version:
resolved_version: gz-harmonic=1.0.0-1~noble;gz-sim=8.14.0-1~noble;sdformat=14.9.0-1~noble
resolved_commit:
license: apache-2.0
qualification_state: pending-worker-resolution
qualification_state: candidate
- id: px4-autopilot
source_url: https://github.com/PX4/PX4-Autopilot
requested_ref: v1.17.0
@@ -90,9 +89,9 @@ components:
qualification_state: candidate
- id: px4-gazebo-models
source_url: https://github.com/PX4/PX4-gazebo-models
requested_ref: main@2026-07-24
resolved_version:
resolved_commit: e00d3b9cde682dbcb3bf6f30a2f2b8ef4325dae8
requested_ref: PX4-Autopilot/v1.17.0-submodule
resolved_version: px4-v1.17.0-submodule
resolved_commit: b6127f4ec20de867e215fb5f78ae88b80f371909
license: bsd-3-clause
qualification_state: candidate
- id: micro-xrce-dds-agent
@@ -105,38 +104,38 @@ components:
- id: nav2
source_url: https://github.com/ros-navigation/navigation2
requested_ref: jazzy@2026-07-24
resolved_version:
resolved_version: navigation2=1.3.12-1noble.20260615.181551;nav2-bringup=1.3.12-1noble.20260616.082701
resolved_commit: c92ea2fd9008f50c0ec8447610800214b2a0dafb
license: apache-2.0
qualification_state: candidate
ports:
- id: micro-xrce-dds
host_scope: worker-wsl
host_scope: loopback-only-netns
protocol: udp
bind: 127.0.0.1
bind: 0.0.0.0
port: 8888
owner: micro-xrce-dds-agent
- id: px4-mavlink-sitl
host_scope: worker-wsl
- id: px4-mavlink-onboard
host_scope: loopback-only-netns
protocol: udp
bind: 127.0.0.1
port: 14540
bind: 0.0.0.0
port: 14580
owner: px4-sitl
- id: qgroundcontrol-reference
host_scope: worker-wsl
- id: px4-mavlink-normal
host_scope: loopback-only-netns
protocol: udp
bind: 127.0.0.1
port: 14550
bind: 0.0.0.0
port: 18570
owner: px4-sitl
- id: simulation-orchestrator-api
host_scope: worker-wsl
host_scope: loopback-only-netns
protocol: tcp
bind: 127.0.0.1
port: 18080
owner: simulation-orchestrator
- id: simulation-telemetry
host_scope: worker-wsl
host_scope: loopback-only-netns
protocol: tcp
bind: 127.0.0.1
port: 18081
@@ -164,9 +163,10 @@ processes:
required_tools:
- git
- docker
- gz
- make
- cmake
- ninja
- colcon
- ros2
- MicroXRCEAgent
+259
View File
@@ -0,0 +1,259 @@
#!/usr/bin/env bash
#
# Run the SIM S0 stock-rover smoke case inside a loopback-only network
# namespace. The script writes factual runtime artifacts to D and never grants
# actuator authority.
set -Eeuo pipefail
readonly EXPECTED_DISTRO="MissionCore-Sim"
readonly D_ROOT="${MISSIONCORE_SIM_D_ROOT:-/mnt/d/NDC_MISSIONCORE/simulation}"
readonly PX4_ROOT="${MISSIONCORE_SIM_PX4_ROOT:-${D_ROOT}/source/PX4-Autopilot}"
readonly AGENT_PREFIX="${MISSIONCORE_SIM_AGENT_PREFIX:-${D_ROOT}/runtime/micro-xrce-dds-agent/2.4.3}"
readonly PX4_MSGS_SETUP="${MISSIONCORE_SIM_PX4_MSGS_SETUP:-${D_ROOT}/build/ros2/px4_msgs/install/setup.bash}"
readonly ARTIFACT_ROOT="${MISSIONCORE_SIM_ARTIFACT_ROOT:-${D_ROOT}/artifacts/s0}"
readonly RUN_ID="${1:-$(date -u +%Y%m%dT%H%M%SZ)}"
readonly RUN_DIR="${ARTIFACT_ROOT}/${RUN_ID}"
if [[ "${MISSIONCORE_S0_NETNS:-0}" != "1" ]]; then
if [[ "${EUID}" -ne 0 ]]; then
echo "error: initial worker-smoke invocation must run as root to create the network namespace" >&2
exit 2
fi
if [[ "${WSL_DISTRO_NAME:-}" != "${EXPECTED_DISTRO}" ]]; then
echo "error: expected WSL distro ${EXPECTED_DISTRO}, observed ${WSL_DISTRO_NAME:-unset}" >&2
exit 2
fi
exec unshare --net -- bash -c '
set -e
ip link set lo up
exec runuser -u missioncore -- env MISSIONCORE_S0_NETNS=1 "$@"
' bash "$0" "$@"
fi
if [[ "${WSL_DISTRO_NAME:-}" != "${EXPECTED_DISTRO}" ]]; then
echo "error: smoke case escaped the reviewed WSL distribution" >&2
exit 2
fi
for required_path in "${PX4_ROOT}" "${AGENT_PREFIX}" "${PX4_MSGS_SETUP}" "${ARTIFACT_ROOT}"; do
if [[ "${required_path}" != /mnt/d/NDC_MISSIONCORE/* ]]; then
echo "error: mutable or executable path escaped D-only root: ${required_path}" >&2
exit 2
fi
done
readonly AGENT_BIN="${AGENT_PREFIX}/bin/MicroXRCEAgent"
readonly AGENT_LOG="${RUN_DIR}/micro-xrce-dds-agent.log"
readonly PX4_LOG="${RUN_DIR}/px4-rover.log"
readonly BRIDGE_LOG="${RUN_DIR}/ros-gz-clock-bridge.log"
readonly TOPICS_LOG="${RUN_DIR}/ros-topics.txt"
readonly VEHICLE_STATUS_LOG="${RUN_DIR}/vehicle-status.yaml"
readonly CLOCK_LOG="${RUN_DIR}/clock.yaml"
readonly NETWORK_LOG="${RUN_DIR}/network.txt"
readonly RESOURCE_LOG="${RUN_DIR}/resource-snapshot.txt"
readonly RESULT_LOG="${RUN_DIR}/result.env"
for required_file in \
"${PX4_ROOT}/build/px4_sitl_default/bin/px4" \
"${PX4_ROOT}/Tools/simulation/gz/worlds/rover.sdf" \
"${AGENT_BIN}" \
"/opt/ros/jazzy/setup.bash" \
"${PX4_MSGS_SETUP}"; do
if [[ ! -e "${required_file}" ]]; then
echo "error: required S0 runtime input is missing: ${required_file}" >&2
exit 2
fi
done
mkdir -p "${RUN_DIR}"
agent_pid=""
px4_pgid=""
bridge_pgid=""
stop_process_group() {
local pgid="${1:-}"
if [[ -z "${pgid}" ]]; then
return
fi
if kill -0 -- "-${pgid}" 2>/dev/null; then
kill -INT -- "-${pgid}" 2>/dev/null || true
for _ in {1..20}; do
if ! kill -0 -- "-${pgid}" 2>/dev/null; then
return
fi
sleep 0.25
done
kill -TERM -- "-${pgid}" 2>/dev/null || true
sleep 1
kill -KILL -- "-${pgid}" 2>/dev/null || true
fi
}
cleanup() {
set +e
exec 3>&-
stop_process_group "${bridge_pgid}"
stop_process_group "${px4_pgid}"
if [[ -n "${agent_pid}" ]] && kill -0 "${agent_pid}" 2>/dev/null; then
kill -TERM "${agent_pid}" 2>/dev/null
wait "${agent_pid}" 2>/dev/null
fi
}
trap cleanup EXIT INT TERM
wait_for_pattern() {
local file="$1"
local pattern="$2"
local attempts="$3"
for ((attempt = 0; attempt < attempts; attempt += 1)); do
if grep -Fq "${pattern}" "${file}" 2>/dev/null; then
return 0
fi
sleep 0.5
done
return 1
}
env \
LD_LIBRARY_PATH="${AGENT_PREFIX}/lib" \
"${AGENT_BIN}" udp4 -p 8888 -v 4 >"${AGENT_LOG}" 2>&1 &
agent_pid="$!"
sleep 1
if ! kill -0 "${agent_pid}" 2>/dev/null; then
echo "error: Micro XRCE-DDS Agent exited during startup" >&2
exit 1
fi
{
echo "network_namespace=loopback-only"
ip -brief address
ss -lunp
} >"${NETWORK_LOG}"
coproc PX4_PROCESS {
exec setsid env HEADLESS=1 make -C "${PX4_ROOT}" \
px4_sitl gz_rover_ackermann >"${PX4_LOG}" 2>&1
}
px4_pgid="${PX4_PROCESS_PID}"
exec 3>&"${PX4_PROCESS[1]}"
if ! wait_for_pattern "${PX4_LOG}" "Startup script returned successfully" 120; then
echo "error: PX4 stock rover did not reach startup completion" >&2
exit 1
fi
sleep 3
printf '%s\n' \
"ver all" \
"commander status" >&3
if ! wait_for_pattern "${AGENT_LOG}" "session established" 60 \
|| ! wait_for_pattern \
"${PX4_LOG}" \
"successfully created rt/fmu/out/vehicle_status_v1 data writer" \
60; then
echo "error: PX4 uXRCE-DDS client did not connect to the loopback agent" >&2
exit 1
fi
printf '%s\n' "uxrce_dds_client status" >&3
if ! wait_for_pattern "${PX4_LOG}" "Running, connected" 20; then
echo "error: PX4 did not report the established uXRCE-DDS session" >&2
exit 1
fi
{
echo
echo "runtime_listeners=loopback-only-netns"
ss -lunp
} >>"${NETWORK_LOG}"
set +u
# shellcheck source=/dev/null
source /opt/ros/jazzy/setup.bash
# shellcheck source=/dev/null
source "${PX4_MSGS_SETUP}"
set -u
export ROS_DOMAIN_ID=0
export ROS_AUTOMATIC_DISCOVERY_RANGE=LOCALHOST
unset ROS_LOCALHOST_ONLY
setsid ros2 run ros_gz_bridge parameter_bridge \
'/clock@rosgraph_msgs/msg/Clock[gz.msgs.Clock' >"${BRIDGE_LOG}" 2>&1 &
bridge_pgid="$!"
timeout 20s ros2 topic list -t >"${TOPICS_LOG}"
vehicle_status_topic="/fmu/out/vehicle_status"
if grep -Fq "/fmu/out/vehicle_status_v1" "${TOPICS_LOG}"; then
vehicle_status_topic="/fmu/out/vehicle_status_v1"
fi
timeout 20s ros2 topic echo --once \
"${vehicle_status_topic}" >"${VEHICLE_STATUS_LOG}"
timeout 20s ros2 topic echo --once \
/clock rosgraph_msgs/msg/Clock >"${CLOCK_LOG}"
{
echo "sample=non-acceptance-point-snapshot"
free -b
ps -g "${px4_pgid}" -o pid,ppid,pgid,rss,vsz,pcpu,comm,args
ps -p "${agent_pid}" -o pid,ppid,pgid,rss,vsz,pcpu,comm,args
ps -g "${bridge_pgid}" -o pid,ppid,pgid,rss,vsz,pcpu,comm,args
if command -v nvidia-smi >/dev/null; then
nvidia-smi \
--query-gpu=memory.used,utilization.gpu \
--format=csv,noheader,nounits
fi
} >"${RESOURCE_LOG}"
printf '%s\n' "shutdown" >&3
if ! wait_for_pattern "${PX4_LOG}" "Exiting NOW." 20; then
echo "error: PX4 did not acknowledge the shutdown command" >&2
exit 1
fi
cleanup
trap - EXIT INT TERM
px4_status="fail"
dds_status="fail"
vehicle_status="fail"
clock_status="fail"
lifecycle_status="fail"
grep -Fq "world: rover, model: rover_ackermann_0" "${PX4_LOG}" && px4_status="pass"
if grep -Fq "session established" "${AGENT_LOG}" \
&& grep -Fq \
"successfully created rt/fmu/out/vehicle_status_v1 data writer" \
"${PX4_LOG}"; then
dds_status="pass"
fi
grep -Fq "arming_state:" "${VEHICLE_STATUS_LOG}" && vehicle_status="pass"
grep -Fq "clock:" "${CLOCK_LOG}" && clock_status="pass"
if ! pgrep -f "${PX4_ROOT}/build/px4_sitl_default/bin/px4" >/dev/null \
&& ! pgrep -f "gz sim.*rover.sdf" >/dev/null \
&& ! pgrep -f "${AGENT_BIN}" >/dev/null; then
lifecycle_status="pass"
fi
{
echo "run_id=${RUN_ID}"
echo "network_scope=loopback-only-netns"
echo "actuator_authority=false"
echo "px4_stock_rover=${px4_status}"
echo "uxrce_dds=${dds_status}"
echo "ros2_vehicle_status=${vehicle_status}"
echo "gazebo_clock=${clock_status}"
echo "clean_lifecycle=${lifecycle_status}"
} >"${RESULT_LOG}"
if [[ "${px4_status}" != "pass" \
|| "${dds_status}" != "pass" \
|| "${vehicle_status}" != "pass" \
|| "${clock_status}" != "pass" \
|| "${lifecycle_status}" != "pass" ]]; then
echo "error: one or more S0 smoke checks failed; inspect ${RUN_DIR}" >&2
exit 1
fi
echo "SIM S0 smoke PASS: ${RUN_DIR}"