接入 task HAL Web 仿真运行时

This commit is contained in:
2026-06-22 06:11:55 +08:00
parent 3771b9eafe
commit bd11a5f8d6
42 changed files with 5574 additions and 50 deletions

View File

@@ -0,0 +1,234 @@
#!/usr/bin/env bash
set -euo pipefail
ROOT_DIR="$(cd "$(dirname "$0")/../.." && pwd)"
LINUXCNC_ROOT="${LINUXCNC_ROOT:-$ROOT_DIR/../linuxcnc}"
MACHINE_DIR="$LINUXCNC_ROOT/configs/sim/axis/vismach/5axis/table-rotary-tilting"
INI_FILE="$MACHINE_DIR/xyzac-trt.ini"
PROGRAM_FILE="$MACHINE_DIR/demos/xyzac_switchkins.ngc"
RUN_DIR="$ROOT_DIR/build/native/trt-task-hal-runtime"
LINUXCNC_STDOUT="$RUN_DIR/linuxcnc.stdout.log"
LINUXCNC_STDERR="$RUN_DIR/linuxcnc.stderr.log"
LINUXCNC_PID=""
required_commands=(halcmd linuxcnc)
missing_commands=()
declare -A command_paths=()
cleanup() {
if [[ -n "$LINUXCNC_PID" ]]; then
kill -TERM "-$LINUXCNC_PID" 2>/dev/null || kill "$LINUXCNC_PID" 2>/dev/null || true
for _ in $(seq 1 20); do
if ! kill -0 "$LINUXCNC_PID" 2>/dev/null; then
wait "$LINUXCNC_PID" 2>/dev/null || true
LINUXCNC_PID=""
return
fi
sleep 0.1
done
kill -KILL "-$LINUXCNC_PID" 2>/dev/null || kill -KILL "$LINUXCNC_PID" 2>/dev/null || true
wait "$LINUXCNC_PID" 2>/dev/null || true
LINUXCNC_PID=""
fi
}
trap cleanup EXIT
print_kv() {
printf '%s=%s\n' "$1" "$2"
}
csv_join() {
local IFS=,
printf '%s' "$*"
}
command_path() {
local command_name="$1"
local path
path="$(command -v "$command_name" 2>/dev/null || true)"
if [[ -n "$path" ]]; then
printf '%s\n' "$path"
return
fi
case "$command_name" in
linuxcnc)
[[ -x "$LINUXCNC_ROOT/scripts/$command_name" ]] && printf '%s\n' "$LINUXCNC_ROOT/scripts/$command_name"
;;
halcmd)
[[ -x "$LINUXCNC_ROOT/bin/$command_name" ]] && printf '%s\n' "$LINUXCNC_ROOT/bin/$command_name"
;;
esac
}
existing_linuxcnc_runtime_conflicts() {
ps -eo pid=,args= | awk '
/linuxcncsvr -ini/ || /rtapi_app load/ {
if ($0 !~ /awk /) {
gsub(/^[[:space:]]+/, "", $0)
print
}
}
'
}
source_ready=1
for rel in \
xyzac-trt.ini \
xyzac-trt.tbl \
xyzac-trt_cmds.hal \
switchkins_postgui.hal \
remap_subs/428remap.ngc \
remap_subs/429remap.ngc \
remap_subs/430remap.ngc \
demos/xyzac_switchkins.ngc; do
if [[ ! -f "$MACHINE_DIR/$rel" ]]; then
source_ready=0
print_kv "trt_task_hal_missing_source_${rel//[^A-Za-z0-9]/_}" "$MACHINE_DIR/$rel"
fi
done
runtime_requirements=()
for command_name in "${required_commands[@]}"; do
path="$(command_path "$command_name")"
if [[ -n "$path" ]]; then
command_paths["$command_name"]="$path"
runtime_requirements+=("$command_name:1")
print_kv "trt_task_hal_runtime_${command_name}_path" "$path"
else
runtime_requirements+=("$command_name:0")
missing_commands+=("$command_name")
fi
done
runtime_ready=0
if [[ "${#missing_commands[@]}" -eq 0 ]]; then
runtime_ready=1
fi
print_kv trt_task_hal_runtime_requirements "$(csv_join "${runtime_requirements[@]}")"
if [[ "${#missing_commands[@]}" -eq 0 ]]; then
print_kv trt_task_hal_missing_requirements "-"
else
print_kv trt_task_hal_missing_requirements "$(csv_join "${missing_commands[@]}")"
fi
print_kv trt_task_hal_source_proof_ready "$source_ready"
print_kv trt_task_hal_runtime_ready "$runtime_ready"
print_kv trt_task_hal_execution_enabled 0
print_kv trt_task_hal_promotion_allowed 0
print_kv nativeTaskReady false
print_kv nativeHalSyncReady false
if [[ "$source_ready" != "1" ]]; then
print_kv native_task_hal_probe "blocked"
print_kv native_probe_status "blocked_missing_source"
print_kv trt_task_hal_runtime_probe_status "blocked_missing_source"
print_kv trt_task_hal_runtime_probe_note "missing_trt_source_requirements_keep_task_hal_blocked"
exit 0
fi
if [[ "$runtime_ready" != "1" ]]; then
print_kv native_task_hal_probe "ok"
print_kv native_probe_status "skipped_missing_host_runtime"
print_kv trt_task_hal_runtime_probe_status "skipped_missing_host_runtime"
print_kv trt_task_hal_runtime_probe_note "missing_host_runtime_requirements_keep_task_hal_blocked"
exit 0
fi
if [[ "${ENABLE_TRT_TASK_HAL_RUNTIME_PROBE:-0}" != "1" ]]; then
print_kv native_task_hal_probe "ok"
print_kv native_probe_status "ready_disabled_by_default"
print_kv trt_task_hal_runtime_probe_status "ready_disabled_by_default"
print_kv trt_task_hal_runtime_probe_note "set_ENABLE_TRT_TASK_HAL_RUNTIME_PROBE_1_to_run_exclusive_host_runtime_probe"
exit 0
fi
existing_runtime_conflicts="$(existing_linuxcnc_runtime_conflicts)"
if [[ -n "$existing_runtime_conflicts" ]]; then
print_kv trt_task_hal_runtime_ready 0
print_kv trt_task_hal_missing_requirements "exclusive_linuxcnc_runtime"
print_kv trt_task_hal_existing_runtime_conflicts "$(printf '%s\n' "$existing_runtime_conflicts" | paste -sd ';' -)"
print_kv native_task_hal_probe "blocked"
print_kv native_probe_status "blocked_existing_linuxcnc_runtime"
print_kv trt_task_hal_runtime_probe_status "blocked_existing_linuxcnc_runtime"
print_kv trt_task_hal_runtime_probe_note "existing_linuxcnc_runtime_conflict_keep_task_hal_blocked"
exit 0
fi
HALCMD_BIN="${command_paths[halcmd]}"
LINUXCNC_BIN="${command_paths[linuxcnc]}"
export PATH="$LINUXCNC_ROOT/bin:$LINUXCNC_ROOT/scripts:$LINUXCNC_ROOT/tcl:$PATH"
export LD_LIBRARY_PATH="$LINUXCNC_ROOT/lib${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH}"
export PYTHONPATH="$LINUXCNC_ROOT/lib/python${PYTHONPATH:+:$PYTHONPATH}"
export TCLLIBPATH="$LINUXCNC_ROOT/tcl${TCLLIBPATH:+ $TCLLIBPATH}"
mkdir -p "$RUN_DIR"
wait_for_hal_pin() {
local pin="$1"
local limit="${TRT_TASK_HAL_RUNTIME_WAIT_SECONDS:-30}"
local end=$((SECONDS + limit))
while (( SECONDS < end )); do
if "$HALCMD_BIN" getp "$pin" >/dev/null 2>&1; then
return 0
fi
sleep 0.25
done
return 1
}
read_hal_pin() {
"$HALCMD_BIN" getp "$1" 2>/dev/null | tr -d '[:space:]'
}
expect_hal_pin_exists() {
local label="$1"
local pin="$2"
if "$HALCMD_BIN" getp "$pin" >/dev/null 2>&1; then
print_kv "trt_task_hal_${label}_${pin//[^A-Za-z0-9]/_}_exists" 1
print_kv "trt_task_hal_${label}_${pin//[^A-Za-z0-9]/_}_value" "$(read_hal_pin "$pin")"
return 0
fi
print_kv "trt_task_hal_${label}_${pin//[^A-Za-z0-9]/_}_exists" 0
return 1
}
print_kv trt_task_hal_runtime_probe_ini "$INI_FILE"
print_kv trt_task_hal_runtime_probe_program "$PROGRAM_FILE"
print_kv trt_task_hal_runtime_probe_linuxcnc_stdout "$LINUXCNC_STDOUT"
print_kv trt_task_hal_runtime_probe_linuxcnc_stderr "$LINUXCNC_STDERR"
setsid "$LINUXCNC_BIN" -r "$INI_FILE" >"$LINUXCNC_STDOUT" 2>"$LINUXCNC_STDERR" &
LINUXCNC_PID="$!"
if ! wait_for_hal_pin motion.switchkins-type || ! wait_for_hal_pin motion.program-line; then
print_kv native_task_hal_probe "failed"
print_kv native_probe_status "failed"
print_kv trt_task_hal_runtime_probe_status "runtime_state_probe_failed"
print_kv trt_task_hal_runtime_probe_note "linuxcnc_started_but_required_trt_hal_pins_did_not_appear"
exit 1
fi
probe_ok=1
expect_hal_pin_exists startup motion.switchkins-type || probe_ok=0
expect_hal_pin_exists startup motion.program-line || probe_ok=0
expect_hal_pin_exists startup motion.motion-type || probe_ok=0
expect_hal_pin_exists startup motion.in-position || probe_ok=0
expect_hal_pin_exists startup joint.0.motor-pos-cmd || probe_ok=0
expect_hal_pin_exists startup joint.0.motor-pos-fb || probe_ok=0
expect_hal_pin_exists startup xyzac-trt-kins.tool-offset || true
if [[ "$probe_ok" == "1" ]]; then
print_kv native_task_hal_probe "ok"
print_kv native_probe_status "passed"
print_kv trt_task_hal_runtime_probe_status "runtime_state_probe_passed"
print_kv trt_task_hal_runtime_probe_note "linuxcnc_owned_trt_task_hal_startup_state_probe_passed_without_promotion"
exit 0
fi
print_kv native_task_hal_probe "failed"
print_kv native_probe_status "failed"
print_kv trt_task_hal_runtime_probe_status "runtime_state_probe_failed"
print_kv trt_task_hal_runtime_probe_note "linuxcnc_owned_trt_task_hal_startup_state_probe_failed"
exit 1

View File

@@ -0,0 +1,85 @@
#!/usr/bin/env bash
set -euo pipefail
ROOT_DIR="$(cd "$(dirname "$0")/../.." && pwd)"
BUILD_DIR="$ROOT_DIR/build/task-hal"
MANIFEST_STDOUT="$BUILD_DIR/verify_task_hal_source_manifest.stdout.log"
PROBE_STDOUT="$BUILD_DIR/probe_trt_task_hal_runtime.stdout.log"
mkdir -p "$BUILD_DIR"
"$ROOT_DIR/tools/verify_task_hal_source_manifest.sh" >"$MANIFEST_STDOUT"
"$ROOT_DIR/tests/native/probe_trt_task_hal_runtime.sh" >"$PROBE_STDOUT"
value_from() {
local file="$1"
local key="$2"
awk -F= -v key="$key" '$1 == key { print substr($0, length(key) + 2); found=1 } END { if (!found) exit 1 }' "$file"
}
expect_value() {
local file="$1"
local key="$2"
local expected="$3"
local actual
actual="$(value_from "$file" "$key")"
if [[ "$actual" != "$expected" ]]; then
echo "$key expected $expected, got $actual" >&2
echo "from $file" >&2
exit 1
fi
}
expect_int_gt() {
local file="$1"
local key="$2"
local minimum="$3"
local actual
actual="$(value_from "$file" "$key")"
if ! [[ "$actual" =~ ^[0-9]+$ ]] || (( actual <= minimum )); then
echo "$key expected > $minimum, got $actual" >&2
echo "from $file" >&2
exit 1
fi
}
expect_value "$MANIFEST_STDOUT" task_hal_source_manifest_status ok
expect_value "$MANIFEST_STDOUT" task_hal_source_manifest_ready 1
expect_value "$MANIFEST_STDOUT" task_hal_reference_source_ready 1
expect_value "$MANIFEST_STDOUT" task_hal_missing_reference_source_count 0
expect_int_gt "$MANIFEST_STDOUT" task_source_count 0
expect_int_gt "$MANIFEST_STDOUT" hal_source_count 0
expect_int_gt "$MANIFEST_STDOUT" motion_source_count 0
expect_int_gt "$MANIFEST_STDOUT" nml_source_count 0
expect_value "$MANIFEST_STDOUT" task_hal_runtime_promoted 0
expect_value "$MANIFEST_STDOUT" nativeTaskReady false
expect_value "$MANIFEST_STDOUT" nativeHalSyncReady false
expect_value "$PROBE_STDOUT" trt_task_hal_source_proof_ready 1
expect_value "$PROBE_STDOUT" trt_task_hal_execution_enabled 0
expect_value "$PROBE_STDOUT" trt_task_hal_promotion_allowed 0
expect_value "$PROBE_STDOUT" native_task_hal_probe ok
expect_value "$PROBE_STDOUT" nativeTaskReady false
expect_value "$PROBE_STDOUT" nativeHalSyncReady false
native_probe_status="$(value_from "$PROBE_STDOUT" native_probe_status)"
probe_status="$(value_from "$PROBE_STDOUT" trt_task_hal_runtime_probe_status)"
case "$probe_status" in
ready_disabled_by_default|skipped_missing_host_runtime|blocked_missing_source)
;;
*)
echo "unexpected non-opt-in TRT task/HAL probe status: $probe_status" >&2
exit 1
;;
esac
case "$native_probe_status" in
ready_disabled_by_default|skipped_missing_host_runtime)
;;
*)
echo "unexpected non-opt-in native probe status: $native_probe_status" >&2
exit 1
;;
esac
echo "task_hal_phase0_native_probe_gate=ok"