From 2a8072fce05ebe8eddc20025a9f82c8165d1e607 Mon Sep 17 00:00:00 2001 From: "cameron.johnson" Date: Tue, 29 Sep 2026 10:31:51 -0400 Subject: [PATCH 1/6] cq was yq + jq. I retired it for jq only. taiga and nayak yaml configs become JSON Read config.json with json.load, not yaml.safe_load --- README.md | 2 +- runtime/env.sh | 2 +- src/cfg/README.md | 57 ++++ src/cfg/cfg-aliases.sh | 2 +- src/cfg/get | 7 +- src/cfg/nayak/config.json | 265 ++++++++++++++++++ src/cfg/nayak/config.yaml | 265 ------------------ src/cfg/taiga/config.json | 262 +++++++++++++++++ src/cfg/taiga/config.yaml | 263 ----------------- src/core/kamcore/scripts/seed_redis_config.py | 18 +- .../wxpython_gui/src/wxpython_gui/cfg.py | 15 +- src/run_scripts/entry/master.sh | 6 +- 12 files changed, 610 insertions(+), 554 deletions(-) create mode 100644 src/cfg/README.md create mode 100644 src/cfg/nayak/config.json delete mode 100644 src/cfg/nayak/config.yaml create mode 100644 src/cfg/taiga/config.json delete mode 100644 src/cfg/taiga/config.yaml diff --git a/README.md b/README.md index 5bd85242..d437666f 100644 --- a/README.md +++ b/README.md @@ -23,7 +23,7 @@ KAMERA, or the **K**nowledge-guided Image **A**cquisition **M**anag**ER** and ** ## Layout - `src/` is the onboard software: ROS packages for the cameras, INS, DAQ and processing, under `src/core`, `src/cams` and `src/process`. -- `src/cfg/` is the per-system configuration. `nayak/` and `taiga/` each hold a `config.yaml`, the default system state, and one folder per host with its network and clock settings. Files shared by every system sit at the top level. The file `~/kw/SYSTEM_NAME` on a host picks which folder applies. +- `src/cfg/` is the per-system configuration. `nayak/` and `taiga/` each hold a `config.json`, the default system state, and one folder per host with its network and clock settings. Files shared by every system sit at the top level. The file `~/kw/SYSTEM_NAME` on a host picks which folder applies. - `runtime/` is how a host runs the system: the env script, the supervisor program definitions for the leader and the followers, and the scripts supervisor calls (tmux startup). It is the same on every system. - `compose/` runs and `docker/` defines the images built for the containers those programs start. - `provision/` sets up a host from a fresh install with Ansible, plus the desktop shortcuts and dotfiles it installs. diff --git a/runtime/env.sh b/runtime/env.sh index 7ed967ff..371e23cc 100644 --- a/runtime/env.sh +++ b/runtime/env.sh @@ -3,7 +3,7 @@ SYSTEM_NAME="$(cat ${HOME}/kw/SYSTEM_NAME)" export SYSTEM_NAME export KAMERA_DIR=$(${HOME}/.config/kamera/repo_dir.bash) -CFG_FILE="${KAMERA_DIR}/src/cfg/${SYSTEM_NAME}/config.yaml" +CFG_FILE="${KAMERA_DIR}/src/cfg/${SYSTEM_NAME}/config.json" cq () { CFG_FILE=${CFG_FILE} ${KAMERA_DIR}/src/cfg/get "$@" } diff --git a/src/cfg/README.md b/src/cfg/README.md new file mode 100644 index 00000000..6fc161fa --- /dev/null +++ b/src/cfg/README.md @@ -0,0 +1,57 @@ +# Per-system deployment configs + +`/config.json` (taiga, nayak) is the singular source of truth for a +deployment's static configuration. More static configuration should be +handled with compose.yml files and .launch files. + +It is read in two ways, both of which expect plain JSON: + +- shell: the `cq` helper (`cfg-aliases.sh` / `runtime/env.sh`) runs + `src/cfg/get`, which is a plain `jq -r config.json` +- python: `kamcore/scripts/seed_redis_config.py` and `wxpython_gui.cfg` + load it and seed the static keys into redis (config.json always wins for + its keys; operator-mutable session state stays owned by the GUI) + +These notes used to live as comments inside `config.yaml` and moved here +when the file became JSON. + +## Field notes + +**Fields of view.** FOV names describe the position of the camera array's +reference frame: `{left, right, center, NONE}` (use `NONE` with +`ROLE=NONE`). Looking along the direction of flight: + +``` + Port Starbrd + _ + /^\ + x | | x + <==U=| |=U==> + | | + \ / + <> + [L] [C] [R] Fields of View +``` + +**`.arch`** — camera information and configuration. `max_frame_rate` is the +max fps we can request of the cameras. `max_mpix: 200000` is 0.2e6. + +**`.interfaces`** — maps channels to ethernet interface names (this is +going to usurp the locations mapping). + +**`.locations`** — maps a DEV_ID to a specific FOV. Use this section to +swap which physical cameras map to a software FOV. + +**`.devices`** — configuration for each physical device, keyed by DEV_ID +(e.g. `ir_n0`). A DEV_ID is an abstract label with no absolute correlation +to FOV; that indirection makes it easy and less error-prone to reroute +camera defs. Device blocks appear in groups: cooled FLIR cameras, IR +"backup" cameras, rgb prosilica backup cameras, rgb phase one cameras, uv +prosilica cameras. For prosilica GUIDs: the last 3 nybbles of the MAC are +the GUID, i.e. `02:c2:8c` = 0x02c28c = 180876. + +**`.camera_models`** — information about the actual camera devices, keyed +by model name. + +**`.launch`** — expert configs; launch params passed through to the camera +launch files. diff --git a/src/cfg/cfg-aliases.sh b/src/cfg/cfg-aliases.sh index 5a926aa8..486a8c60 100755 --- a/src/cfg/cfg-aliases.sh +++ b/src/cfg/cfg-aliases.sh @@ -8,5 +8,5 @@ export CFG_ALIAS_SET=true # ConfigQuery cq () { - CFG_FILE=${CFG_DIR}/${SYSTEM_NAME}/config.yaml ${CFG_DIR}/get "$@" + CFG_FILE=${CFG_DIR}/${SYSTEM_NAME}/config.json ${CFG_DIR}/get "$@" } diff --git a/src/cfg/get b/src/cfg/get index 93eddce3..76493a72 100755 --- a/src/cfg/get +++ b/src/cfg/get @@ -1,7 +1,8 @@ #!/usr/bin/env bash -#Retrieve values from user config yaml, basically syntactic sugar for `yq r user-config.yml` +# Retrieve values from the per-system config.json; queries are plain jq. +# (Historically this piped config.yaml through a pinned yq v3 binary into +# jq; the configs are JSON now, so jq alone does the job.) CFG_FILE="${CFG_FILE}" -## Gotta pass it into jq cause it's more feature rich -yq read -j "${CFG_FILE}" | jq -r "${1}" +exec jq -r "${1}" "${CFG_FILE}" diff --git a/src/cfg/nayak/config.json b/src/cfg/nayak/config.json new file mode 100644 index 00000000..335e4aa0 --- /dev/null +++ b/src/cfg/nayak/config.json @@ -0,0 +1,265 @@ +{ + "arch": { + "max_frame_rate": 2.0, + "min_frame_rate": 0.1, + "base_template": "{base}/{project}/fl{flight}/{sys_cfg}/", + "template": "{base}/{project}/fl{flight}/{sys_cfg}/{cam_fov}_view/{project}_fl{flight}_{cf}_{time}_{mode}.{ext}", + "max_exposure_ms": 125, + "ext_rgb": "jpg", + "ext_uv": "jpg", + "ext_ir": "tif", + "ext_evt": "json", + "ext_ins": "json", + "hosts": { + "center0nayak": { + "fov": "center", + "idx": 0, + "enabled": true + }, + "left1nayak": { + "fov": "left", + "idx": 1, + "enabled": true + }, + "right2nayak": { + "fov": "right", + "idx": 2, + "enabled": true + }, + "center0spare": { + "fov": "center", + "idx": 0, + "enabled": false + } + } + }, + "postproc_commands": [ + "flight_summary", + "homography", + "detections" + ], + "nas_mnt": "/mnt/flight_data", + "local_ssd_mnt": "/mnt/data", + "kamera_dir": "/home/user/kw/kamera", + "gui_cfg_dir": "/home/user/.config/kamera/gui", + "master_host": "center0nayak", + "redis_host": "center0nayak", + "verbosity": 9, + "max_mpix": 200000, + "channels": { + "rgb": 0 + }, + "interfaces": { + "rgb": "pci_btm", + "ir": "mobo_top", + "uv": "mobo_btm" + }, + "locations": { + "center": { + "ir": "ir_n0", + "rgb": "rgb_n0", + "uv": "uv_n0" + }, + "left": { + "ir": "ir_n1", + "rgb": "rgb_n1", + "uv": "uv_n1" + }, + "right": { + "ir": "ir_n2", + "rgb": "rgb_n2", + "uv": "uv_n2" + } + }, + "enabled": { + "center": { + "rgb": true, + "ir": false, + "uv": false + }, + "left": { + "rgb": true, + "ir": false, + "uv": false + }, + "right": { + "rgb": true, + "ir": false, + "uv": false + } + }, + "devices": { + "ir_n0": { + "model": "flir_a6750", + "mac": "00:11:1c:02:40:46", + "prefer_ip": "192.168.1.50", + "ip_mode": "fixed" + }, + "ir_n1": { + "model": "flir_a6750", + "mac": "00:11:1c:01:ec:f7", + "prefer_ip": "192.168.1.51", + "ip_mode": "fixed" + }, + "ir_n2": { + "model": "flir_a6750", + "mac": "00:11:1c:01:c8:5b", + "prefer_ip": "192.168.1.52", + "ip_mode": "fixed" + }, + "ir_nb0": { + "model": "flir_a645", + "mac": "00:11:1c:00:e6:d1", + "prefer_ip": "192.168.1.53", + "ip_mode": "dhcp" + }, + "ir_nb1": { + "model": "flir_a645", + "mac": "00:11:1c:00:bf:6a", + "prefer_ip": "192.168.1.54", + "ip_mode": "dhcp" + }, + "ir_nb2": { + "model": "flir_a645", + "mac": "00:11:1c", + "prefer_ip": "192.168.1.55", + "ip_mode": "dhcp" + }, + "rgb_nb0": { + "label": "CENTER", + "model": "allied_gt6600_rgb", + "mac": "00:0f:31:02:37:6c", + "prefer_ip": "192.168.4.40", + "guid": 145260, + "ip_mode": "fixed" + }, + "rgb_nb1": { + "label": "unknown", + "model": "allied_gt6600_rgb", + "mac": "00:0f:31:02:c2:8d", + "guid": 180877, + "prefer_ip": "192.168.4.41", + "ip_mode": "fixed" + }, + "rgb_nb2": { + "model": "allied_gt6600_rgb", + "label": "CENTER", + "mac": "00:0f:31:02:c2:8c", + "guid": 180876, + "prefer_ip": "192.168.4.42", + "ip_mode": "fixed" + }, + "rgb_n0": { + "label": "CENTER", + "model": "gsm_ix120", + "mac": "00:0f:31:02:37:6c", + "prefer_ip": "192.168.4.40", + "guid": 145260, + "ip_mode": "fixed" + }, + "rgb_n1": { + "label": "unknown", + "model": "gsm_ix120", + "mac": "00:0f:31:02:c2:8d", + "guid": 180877, + "prefer_ip": "192.168.4.41", + "ip_mode": "fixed" + }, + "rgb_n2": { + "model": "gsm_ix120", + "label": "CENTER", + "mac": "00:0f:31:02:c2:8c", + "guid": 180876, + "prefer_ip": "192.168.4.42", + "ip_mode": "fixed" + }, + "uv_n0": { + "label": "unknown", + "model": "allied_gt4907_uv", + "mac": "00:0f:31:03:64:5a", + "guid": 222298, + "prefer_ip": "192.168.2.60", + "ip_mode": "linklocal" + }, + "uv_n1": { + "label": "unknown", + "model": "allied_gt4907_uv", + "mac": "00:0f:31:03:65:d0", + "guid": 222672, + "prefer_ip": "192.168.2.61", + "ip_mode": "linklocal" + }, + "uv_n2": { + "label": "unknown", + "model": "allied_gt4907_uv", + "mac": "00:0f:31:03:64:26", + "guid": 222246, + "prefer_ip": "192.168.2.62", + "ip_mode": "linklocal" + } + }, + "models": { + "flir_a6750": { + "mfgr": "flir", + "nic_mfgr": "pleora", + "mac_prefix": "00:11:1c", + "spectrum": "ir", + "specs": { + "width": 640, + "height": 512 + } + }, + "flir_645": { + "mfgr": "flir", + "nic_mfgr": "", + "mac_prefix": "", + "spectrum": "ir", + "specs": { + "width": 640, + "height": 480 + } + }, + "allied_gt6600_rgb": { + "mfgr": "allied vision", + "nic_mfgr": "", + "mac_prefix": "00:0f:31", + "spectrum": "rgb", + "specs": { + "width": 6576, + "height": 4384 + } + }, + "allied_gt4907_uv": { + "mfgr": "allied vision", + "nic_mfgr": "", + "mac_prefix": "00:0f:31", + "spectrum": "uv", + "specs": { + "width": 4864, + "height": 3232 + } + }, + "gsm_ix120": { + "mfgr": "phase one", + "nic_mfgr": "", + "mac_prefix": "", + "spectrum": "rgb", + "specs": { + "width": 12768, + "height": 9654 + } + } + }, + "launch": { + "cam": { + "rgb": { + "GainMode": "Auto", + "GainValue": 0 + }, + "uv": { + "GainMode": "Auto", + "GainValue": 0 + } + } + } +} diff --git a/src/cfg/nayak/config.yaml b/src/cfg/nayak/config.yaml deleted file mode 100644 index d61a685a..00000000 --- a/src/cfg/nayak/config.yaml +++ /dev/null @@ -1,265 +0,0 @@ ---- -# This is (eventually) to be the SINGULAR SOURCE OF TRUTH of app deployment configs -# More static configuration should be handled with compose.yml files and .launch files - -# Position of reference frame of the camera array. Corresponds to field of view -# See airplane diagram: -# Port Starbrd -# _ -# /^\ -# x | | x -# <==Û=| |=Û==> -# | | -# \ / -# <> -#[ L] [ C ] [R ] Fields of View -# -# {left, right, center, NONE} use NONE with ROLE=NONE - - -# Camera information and configuration: -arch: - max_frame_rate: 2.0 # max fps we can request of the cameras - min_frame_rate: 0.1 - base_template: "{base}/{project}/fl{flight}/{sys_cfg}/" - template: "{base}/{project}/fl{flight}/{sys_cfg}/{cam_fov}_view/{project}_fl{flight}_{cf}_{time}_{mode}.{ext}" - max_exposure_ms: 125 - ext_rgb: jpg - ext_uv: jpg - ext_ir: tif - ext_evt: json - ext_ins: json - hosts: - center0nayak: - fov: center - idx: 0 - enabled: true - left1nayak: - fov: left - idx: 1 - enabled: true - right2nayak: - fov: right - idx: 2 - enabled: true - center0spare: - fov: center - idx: 0 - enabled: false -postproc_commands: - - "flight_summary" - - "homography" - - "detections" -nas_mnt: "/mnt/flight_data" -local_ssd_mnt: "/mnt/data" -kamera_dir: "/home/user/kw/kamera" -gui_cfg_dir: "/home/user/.config/kamera/gui" -master_host: center0nayak -redis_host: center0nayak -verbosity: 9 -max_mpix: 200000 # 0.2e6 - -channels: - rgb: 0 -interfaces: - # map channels to ethernet interface names - # this is gonna usurp the locations mapping - rgb: pci_btm - ir: mobo_top - uv: mobo_btm -locations: - # this maps a DEV_ID to a specific FOV. Use this section - # to swap which physical cameras map to software FOV - center: - ir: ir_n0 - rgb: rgb_n0 - uv: uv_n0 - left: - ir: ir_n1 - rgb: rgb_n1 - uv: uv_n1 - right: - ir: ir_n2 - rgb: rgb_n2 - uv: uv_n2 - -enabled: - center: - rgb: true - ir: false - uv: false - left: - rgb: true - ir: false - uv: false - right: - rgb: true - ir: false - uv: false - -# This is configuration information for each physical device -# `ir_n0` is a DEV_ID. This is an abstract label and has no absolute correlation -# with FOV. This makes it easy and less error-prone to reroute camera defs -devices: -# === === === === cooled FLIR cameras === === === === - ir_n0: - model: flir_a6750 - mac: 00:11:1c:02:40:46 - prefer_ip: '192.168.1.50' - ip_mode: fixed - ir_n1: - model: flir_a6750 - mac: 00:11:1c:01:ec:f7 - prefer_ip: '192.168.1.51' - ip_mode: fixed - ir_n2: - model: flir_a6750 - mac: 00:11:1c:01:c8:5b - prefer_ip: '192.168.1.52' - ip_mode: fixed - -# === === === === IR "backup" cameras === === === === - - ir_nb0: - model: flir_a645 - mac: 00:11:1c:00:e6:d1 - prefer_ip: '192.168.1.53' - ip_mode: dhcp - ir_nb1: - model: flir_a645 - mac: 00:11:1c:00:bf:6a - prefer_ip: '192.168.1.54' - ip_mode: dhcp - ir_nb2: - model: flir_a645 - mac: 00:11:1c - prefer_ip: '192.168.1.55' - ip_mode: dhcp - -# === === === === rgb prosilica backup cameras === === === === - rgb_nb0: - label: CENTER - model: allied_gt6600_rgb - mac: '00:0f:31:02:37:6c' - prefer_ip: '192.168.4.40' - guid: 145260 - ip_mode: fixed - rgb_nb1: - label: unknown - model: allied_gt6600_rgb - mac: '00:0f:31:02:c2:8d' - guid: 180877 - prefer_ip: '192.168.4.41' - ip_mode: fixed - rgb_nb2: - model: allied_gt6600_rgb - label: CENTER - mac: '00:0f:31:02:c2:8c' - guid: 180876 - prefer_ip: '192.168.4.42' - ip_mode: fixed - -# === === === === rgb phase one cameras === === === === - rgb_n0: - label: CENTER - model: gsm_ix120 - mac: '00:0f:31:02:37:6c' - prefer_ip: '192.168.4.40' - guid: 145260 - ip_mode: fixed - rgb_n1: - label: unknown - model: gsm_ix120 - mac: '00:0f:31:02:c2:8d' - guid: 180877 - prefer_ip: '192.168.4.41' - ip_mode: fixed - rgb_n2: - model: gsm_ix120 - label: CENTER - mac: '00:0f:31:02:c2:8c' - guid: 180876 - prefer_ip: '192.168.4.42' - ip_mode: fixed - -# === === === === uv prosilica cameras === === === === - uv_n0: - label: unknown - model: allied_gt4907_uv - mac: '00:0f:31:03:64:5a' - guid: 222298 - prefer_ip: '192.168.2.60' - ip_mode: linklocal - - uv_n1: - label: unknown - model: allied_gt4907_uv - mac: '00:0f:31:03:65:d0' - guid: 222672 - prefer_ip: '192.168.2.61' - ip_mode: linklocal - uv_n2: - label: unknown - model: allied_gt4907_uv - mac: '00:0f:31:03:64:26' - guid: 222246 - prefer_ip: '192.168.2.62' - ip_mode: linklocal - -# This defines information about the actual camera devices, based on model name -models: - flir_a6750: - mfgr: flir - nic_mfgr: pleora - mac_prefix: 00:11:1c - spectrum: ir - specs: - width: 640 - height: 512 - flir_645: - mfgr: flir - nic_mfgr: '' - mac_prefix: '' - spectrum: ir - specs: - width: 640 - height: 480 - allied_gt6600_rgb: - # last 3 nybbles of MAC is GUID, i.e. 02:c2:8c = 0x02c28c = 180876 - mfgr: allied vision - nic_mfgr: '' - mac_prefix: '00:0f:31' - spectrum: rgb - specs: - width: 6576 - height: 4384 - allied_gt4907_uv: - mfgr: allied vision - nic_mfgr: '' - mac_prefix: '00:0f:31' - spectrum: uv - specs: - width: 4864 - height: 3232 - gsm_ix120: - mfgr: phase one - nic_mfgr: '' - mac_prefix: '' - spectrum: rgb - specs: - width: 12768 - height: 9654 - -# expert configs - -# launch params - get passed to roslaunch -launch: - cam: - rgb: - GainMode: Auto - GainValue: 0 - - uv: - GainMode: Auto - GainValue: 0 -... diff --git a/src/cfg/taiga/config.json b/src/cfg/taiga/config.json new file mode 100644 index 00000000..3a29e87a --- /dev/null +++ b/src/cfg/taiga/config.json @@ -0,0 +1,262 @@ +{ + "arch": { + "max_frame_rate": 2.0, + "min_frame_rate": 0.1, + "base_template": "{base}/{project}/fl{flight}/{sys_cfg}/", + "template": "{base}/{project}/fl{flight}/{sys_cfg}/{cam_fov}_view/{project}_fl{flight}_{cf}_{time}_{mode}.{ext}", + "max_exposure_ms": 125, + "ext_rgb": "jpg", + "ext_uv": "jpg", + "ext_ir": "tif", + "ext_evt": "json", + "ext_ins": "json", + "hosts": { + "center0taiga": { + "fov": "center", + "idx": 0, + "enabled": true + }, + "left1taiga": { + "fov": "left", + "idx": 1, + "enabled": true + }, + "right2taiga": { + "fov": "right", + "idx": 2, + "enabled": true + } + } + }, + "postproc_commands": [ + "flight_summary", + "homography", + "detections" + ], + "nas_mnt": "/mnt/flight_data", + "local_ssd_mnt": "/mnt/data", + "kamera_dir": "/home/user/kw/kamera", + "gui_cfg_dir": "/home/user/.config/kamera/gui", + "master_host": "center0taiga", + "redis_host": "center0taiga", + "verbosity": 9, + "max_mpix": 200000, + "channels": { + "ir": 0, + "rgb": 1, + "uv": 2 + }, + "interfaces": { + "rgb": "pci_btm", + "ir": "mobo_top", + "uv": "mobo_btm" + }, + "locations": { + "center": { + "ir": "ir_n0", + "rgb": "rgb_n0", + "uv": "uv_n0" + }, + "left": { + "ir": "ir_n1", + "rgb": "rgb_n1", + "uv": "uv_n1" + }, + "right": { + "ir": "ir_n2", + "rgb": "rgb_n2", + "uv": "uv_n2" + } + }, + "enabled": { + "center": { + "ir": true, + "rgb": true, + "uv": true + }, + "left": { + "ir": true, + "rgb": true, + "uv": true + }, + "right": { + "ir": true, + "rgb": true, + "uv": true + } + }, + "devices": { + "ir_n0": { + "model": "flir_a6750", + "mac": "00:11:1c:02:40:46", + "prefer_ip": "192.168.1.50", + "ip_mode": "fixed" + }, + "ir_n1": { + "model": "flir_a6750", + "mac": "00:11:1c:01:ec:f7", + "prefer_ip": "192.168.1.51", + "ip_mode": "fixed" + }, + "ir_n2": { + "model": "flir_a6750", + "mac": "00:11:1c:01:c8:5b", + "prefer_ip": "192.168.1.52", + "ip_mode": "fixed" + }, + "ir_nb0": { + "model": "flir_a645", + "mac": "00:11:1c:00:e6:d1", + "prefer_ip": "192.168.1.53", + "ip_mode": "dhcp" + }, + "ir_nb1": { + "model": "flir_a645", + "mac": "00:11:1c:00:bf:6a", + "prefer_ip": "192.168.1.54", + "ip_mode": "dhcp" + }, + "ir_nb2": { + "model": "flir_a645", + "mac": "00:11:1c", + "prefer_ip": "192.168.1.55", + "ip_mode": "dhcp" + }, + "rgb_nb0": { + "label": "CENTER", + "model": "allied_gt6600_rgb", + "mac": "00:0f:31:02:37:6c", + "prefer_ip": "192.168.4.40", + "guid": 145260, + "ip_mode": "fixed" + }, + "rgb_nb1": { + "label": "unknown", + "model": "allied_gt6600_rgb", + "mac": "00:0f:31:02:c2:8d", + "guid": 180877, + "prefer_ip": "192.168.4.41", + "ip_mode": "fixed" + }, + "rgb_nb2": { + "model": "allied_gt6600_rgb", + "label": "CENTER", + "mac": "00:0f:31:02:c2:8c", + "guid": 180876, + "prefer_ip": "192.168.4.42", + "ip_mode": "fixed" + }, + "rgb_n0": { + "label": "CENTER", + "model": "gsm_ix120", + "mac": "00:0f:31:02:37:6c", + "prefer_ip": "192.168.4.40", + "guid": 145260, + "ip_mode": "fixed" + }, + "rgb_n1": { + "label": "unknown", + "model": "gsm_ix120", + "mac": "00:0f:31:02:c2:8d", + "guid": 180877, + "prefer_ip": "192.168.4.41", + "ip_mode": "fixed" + }, + "rgb_n2": { + "model": "gsm_ix120", + "label": "CENTER", + "mac": "00:0f:31:02:c2:8c", + "guid": 180876, + "prefer_ip": "192.168.4.42", + "ip_mode": "fixed" + }, + "uv_n0": { + "label": "unknown", + "model": "allied_gt4907_uv", + "mac": "00:0f:31:03:64:5a", + "guid": 222298, + "prefer_ip": "192.168.2.60", + "ip_mode": "linklocal" + }, + "uv_n1": { + "label": "unknown", + "model": "allied_gt4907_uv", + "mac": "00:0f:31:03:65:d0", + "guid": 222672, + "prefer_ip": "192.168.2.61", + "ip_mode": "linklocal" + }, + "uv_n2": { + "label": "unknown", + "model": "allied_gt4907_uv", + "mac": "00:0f:31:03:64:26", + "guid": 222246, + "prefer_ip": "192.168.2.62", + "ip_mode": "linklocal" + } + }, + "models": { + "flir_a6750": { + "mfgr": "flir", + "nic_mfgr": "pleora", + "mac_prefix": "00:11:1c", + "spectrum": "ir", + "specs": { + "width": 640, + "height": 512 + } + }, + "flir_645": { + "mfgr": "flir", + "nic_mfgr": "", + "mac_prefix": "", + "spectrum": "ir", + "specs": { + "width": 640, + "height": 480 + } + }, + "allied_gt6600_rgb": { + "mfgr": "allied vision", + "nic_mfgr": "", + "mac_prefix": "00:0f:31", + "spectrum": "rgb", + "specs": { + "width": 6576, + "height": 4384 + } + }, + "allied_gt4907_uv": { + "mfgr": "allied vision", + "nic_mfgr": "", + "mac_prefix": "00:0f:31", + "spectrum": "uv", + "specs": { + "width": 4864, + "height": 3232 + } + }, + "gsm_ix120": { + "mfgr": "phase one", + "nic_mfgr": "", + "mac_prefix": "", + "spectrum": "rgb", + "specs": { + "width": 12768, + "height": 9654 + } + } + }, + "launch": { + "cam": { + "rgb": { + "GainMode": "Auto", + "GainValue": 0 + }, + "uv": { + "GainMode": "Auto", + "GainValue": 0 + } + } + } +} diff --git a/src/cfg/taiga/config.yaml b/src/cfg/taiga/config.yaml deleted file mode 100644 index a02b2f11..00000000 --- a/src/cfg/taiga/config.yaml +++ /dev/null @@ -1,263 +0,0 @@ ---- -# This is (eventually) to be the SINGULAR SOURCE OF TRUTH of app deployment configs -# More static configuration should be handled with compose.yml files and .launch files - -# Position of reference frame of the camera array. Corresponds to field of view -# See airplane diagram: -# Port Starbrd -# _ -# /^\ -# x | | x -# <==Û=| |=Û==> -# | | -# \ / -# <> -#[ L] [ C ] [R ] Fields of View -# -# {left, right, center, NONE} use NONE with ROLE=NONE - - -# Camera information and configuration: -arch: - max_frame_rate: 2.0 # max fps we can request of the cameras - min_frame_rate: 0.1 - base_template: "{base}/{project}/fl{flight}/{sys_cfg}/" - template: "{base}/{project}/fl{flight}/{sys_cfg}/{cam_fov}_view/{project}_fl{flight}_{cf}_{time}_{mode}.{ext}" - max_exposure_ms: 125 - ext_rgb: jpg - ext_uv: jpg - ext_ir: tif - ext_evt: json - ext_ins: json - hosts: - center0taiga: - fov: center - idx: 0 - enabled: true - left1taiga: - fov: left - idx: 1 - enabled: true - right2taiga: - fov: right - idx: 2 - enabled: true -postproc_commands: - - "flight_summary" - - "homography" - - "detections" -nas_mnt: "/mnt/flight_data" -local_ssd_mnt: "/mnt/data" -kamera_dir: "/home/user/kw/kamera" -gui_cfg_dir: "/home/user/.config/kamera/gui" -master_host: center0taiga -redis_host: center0taiga -verbosity: 9 -max_mpix: 200000 # 0.2e6 - -channels: - ir: 0 - rgb: 1 - uv: 2 -interfaces: - # map channels to ethernet interface names - # this is gonna usurp the locations mapping - rgb: pci_btm - ir: mobo_top - uv: mobo_btm -locations: - # this maps a DEV_ID to a specific FOV. Use this section - # to swap which physical cameras map to software FOV - center: - ir: ir_n0 - rgb: rgb_n0 - uv: uv_n0 - left: - ir: ir_n1 - rgb: rgb_n1 - uv: uv_n1 - right: - ir: ir_n2 - rgb: rgb_n2 - uv: uv_n2 - -enabled: - center: - ir: true - rgb: true - uv: true - left: - ir: true - rgb: true - uv: true - right: - ir: true - rgb: true - uv: true - -# This is configuration information for each physical device -# `ir_n0` is a DEV_ID. This is an abstract label and has no absolute correlation -# with FOV. This makes it easy and less error-prone to reroute camera defs -devices: -# === === === === cooled FLIR cameras === === === === - ir_n0: - model: flir_a6750 - mac: 00:11:1c:02:40:46 - prefer_ip: '192.168.1.50' - ip_mode: fixed - ir_n1: - model: flir_a6750 - mac: 00:11:1c:01:ec:f7 - prefer_ip: '192.168.1.51' - ip_mode: fixed - ir_n2: - model: flir_a6750 - mac: 00:11:1c:01:c8:5b - prefer_ip: '192.168.1.52' - ip_mode: fixed - -# === === === === IR "backup" cameras === === === === - - ir_nb0: - model: flir_a645 - mac: 00:11:1c:00:e6:d1 - prefer_ip: '192.168.1.53' - ip_mode: dhcp - ir_nb1: - model: flir_a645 - mac: 00:11:1c:00:bf:6a - prefer_ip: '192.168.1.54' - ip_mode: dhcp - ir_nb2: - model: flir_a645 - mac: 00:11:1c - prefer_ip: '192.168.1.55' - ip_mode: dhcp - -# === === === === rgb prosilica backup cameras === === === === - rgb_nb0: - label: CENTER - model: allied_gt6600_rgb - mac: '00:0f:31:02:37:6c' - prefer_ip: '192.168.4.40' - guid: 145260 - ip_mode: fixed - rgb_nb1: - label: unknown - model: allied_gt6600_rgb - mac: '00:0f:31:02:c2:8d' - guid: 180877 - prefer_ip: '192.168.4.41' - ip_mode: fixed - rgb_nb2: - model: allied_gt6600_rgb - label: CENTER - mac: '00:0f:31:02:c2:8c' - guid: 180876 - prefer_ip: '192.168.4.42' - ip_mode: fixed - -# === === === === rgb phase one cameras === === === === - rgb_n0: - label: CENTER - model: gsm_ix120 - mac: '00:0f:31:02:37:6c' - prefer_ip: '192.168.4.40' - guid: 145260 - ip_mode: fixed - rgb_n1: - label: unknown - model: gsm_ix120 - mac: '00:0f:31:02:c2:8d' - guid: 180877 - prefer_ip: '192.168.4.41' - ip_mode: fixed - rgb_n2: - model: gsm_ix120 - label: CENTER - mac: '00:0f:31:02:c2:8c' - guid: 180876 - prefer_ip: '192.168.4.42' - ip_mode: fixed - -# === === === === uv prosilica cameras === === === === - uv_n0: - label: unknown - model: allied_gt4907_uv - mac: '00:0f:31:03:64:5a' - guid: 222298 - prefer_ip: '192.168.2.60' - ip_mode: linklocal - - uv_n1: - label: unknown - model: allied_gt4907_uv - mac: '00:0f:31:03:65:d0' - guid: 222672 - prefer_ip: '192.168.2.61' - ip_mode: linklocal - uv_n2: - label: unknown - model: allied_gt4907_uv - mac: '00:0f:31:03:64:26' - guid: 222246 - prefer_ip: '192.168.2.62' - ip_mode: linklocal - -# This defines information about the actual camera devices, based on model name -models: - flir_a6750: - mfgr: flir - nic_mfgr: pleora - mac_prefix: 00:11:1c - spectrum: ir - specs: - width: 640 - height: 512 - flir_645: - mfgr: flir - nic_mfgr: '' - mac_prefix: '' - spectrum: ir - specs: - width: 640 - height: 480 - allied_gt6600_rgb: - # last 3 nybbles of MAC is GUID, i.e. 02:c2:8c = 0x02c28c = 180876 - mfgr: allied vision - nic_mfgr: '' - mac_prefix: '00:0f:31' - spectrum: rgb - specs: - width: 6576 - height: 4384 - allied_gt4907_uv: - mfgr: allied vision - nic_mfgr: '' - mac_prefix: '00:0f:31' - spectrum: uv - specs: - width: 4864 - height: 3232 - gsm_ix120: - mfgr: phase one - nic_mfgr: '' - mac_prefix: '' - spectrum: rgb - specs: - width: 12768 - height: 9654 - -# expert configs - -# launch params - get passed to roslaunch -launch: - cam: - rgb: - GainMode: Auto - GainValue: 0 - - uv: - GainMode: Auto - GainValue: 0 -... diff --git a/src/core/kamcore/scripts/seed_redis_config.py b/src/core/kamcore/scripts/seed_redis_config.py index f964f52b..220dc0ae 100755 --- a/src/core/kamcore/scripts/seed_redis_config.py +++ b/src/core/kamcore/scripts/seed_redis_config.py @@ -1,5 +1,5 @@ #! /usr/bin/python -"""Seed Redis with the static system config from config.yaml. +"""Seed Redis with the static system config from config.json. kamcore nodes (cam_param_monitor, fps_monitor, ...) read /sys/arch/* and /sys/channels straight from Redis, but nothing in the core startup populates @@ -7,14 +7,14 @@ wxpython_gui.cfg, so the nodes raced (and crashed against) the GUI on a fresh boot. This seeds the static config up front so they no longer depend on it. -Only config.yaml (the static deployment truth) is written; operator-mutable -session state (flight, project, effort, ...) stays owned by the GUI. config.yaml +Only config.json (the static deployment truth) is written; operator-mutable +session state (flight, project, effort, ...) stays owned by the GUI. config.json keys are authoritative, so overwriting any stale Redis values here is correct. """ import os import sys -import yaml +import json from roskv.impl.redis_envoy import RedisEnvoy @@ -23,14 +23,14 @@ def main(): if len(sys.argv) > 1: cfg_file = sys.argv[1] else: - cfg_file = "/cfg/%s/config.yaml" % os.environ["SYSTEM_NAME"] + cfg_file = "/cfg/%s/config.json" % os.environ["SYSTEM_NAME"] with open(cfg_file, "r") as stream: - config = yaml.safe_load(stream) + config = json.load(stream) envoy = RedisEnvoy(os.environ["REDIS_HOST"], client_name="config_seeder") - # config.yaml is authoritative for its static keys. Clear each static subtree - # first so keys removed from the yaml (e.g. a dropped channel) don't linger + # config.json is authoritative for its static keys. Clear each static subtree + # first so keys removed from the config (e.g. a dropped channel) don't linger # in Redis -- put only sets keys, it never deletes. "arch" also carries the # GUI's mutable session state (flight, project, ...), so only its static # "hosts" subtree is reset there, never all of /sys/arch. @@ -44,7 +44,7 @@ def main(): envoy.delete_dict("/sys/arch/hosts") except Exception: pass - # Mirror wxpython_gui.cfg: each top-level config.yaml key is published under + # Mirror wxpython_gui.cfg: each top-level config.json key is published under # /sys (RedisEnvoy.put flattens nested dicts into keypaths). for key, val in config.items(): envoy.put("/sys/%s" % key, val) diff --git a/src/kitware-ros-pkg/wxpython_gui/src/wxpython_gui/cfg.py b/src/kitware-ros-pkg/wxpython_gui/src/wxpython_gui/cfg.py index 40b24c47..34a36109 100644 --- a/src/kitware-ros-pkg/wxpython_gui/src/wxpython_gui/cfg.py +++ b/src/kitware-ros-pkg/wxpython_gui/src/wxpython_gui/cfg.py @@ -5,7 +5,6 @@ import redis import re import time -import yaml from collections import OrderedDict from functools import reduce @@ -29,11 +28,11 @@ # These never-changing values are placed under "/sys/arch", and will never # have to be backed up system_name = os.getenv("SYSTEM_NAME") -cfg_file = "%s/src/cfg/%s/config.yaml" % (REAL_KAM_REPO_DIR, system_name) +cfg_file = "%s/src/cfg/%s/config.json" % (REAL_KAM_REPO_DIR, system_name) with open(cfg_file, "r") as stream: try: - USER_CFG = yaml.safe_load(stream) - except yaml.YAMLError as exc: + USER_CFG = json.load(stream) + except json.JSONDecodeError as exc: print(exc) # Need a redis instance to push/pull from kv = ImplEnvoy(host=USER_CFG["redis_host"]) @@ -95,7 +94,7 @@ def update(self, *args, **kwargs): # 1. default_system_state.json factory defaults # 2. /system_state.json last session (the only thing saved back) # 3. Redis /sys/* live runtime values -# 4. config.yaml (USER_CFG) static truth; ALWAYS WINS for its keys +# 4. config.json (USER_CFG) static truth; ALWAYS WINS for its keys # camera_configurations.json owns SYS_CFG["camera_cfgs"]. @@ -173,8 +172,8 @@ def deep_merge(base, override): deep_merge(SYS_ARCH, DEFAULT_STATE) # 1. factory defaults deep_merge(SYS_ARCH, CACHE_STATE) # 2. operator's last session deep_merge(SYS_ARCH, REDIS_LIVE) # 3. live runtime values -# 4. config.yaml OWNS the static keys it declares: replace rather than merge, so -# a key removed from the yaml (e.g. a dropped channel) can't survive from a +# 4. config.json OWNS the static keys it declares: replace rather than merge, so +# a key removed from the config (e.g. a dropped channel) can't survive from a # lower tier. "arch" mixes static + mutable session subkeys, so only its # static subkeys are replaced. for key, val in USER_CFG.items(): @@ -186,7 +185,7 @@ def deep_merge(base, override): SYS_ARCH["camera_cfgs"] = CAMERA_PRESETS # Publish to Redis under /sys. First drop the static subtrees so keys removed -# from config.yaml don't linger (put only sets keys, never deletes); the update +# from config.json don't linger (put only sets keys, never deletes); the update # then republishes the authoritative values. arch.hosts is the only static dict # under "arch" -- the rest of /sys/arch holds mutable state we must not wipe. for key, val in USER_CFG.items(): diff --git a/src/run_scripts/entry/master.sh b/src/run_scripts/entry/master.sh index 8b20abf5..29d8597e 100755 --- a/src/run_scripts/entry/master.sh +++ b/src/run_scripts/entry/master.sh @@ -4,7 +4,7 @@ echo "[ ] [ ] [ ] KAMCORE [ ] [ ] [ ] " # dump the global config as a debugging step -cat /cfg/${SYSTEM_NAME}/config.yaml +cat /cfg/${SYSTEM_NAME}/config.json source /entry/project_env.sh @@ -27,7 +27,7 @@ redis-client -h ${REDIS_HOST} incr term # Seed Redis with the static system config before anything starts, so kamcore # nodes (cam_param_monitor, etc.) read /sys/arch from Redis without depending on # the GUI. Done before roscore so the --wait monitors can't start until it's up. -rosrun kamcore seed_redis_config.py /cfg/${SYSTEM_NAME}/config.yaml +rosrun kamcore seed_redis_config.py /cfg/${SYSTEM_NAME}/config.json # Start core and block until it's up, then bootstrap parameters roscore & @@ -44,6 +44,6 @@ until /entry/rosnode_list.sh; do fi done -rosparam load /cfg/${SYSTEM_NAME}/config.yaml /cfg +rosparam load /cfg/${SYSTEM_NAME}/config.json /cfg exec roslaunch kamcore kamcore.launch data_mount_point:=$DATA_MOUNT_POINT \ spoof_rate:="${SPOOF_RATE}" From 7850f22afb386cc36c4671093aa024abe7c29ffb Mon Sep 17 00:00:00 2001 From: "cameron.johnson" Date: Tue, 29 Sep 2026 10:31:51 -0400 Subject: [PATCH 2/6] Stop installing yq; nothing consumes it since the JSON config switch --- docker/base/core-deps.dockerfile | 5 ----- docker/base/detector-viame-deps.dockerfile | 5 ----- provision/ansible/playbooks/provision.yml | 15 --------------- 3 files changed, 25 deletions(-) diff --git a/docker/base/core-deps.dockerfile b/docker/base/core-deps.dockerfile index 18df1ef9..34ecadda 100644 --- a/docker/base/core-deps.dockerfile +++ b/docker/base/core-deps.dockerfile @@ -85,11 +85,6 @@ RUN :\ && make -j && make install \ &&: -# Add yq for configu query to work -RUN curl -sL https://github.com/mikefarah/yq/releases/download/3.4.1/yq_linux_amd64 \ - -o /usr/local/bin/yq && \ - chmod +x /usr/local/bin/yq - ## =================== install ebus sdk =================== COPY ./artifacts/ebus.deb /ebus.deb COPY ./artifacts/GigE-V-Framework_x86_2.02.0.0132.tar.gz /gigev.tar.gz diff --git a/docker/base/detector-viame-deps.dockerfile b/docker/base/detector-viame-deps.dockerfile index 12675132..d1047358 100644 --- a/docker/base/detector-viame-deps.dockerfile +++ b/docker/base/detector-viame-deps.dockerfile @@ -37,11 +37,6 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ # Build tools necessary for catkin and roskv -# Add yq to make config query work -RUN curl -sL https://github.com/mikefarah/yq/releases/download/2.4.0/yq_linux_amd64 \ - -o /usr/local/bin/yq && \ - chmod +x /usr/local/bin/yq - ## === === === === === === === === === === === === === === === # Clone in C++ Deps for Redis RUN mkdir /src diff --git a/provision/ansible/playbooks/provision.yml b/provision/ansible/playbooks/provision.yml index 193a3fa2..3c8bd08d 100644 --- a/provision/ansible/playbooks/provision.yml +++ b/provision/ansible/playbooks/provision.yml @@ -37,14 +37,6 @@ ] pre_tasks: - - shell: uname -s - ignore_errors: yes - register: uname_s - - - shell: uname -m - ignore_errors: yes - register: uname_m - - name: Fully Update System become: True become_user: root @@ -174,13 +166,6 @@ groups: ['user', 'docker', 'dialout', 'sudo'] tasks: - - name: Install yq - become: True - get_url: - url: "https://github.com/mikefarah/yq/releases/download/2.4.0/yq_{{ uname_s.stdout }}_amd64" - dest: /usr/local/bin/yq - mode: '0755' - # - name: Reboot system # become: True # reboot: From 445946eb786478c4a429b3a6f0e856552c32bb48 Mon Sep 17 00:00:00 2001 From: Adam Romlein Date: Tue, 29 Sep 2026 10:31:51 -0400 Subject: [PATCH 3/6] Remove unused setup scripts: install_extras, check_system, setup_kamera_env Nothing references them; all three still installed or checked for yq. --- src/run_scripts/entry/setup_kamera_env.sh | 63 ----------- src/run_scripts/setup/check_system.sh | 129 ---------------------- src/run_scripts/setup/install_extras.bash | 16 --- 3 files changed, 208 deletions(-) delete mode 100755 src/run_scripts/entry/setup_kamera_env.sh delete mode 100755 src/run_scripts/setup/check_system.sh delete mode 100755 src/run_scripts/setup/install_extras.bash diff --git a/src/run_scripts/entry/setup_kamera_env.sh b/src/run_scripts/entry/setup_kamera_env.sh deleted file mode 100755 index 2fdcbb75..00000000 --- a/src/run_scripts/entry/setup_kamera_env.sh +++ /dev/null @@ -1,63 +0,0 @@ -#!/usr/bin/env bash - -## TODO: IN THE PROCESS OF DEPRECATION IN FAVOR OF yq-based config - -# Set up the environmental variables that define the behavior of the current node -# This is useful both inside and out of containers - -## === === === === User-set configuration === === === === - -KAM_REPO_DIR=$(~/.config/kamera/repo_dir.bash) -source ${KAM_REPO_DIR}/src/cfg/cfg-aliases.sh # get cq - ConfigQuery - -## tell the system hostname of the node acting as ROS master host -export MASTER_HOST=$(cq '.master_host') - -## === === === === Static configuration === === === === - -export _ROS_PORT=11311 - - -## === === === === default values === === === -# index number of the system, 0 being master -SYSIDX=0 - - -CAM_FOV=${CAM_FOV:-NONE} - - -## === === === === Infer variables === === === -# Determine env variables based on configuration -# and parameters from system such as hostname - - -# Check cgroup to see if we are running inside a container -if [[ -n `grep docker /proc/1/cgroup` ]] ; then - export IS_CONTAINER=true -else - export REPO_DIR=$HOME/kw/kamera -fi - -## name of current host -export HOST=`hostname` - -## name of current host, passed to ROS -export ROS_HOSTNAME=`hostname` - -NODE_HOSTNAME=${NODE_HOSTNAME:-${ROS_HOSTNAME}} - -echo "node hostname: $NODE_HOSTNAME . is_container: ${IS_CONTAINER:-false}" - -if [[ -z ${NODE_HOSTNAME} ]] ; then - echo "WARNING: NODE_HOSTNAME not set! This happens in builds, but should not happen in production" -fi - -if [[ -z $IS_CONTAINER ]] ; then - SUBDIR=/kw - export REPO_DIR=${HOME}${SUBDIR}/kamera -fi - - -## This is some jankitude to set the pod. I really wanna fix this -export NODE_HOSTNAME -export ROS_MASTER_URI="http://${MASTER_HOST}:${_ROS_PORT}/" diff --git a/src/run_scripts/setup/check_system.sh b/src/run_scripts/setup/check_system.sh deleted file mode 100755 index 29a8f31d..00000000 --- a/src/run_scripts/setup/check_system.sh +++ /dev/null @@ -1,129 +0,0 @@ -#!/usr/bin/env bash - -FAIL_ON_CHECK_COMMAND=${FAIL_ON_CHECK_COMMAND} - -logbold() { - (echo >&2 -e "\e[1m$1\e[0m") -} - -logred() { - (echo >&2 -e "\e[31m$1\e[0m") -} - -loggrn() { - (echo >&2 -e "\e[32m$1\e[0m") -} - -logyel() { - (echo >&2 -e "\e[33m$1\e[0m") -} - -logmag() { - (echo >&2 -e "\e[35m$1\e[0m") -} - - -function check_command() { - if ! command -v "${2}" &>/dev/null; then - if [[ "$1" == "E" ]]; then - MSG="command could not be found. Please make sure it is installed and in your PATH:\e[1m $2" - logred "$MSG" - if [[ -n "${FAIL_ON_CHECK_COMMAND}" ]]; then - exit 1 - fi - else - logyel "MISSING :\e[1m $2" - fi - else - loggrn "FOUND :\e[1m $2" - fi -} - -function check_run() { - MSG="${1}" - ARGS=( "${@:2}" ) - logmag "checking: ${ARGS[*]}" - - if ! ${ARGS[*]} 1>/dev/null; then - MSG="FAILED : ${MSG}: ${ARGS[*]}" - logred "${MSG}" - else - loggrn "SUCCESS :\e[1m ${MSG}" - fi -} - - -function check_result() { - MSG="${1}" - LVL="${2}" - RES="${3}" - - if [[ -z "${RES}" ]]; then - if [[ "${LVL}" == "E" ]]; then - logred "FAILED :\e[1m ${MSG}: false" - else - logyel "WARNING :\e[1m ${MSG}: false" - fi - else - loggrn "SUCCESS :\e[1m ${MSG}" - fi -} - -function check_exists() { - PATH="${1}" - LVL="${2}" - - if [[ ! -e "${PATH}" ]]; then - if [[ "${LVL}" == "E" ]]; then - logred "MISSING :\e[1m ${PATH}" - else - logyel "MISSING :\e[1m ${PATH}" - fi - else - loggrn "FOUND :\e[1m ${PATH}" - fi -} - - -if ! echo hi | grep -P hi &>/dev/null; then - errcho "Error: You need gnu grep (with -P flag) in your PATH"; exit 1 -fi - -logbold "checking for which necessary commands are available:" - -check_command E docker -check_command E docker compose -check_command E python3 -check_command E git -check_command E ifconfig - -logbold "checking for commands necessary for Nuvos:" -check_command W nvidia-smi -check_command W redis-cli -check_command W redis-server -check_command W yq -check_command W jq - -logbold "checking other conditions:" - -for VNAME in REDIS_HOST ROS_MASTER_URI -do - if [[ -z "${!VNAME}" ]]; then - logyel "UNSET :\e[1m ${VNAME}=" - elif [[ "${!VNAME}" == 'null' ]] ; then - echo "ERROR: $VNAME is null. check config" - else - loggrn "INFO :\e[1m ${VNAME}=${!VNAME}" - fi -done - -check_result "user in docker group" E "$(groups | grep docker)" -check_result "user in dialout group" W "$(groups | grep dialout)" -check_run "connect to redis" "redis-cli -h ${REDIS_HOST} client list" -check_result "interface pci_top exists" W "$(ifconfig | grep pci_top)" -check_result "interface pci_btm exists" W "$(ifconfig | grep pci_btm)" -check_result "interface mobo_top exists" W "$(ifconfig | grep mobo_top)" -check_result "interface mobo_btm exists" W "$(ifconfig | grep mobo_btm)" -check_result "network is on 192.168.88" W "$(ifconfig | grep '192.168.88')" -check_exists "$HOME/kw/kamera" E - diff --git a/src/run_scripts/setup/install_extras.bash b/src/run_scripts/setup/install_extras.bash deleted file mode 100755 index 3ebe8f04..00000000 --- a/src/run_scripts/setup/install_extras.bash +++ /dev/null @@ -1,16 +0,0 @@ -#!/bin/bash -# Sets up the Nuvo computer from a fresh Ubuntu X.04 install - -sudo apt update -sudo apt install -y \ - jq \ - lm-sensors \ - tree \ - cowsay \ - lldpd - -# get yq -sudo curl -sL https://github.com/mikefarah/yq/releases/download/2.4.0/yq_linux_amd64 \ - -o /usr/local/bin/yq &&\ - sudo chmod +x /usr/local/bin/yq - From 0d5707a12eb22b9c9ae8d803d4b9aa2a776f36df Mon Sep 17 00:00:00 2001 From: Adam Romlein Date: Tue, 29 Sep 2026 10:48:45 -0400 Subject: [PATCH 4/6] Remove unused nexus and syscall entry scripts No compose file launches them. --- src/run_scripts/entry/nexus.sh | 14 -------------- src/run_scripts/entry/syscall.sh | 12 ------------ 2 files changed, 26 deletions(-) delete mode 100755 src/run_scripts/entry/nexus.sh delete mode 100755 src/run_scripts/entry/syscall.sh diff --git a/src/run_scripts/entry/nexus.sh b/src/run_scripts/entry/nexus.sh deleted file mode 100755 index 9e6ef2a7..00000000 --- a/src/run_scripts/entry/nexus.sh +++ /dev/null @@ -1,14 +0,0 @@ -#!/bin/bash - -# Nexus node startup script - -echo "<> <> <> NEXUS <> <> <> " -source /entry/project.sh - -pip install redis - -ROSWAIT="--wait" - -exec roslaunch "${ROSWAIT}" nexus nexus.launch \ - system_name:=${NODE_HOSTNAME} \ - verbosity:=$(/cfg/get ".verbosity") diff --git a/src/run_scripts/entry/syscall.sh b/src/run_scripts/entry/syscall.sh deleted file mode 100755 index f2f5445e..00000000 --- a/src/run_scripts/entry/syscall.sh +++ /dev/null @@ -1,12 +0,0 @@ -#!/bin/bash - -# System call service node - -echo "<> <> <> SysCall <> <> <> " -source /entry/project.sh - -ROSWAIT="--wait" - -exec roslaunch "${ROSWAIT}" sysinfo syscall.launch \ - system_name:=`hostname` \ - verbosity:=$(/cfg/get ".verbosity") From f2961d3ca2f2cde37316ca9745597558eef51b48 Mon Sep 17 00:00:00 2001 From: Adam Romlein Date: Tue, 29 Sep 2026 10:48:45 -0400 Subject: [PATCH 5/6] Replace cq, get and the /cfg symlink with kamera-cfg kamera-cfg lives in src/run_scripts/inpath, which is on PATH in the containers and via runtime/env.sh on the host, and finds config.json relative to itself. Callers query the config with 'kamera-cfg ' instead of the cq shell function, the get wrapper, or /cfg/get, which read an unset CFG_FILE inside the containers. master.sh and seed_redis_config.py read the config from REPO_DIR, so the /cfg symlink in the core and gui images goes. --- docker/core.dockerfile | 1 - docker/gui.dockerfile | 1 - runtime/env.sh | 16 ++++++------- scripts/docker_images.sh | 2 +- scripts/kamera_halt.sh | 6 ++--- scripts/kamera_run.sh | 18 +++++++-------- src/cfg/README.md | 4 ++-- src/cfg/cfg-aliases.sh | 12 ---------- src/cfg/get | 8 ------- src/core/kamcore/scripts/seed_redis_config.py | 5 +++- src/run_scripts/entry/cam_ir.sh | 17 +++++--------- src/run_scripts/entry/cam_phaseone.sh | 19 ++++++--------- src/run_scripts/entry/cam_prosilica.sh | 23 ++++++++----------- src/run_scripts/entry/gui.sh | 8 +------ src/run_scripts/entry/master.sh | 6 ++--- src/run_scripts/entry/postproc.sh | 7 +++--- src/run_scripts/entry/viame.sh | 7 +++--- src/run_scripts/inpath/kamera-cfg | 8 +++++++ 18 files changed, 67 insertions(+), 101 deletions(-) delete mode 100755 src/cfg/cfg-aliases.sh delete mode 100755 src/cfg/get create mode 100755 src/run_scripts/inpath/kamera-cfg diff --git a/docker/core.dockerfile b/docker/core.dockerfile index 7dc471b4..1acff66f 100644 --- a/docker/core.dockerfile +++ b/docker/core.dockerfile @@ -15,7 +15,6 @@ RUN rm -rf /entry \ && printf "\nsource /aliases.sh\n" >> /root/.bashrc RUN ln -sf $REPO_DIR/scripts/activate_ros.bash $REPO_DIR/activate_ros.bash -RUN ln -sf $REPO_DIR/src/cfg /cfg RUN mkdir -p /root/.config/kamera && \ ln -sf $REPO_DIR/.dir /root/.config/kamera/repo_dir.bash diff --git a/docker/gui.dockerfile b/docker/gui.dockerfile index fdbf0e66..aa9ac01a 100644 --- a/docker/gui.dockerfile +++ b/docker/gui.dockerfile @@ -29,7 +29,6 @@ RUN rm -rf /entry \ && printf "\nsource /aliases.sh\n" >> /home/user/.bashrc RUN ln -sf $REPO_DIR/scripts/activate_ros.bash $REPO_DIR/activate_ros.bash -RUN ln -sf $REPO_DIR/src/cfg /cfg RUN mkdir -p /home/user/.config/kamera && \ ln -sf $REPO_DIR/.dir /home/user/.config/kamera/repo_dir.bash diff --git a/runtime/env.sh b/runtime/env.sh index 371e23cc..99bb901d 100644 --- a/runtime/env.sh +++ b/runtime/env.sh @@ -3,12 +3,12 @@ SYSTEM_NAME="$(cat ${HOME}/kw/SYSTEM_NAME)" export SYSTEM_NAME export KAMERA_DIR=$(${HOME}/.config/kamera/repo_dir.bash) -CFG_FILE="${KAMERA_DIR}/src/cfg/${SYSTEM_NAME}/config.json" -cq () { - CFG_FILE=${CFG_FILE} ${KAMERA_DIR}/src/cfg/get "$@" -} +case ":${PATH}:" in + *":${KAMERA_DIR}/src/run_scripts/inpath:"*) ;; + *) export PATH="${KAMERA_DIR}/src/run_scripts/inpath:${PATH}" ;; +esac -export REDIS_HOST=$(cq ".redis_host") +export REDIS_HOST=$(kamera-cfg ".redis_host") # Uncomment this line if you wish to run the GUI in "offline" mode # (without center0, left1, etc. hooked up) @@ -28,12 +28,12 @@ unset _redis_elapsed echo "Redis successfully connected at ${REDIS_HOST}, starting." -export ROS_HOSTNAME=$(cq ".master_host") +export ROS_HOSTNAME=$(kamera-cfg ".master_host") export NODE_HOSTNAME=$(hostname) export ROS_MASTER_URI="http://${ROS_HOSTNAME}:11311" export DOCKER_KAMERA_DIR="/root/kamera" -export DATA_MOUNT_POINT=$(cq .local_ssd_mnt) -export CAM_FOV=$(cq ".arch.hosts[\"${NODE_HOSTNAME}\"].fov") +export DATA_MOUNT_POINT=$(kamera-cfg .local_ssd_mnt) +export CAM_FOV=$(kamera-cfg ".arch.hosts[\"${NODE_HOSTNAME}\"].fov") export ROS_DISTRO="noetic" export KAMERA_DNS_IP="192.168.88.1" diff --git a/scripts/docker_images.sh b/scripts/docker_images.sh index 600a8356..a4dd51d2 100755 --- a/scripts/docker_images.sh +++ b/scripts/docker_images.sh @@ -12,7 +12,7 @@ KAM_REPO_DIR=$(/home/user/.config/kamera/repo_dir.bash) echo $KAM_REPO_DIR source "${KAM_REPO_DIR}/runtime/env.sh" -MASTER_HOST=$(cq '.master_host') +MASTER_HOST=$(kamera-cfg '.master_host') if [[ -z "$@" ]] ; then ARGS=(start) diff --git a/scripts/kamera_halt.sh b/scripts/kamera_halt.sh index 0f9b7e5b..2fbd7629 100755 --- a/scripts/kamera_halt.sh +++ b/scripts/kamera_halt.sh @@ -48,7 +48,7 @@ if [[ -z "${KAM_REPO_DIR}" ]]; then fi blueprintf "." -MASTER_HOST=$(cq '.master_host') +MASTER_HOST=$(kamera-cfg '.master_host') ## === === === === === === End Env setup === === === === === === @@ -62,8 +62,8 @@ blueprintf "done\nGui down. Killing pods...\n" # Bring up all pod systems # Query list of hosts as line delim array declare -A PIDS -for host in $(cq '.arch.hosts | keys | join("\n" )') ; do - if [[ $(cq ".arch.hosts.${host}.enabled") == 'true' ]]; then +for host in $(kamera-cfg '.arch.hosts | keys | join("\n" )') ; do + if [[ $(kamera-cfg ".arch.hosts.${host}.enabled") == 'true' ]]; then python3 ${KAM_REPO_DIR}/scripts/system.py $host ${ARGS[@]} pod & PIDS["${host}_pod"]=$! python3 ${KAM_REPO_DIR}/scripts/system.py $host ${ARGS[@]} detector & diff --git a/scripts/kamera_run.sh b/scripts/kamera_run.sh index e9277767..8fd92fbb 100755 --- a/scripts/kamera_run.sh +++ b/scripts/kamera_run.sh @@ -60,7 +60,7 @@ blueprintf "Configuring main KAMERA entrypoint." source ${KAM_REPO_DIR}/scripts/set_detector_read_state.sh blueprintf "." -MASTER_HOST=$(cq '.master_host') +MASTER_HOST=$(kamera-cfg '.master_host') for VNAME in MASTER_HOST KAM_REPO_DIR do @@ -81,7 +81,7 @@ until ping -c1 -W1 ${MASTER_HOST} &>/dev/null; do done SKIP_PING=true -for host in $(cq '.arch.hosts | keys | join("\n" )') ; do +for host in $(kamera-cfg '.arch.hosts | keys | join("\n" )') ; do hostip=$(dig +short $host) if [[ $? != 0 ]]; then errcho "FATAL: Cannot resolve IP for necassary host ${host}" @@ -96,9 +96,9 @@ done if [[ -n ${SKIP_PING} ]]; then echo "all clients located, yay!" else - for host in $(cq '.arch.hosts | keys | join("\n" )') ; do + for host in $(kamera-cfg '.arch.hosts | keys | join("\n" )') ; do echo "Waiting on ping $host." - if [[ $(cq ".arch.hosts.${host}.enabled") == 'true' ]]; then + if [[ $(kamera-cfg ".arch.hosts.${host}.enabled") == 'true' ]]; then until ping -c1 -W1 ${host} &>/dev/null; do printf "\b${SP:i++%${#SP}:1}" done @@ -119,8 +119,8 @@ else echo "NAS mounted!" fi declare -A PIDS -for host in $(cq '.arch.hosts | keys | join("\n" )') ; do - if [[ $(cq ".arch.hosts.${host}.enabled") == 'true' ]]; then +for host in $(kamera-cfg '.arch.hosts | keys | join("\n" )') ; do + if [[ $(kamera-cfg ".arch.hosts.${host}.enabled") == 'true' ]]; then python3 ${KAM_REPO_DIR}/scripts/system.py $host restart nas & PIDS[${host}]=$! else @@ -135,7 +135,7 @@ done # Bring up master and core nodes -MASTER_HOST=$(cq '.master_host') +MASTER_HOST=$(kamera-cfg '.master_host') blueprintf "done\nBringing up master $MASTER_HOST..." python3 ${KAM_REPO_DIR}/scripts/system.py $MASTER_HOST "${ARGS[@]}" master @@ -163,11 +163,11 @@ blueprintf "done\nLaunching pod nodes...\n" # Query list of hosts as line delim array declare -A PIDS # sort, so hosts are started idempotently -hosts=$(cq '.arch.hosts | keys | join("\n" )') +hosts=$(kamera-cfg '.arch.hosts | keys | join("\n" )') IFS=$'\n' sorted_hosts=($(sort <<<"${hosts[*]}")) unset IFS for host in "${sorted_hosts[@]}"; do - if [[ $(cq ".arch.hosts.${host}.enabled") == 'true' ]]; then + if [[ $(kamera-cfg ".arch.hosts.${host}.enabled") == 'true' ]]; then # daemon group (kamerad) is always started and never stopped by normal operations python3 ${KAM_REPO_DIR}/scripts/system.py $host start daemon python3 ${KAM_REPO_DIR}/scripts/system.py $host "${ARGS[@]}" pod & diff --git a/src/cfg/README.md b/src/cfg/README.md index 6fc161fa..c29f25a7 100644 --- a/src/cfg/README.md +++ b/src/cfg/README.md @@ -6,8 +6,8 @@ handled with compose.yml files and .launch files. It is read in two ways, both of which expect plain JSON: -- shell: the `cq` helper (`cfg-aliases.sh` / `runtime/env.sh`) runs - `src/cfg/get`, which is a plain `jq -r config.json` +- shell: `kamera-cfg ` (`src/run_scripts/inpath/kamera-cfg`), a + plain `jq -r config.json` - python: `kamcore/scripts/seed_redis_config.py` and `wxpython_gui.cfg` load it and seed the static keys into redis (config.json always wins for its keys; operator-mutable session state stays owned by the GUI) diff --git a/src/cfg/cfg-aliases.sh b/src/cfg/cfg-aliases.sh deleted file mode 100755 index 486a8c60..00000000 --- a/src/cfg/cfg-aliases.sh +++ /dev/null @@ -1,12 +0,0 @@ -#!/usr/bin/env bash - -## Aliases used with configurating - -## make this config dir self-hosting directory-wise -CFG_DIR="${KAM_REPO_DIR}/src/cfg" -export CFG_ALIAS_SET=true - -# ConfigQuery -cq () { - CFG_FILE=${CFG_DIR}/${SYSTEM_NAME}/config.json ${CFG_DIR}/get "$@" -} diff --git a/src/cfg/get b/src/cfg/get deleted file mode 100755 index 76493a72..00000000 --- a/src/cfg/get +++ /dev/null @@ -1,8 +0,0 @@ -#!/usr/bin/env bash - -# Retrieve values from the per-system config.json; queries are plain jq. -# (Historically this piped config.yaml through a pinned yq v3 binary into -# jq; the configs are JSON now, so jq alone does the job.) - -CFG_FILE="${CFG_FILE}" -exec jq -r "${1}" "${CFG_FILE}" diff --git a/src/core/kamcore/scripts/seed_redis_config.py b/src/core/kamcore/scripts/seed_redis_config.py index 220dc0ae..4f0f558b 100755 --- a/src/core/kamcore/scripts/seed_redis_config.py +++ b/src/core/kamcore/scripts/seed_redis_config.py @@ -23,7 +23,10 @@ def main(): if len(sys.argv) > 1: cfg_file = sys.argv[1] else: - cfg_file = "/cfg/%s/config.json" % os.environ["SYSTEM_NAME"] + cfg_file = "%s/src/cfg/%s/config.json" % ( + os.environ["REPO_DIR"], + os.environ["SYSTEM_NAME"], + ) with open(cfg_file, "r") as stream: config = json.load(stream) diff --git a/src/run_scripts/entry/cam_ir.sh b/src/run_scripts/entry/cam_ir.sh index ed9eab26..12432271 100755 --- a/src/run_scripts/entry/cam_ir.sh +++ b/src/run_scripts/entry/cam_ir.sh @@ -5,10 +5,7 @@ echo "~ ~ ~ ~ ~ IR ~ ~ ~ ~ ~ " source /entry/project_env.sh -KAM_REPO_DIR=$(~/.config/kamera/repo_dir.bash) -source ${KAM_REPO_DIR}/src/cfg/cfg-aliases.sh # get cq - ConfigQuery - -for VNAME in CFG_ALIAS_SET CAM_FOV CAM_MODE +for VNAME in SYSTEM_NAME CAM_FOV CAM_MODE do if [[ -z "${!VNAME}" ]] then @@ -20,33 +17,31 @@ do done NODE_HOSTNAME=${NODE_HOSTNAME:-undefined} -DEV_ID=$(cq ".locations.${CAM_FOV}.${CAM_MODE}") +DEV_ID=$(kamera-cfg ".locations.${CAM_FOV}.${CAM_MODE}") if [[ ${DEV_ID} == 'null' ]]; then printf " Not a valid camera FOV/ mode: ${CAM_FOV}:${CAM_MODE}. oneof: {ir}" exit 1 fi -GUID=$(/cfg/get ".devices.${DEV_ID}.mac") +GUID=$(kamera-cfg ".devices.${DEV_ID}.mac") if [[ ${GUID} == 'null' ]]; then printf " Unable to find camera GUID: ${CAM_FOV}:${CAM_MODE}" exit 1 fi -CAM_IP=$(cq ".devices.${DEV_ID}.prefer_ip") +CAM_IP=$(kamera-cfg ".devices.${DEV_ID}.prefer_ip") if [[ ${CAM_IP} == 'null' ]]; then printf " Unable to find camera prefer_ip: ${CAM_FOV}:${CAM_MODE}" exit 1 fi - - ROSWAIT="--wait" CAM_PIXEL_FORMAT=${CAM_PIXEL_FORMAT:-mono16} CAM_TRIGGER_SOURCE=${CAM_TRIGGER_SOURCE:-External} CAM_TIMEOUT=${CAM_TIMEOUT:-3333} -DRIVER=$(cq ".devices.${DEV_ID}.model").launch +DRIVER=$(kamera-cfg ".devices.${DEV_ID}.model").launch # extra arguments to pass to roslaunch in the form of `argname1:=val argname2:=val` CAM_EXTRA_ARGS=${CAM_EXTRA_ARGS:-} LOGFILE="/tmp/roslaunch_err_${CAM_FOV}_${CAM_MODE}.log" @@ -78,7 +73,7 @@ exec roslaunch "${ROSWAIT}" kw_genicam_driver ${DRIVER} \ camera_manufacturer:=FLIR \ firmware_mode:=${CAM_PIXEL_FORMAT} \ nextImage_timeout:=${CAM_TIMEOUT} \ - info_verbosity:=$(/cfg/get ".verbosity") \ + info_verbosity:=$(kamera-cfg ".verbosity") \ ${CAM_EXTRA_ARGS} 2> >(tee -a "${LOGFILE}" >&2) & STAT_ROS=$! diff --git a/src/run_scripts/entry/cam_phaseone.sh b/src/run_scripts/entry/cam_phaseone.sh index 01323e6e..15600084 100755 --- a/src/run_scripts/entry/cam_phaseone.sh +++ b/src/run_scripts/entry/cam_phaseone.sh @@ -13,12 +13,7 @@ NODE_HOSTNAME=${NODE_HOSTNAME:-$(hostname)} source /entry/project_env.sh KAM_REPO_DIR=$(~/.config/kamera/repo_dir.bash) -source ${KAM_REPO_DIR}/src/cfg/cfg-aliases.sh # get cq - ConfigQuery -if [[ -z "CFG_ALIAS_SET" ]]; then - echo " Configuration failed" - exit 1 -fi if [[ $(redis-cli --raw -h $REDIS_HOST get /debug/enable ) == "true" ]]; then export KAMERA_DEBUG=true @@ -29,9 +24,9 @@ if [[ $(redis-cli --raw -h $REDIS_HOST get /debug/enable ) == "true" ]]; then fi fi -CAM_FOV=${CAM_FOV:-$(cq ".arch.hosts[\"${NODE_HOSTNAME}\"].fov")} +CAM_FOV=${CAM_FOV:-$(kamera-cfg ".arch.hosts[\"${NODE_HOSTNAME}\"].fov")} -for VNAME in CFG_ALIAS_SET CAM_FOV CAM_MODE +for VNAME in SYSTEM_NAME CAM_FOV CAM_MODE do if [[ -z "${!VNAME}" ]]; then echo "ERROR: Expected $VNAME environment variable that is missing." @@ -46,17 +41,17 @@ done echo "% % % % CAM-${CAM_MODE}-${CAM_FOV} % % % %" -DEV_ID=$(cq ".locations.${CAM_FOV}.${CAM_MODE}") +DEV_ID=$(kamera-cfg ".locations.${CAM_FOV}.${CAM_MODE}") if [[ ${DEV_ID} == 'null' ]]; then printf " Not a valid camera FOV/ mode: ${CAM_FOV}:${CAM_MODE}. oneof: {ir}" exit 1 fi -CAM_IFACE=$(cq ".interfaces.${CAM_MODE}") +CAM_IFACE=$(kamera-cfg ".interfaces.${CAM_MODE}") if [[ ${CAM_IFACE} == 'null' ]]; then printf " Not a valid camera FOV/ mode: ${CAM_FOV}/${CAM_MODE}. - CAM_FOV: oneof: `cq '.locations | keys' | tr '\n' ' '` - CAM_MODE: oneof: `cq '.channels ' | tr '\n' ' '`\n" + CAM_FOV: oneof: `kamera-cfg '.locations | keys' | tr '\n' ' '` + CAM_MODE: oneof: `kamera-cfg '.channels ' | tr '\n' ' '`\n" exit 1 fi @@ -67,7 +62,7 @@ if [[ ${CAM_IFACE} == 'null' ]]; then fi #CAM_IP=$(locate-attached.sh "$CAM_IFACE") -CAM_IP=$(cq ".devices.${DEV_ID}.prefer_ip") +CAM_IP=$(kamera-cfg ".devices.${DEV_ID}.prefer_ip") if [[ $? -ne 0 || ${CAM_IP} == 'null' ]]; then printf " Unable to find camera IP: ${CAM_FOV}:${CAM_MODE} on interface ${CAM_IFACE}" diff --git a/src/run_scripts/entry/cam_prosilica.sh b/src/run_scripts/entry/cam_prosilica.sh index 5d195740..e3051005 100755 --- a/src/run_scripts/entry/cam_prosilica.sh +++ b/src/run_scripts/entry/cam_prosilica.sh @@ -13,22 +13,17 @@ NODE_HOSTNAME=${NODE_HOSTNAME:-$(hostname)} source /entry/project_env.sh KAM_REPO_DIR=$(~/.config/kamera/repo_dir.bash) -source ${KAM_REPO_DIR}/src/cfg/cfg-aliases.sh # get cq - ConfigQuery -if [[ -z "CFG_ALIAS_SET" ]]; then - echo " Configuration failed" - exit 1 -fi if [[ $(redis-cli --raw -h $REDIS_HOST get /debug/enable ) == "true" ]]; then export KAMERA_DEBUG=true fi -CAM_FOV=${CAM_FOV:-$(cq ".arch.hosts[\"${NODE_HOSTNAME}\"].fov")} +CAM_FOV=${CAM_FOV:-$(kamera-cfg ".arch.hosts[\"${NODE_HOSTNAME}\"].fov")} -for VNAME in CFG_ALIAS_SET CAM_FOV CAM_MODE +for VNAME in SYSTEM_NAME CAM_FOV CAM_MODE do if [[ -z "${!VNAME}" ]]; then echo "ERROR: Expected $VNAME environment variable that is missing." @@ -43,17 +38,17 @@ done echo "% % % % CAM-${CAM_MODE}-${CAM_FOV} % % % %" -DEV_ID=$(cq ".locations.${CAM_FOV}.${CAM_MODE}") +DEV_ID=$(kamera-cfg ".locations.${CAM_FOV}.${CAM_MODE}") if [[ ${DEV_ID} == 'null' ]]; then printf " Not a valid camera FOV/ mode: ${CAM_FOV}:${CAM_MODE}. oneof: {ir}" exit 1 fi -CAM_IFACE=$(cq ".interfaces.${CAM_MODE}") +CAM_IFACE=$(kamera-cfg ".interfaces.${CAM_MODE}") if [[ ${CAM_IFACE} == 'null' ]]; then printf " Not a valid camera FOV/ mode: ${CAM_FOV}/${CAM_MODE}. - CAM_FOV: oneof: `cq '.locations | keys' | tr '\n' ' '` - CAM_MODE: oneof: `cq '.channels ' | tr '\n' ' '`\n" + CAM_FOV: oneof: `kamera-cfg '.locations | keys' | tr '\n' ' '` + CAM_MODE: oneof: `kamera-cfg '.channels ' | tr '\n' ' '`\n" exit 1 fi @@ -64,7 +59,7 @@ if [[ ${CAM_IFACE} == 'null' ]]; then fi #CAM_IP=$(locate-attached.sh "$CAM_IFACE") -CAM_IP=$(cq ".devices.${DEV_ID}.prefer_ip") +CAM_IP=$(kamera-cfg ".devices.${DEV_ID}.prefer_ip") if [[ $? -ne 0 || ${CAM_IP} == 'null' ]]; then printf " Unable to find camera IP: ${CAM_FOV}:${CAM_MODE} on interface ${CAM_IFACE}" @@ -108,8 +103,8 @@ exec roslaunch "${ROSWAIT}" prosilica_camera prosilica.launch \ cam_fov:=${CAM_FOV} \ trigger_mode:=${TRIGGER_MODE} \ norespawn:=${NORESPAWN} \ - GainMode:=$(cq ".launch.cam.${CAM_MODE}.GainMode") \ - GainValue:=$(cq ".launch.cam.${CAM_MODE}.GainValue") 2> >(tee -a "${LOGFILE}" >&2) & + GainMode:=$(kamera-cfg ".launch.cam.${CAM_MODE}.GainMode") \ + GainValue:=$(kamera-cfg ".launch.cam.${CAM_MODE}.GainValue") 2> >(tee -a "${LOGFILE}" >&2) & STAT_ROS=$! wait $STAT_ROS diff --git a/src/run_scripts/entry/gui.sh b/src/run_scripts/entry/gui.sh index 6a40ee9b..470cb3c0 100755 --- a/src/run_scripts/entry/gui.sh +++ b/src/run_scripts/entry/gui.sh @@ -4,15 +4,10 @@ echo "GUI GUI GUI GUI GUI " - -KAM_REPO_DIR=$(~/.config/kamera/repo_dir.bash) -source ${KAM_REPO_DIR}/src/cfg/cfg-aliases.sh # get cq - ConfigQuery - - source /entry/project.sh source /aliases.sh -for VNAME in CFG_ALIAS_SET ROS_MASTER_URI DATA_MOUNT_POINT +for VNAME in SYSTEM_NAME ROS_MASTER_URI DATA_MOUNT_POINT do if [[ -z "${!VNAME}" ]] then @@ -23,7 +18,6 @@ do fi done - NODE_HOSTNAME=${NODE_HOSTNAME:-undefined} #pip install --user "src/core/roskv/[redis]" #catkin build custom_msgs roskv diff --git a/src/run_scripts/entry/master.sh b/src/run_scripts/entry/master.sh index 29d8597e..e806f68d 100755 --- a/src/run_scripts/entry/master.sh +++ b/src/run_scripts/entry/master.sh @@ -4,7 +4,7 @@ echo "[ ] [ ] [ ] KAMCORE [ ] [ ] [ ] " # dump the global config as a debugging step -cat /cfg/${SYSTEM_NAME}/config.json +cat ${REPO_DIR}/src/cfg/${SYSTEM_NAME}/config.json source /entry/project_env.sh @@ -27,7 +27,7 @@ redis-client -h ${REDIS_HOST} incr term # Seed Redis with the static system config before anything starts, so kamcore # nodes (cam_param_monitor, etc.) read /sys/arch from Redis without depending on # the GUI. Done before roscore so the --wait monitors can't start until it's up. -rosrun kamcore seed_redis_config.py /cfg/${SYSTEM_NAME}/config.json +rosrun kamcore seed_redis_config.py ${REPO_DIR}/src/cfg/${SYSTEM_NAME}/config.json # Start core and block until it's up, then bootstrap parameters roscore & @@ -44,6 +44,6 @@ until /entry/rosnode_list.sh; do fi done -rosparam load /cfg/${SYSTEM_NAME}/config.json /cfg +rosparam load ${REPO_DIR}/src/cfg/${SYSTEM_NAME}/config.json /cfg exec roslaunch kamcore kamcore.launch data_mount_point:=$DATA_MOUNT_POINT \ spoof_rate:="${SPOOF_RATE}" diff --git a/src/run_scripts/entry/postproc.sh b/src/run_scripts/entry/postproc.sh index 0fcd987d..a1ad521e 100755 --- a/src/run_scripts/entry/postproc.sh +++ b/src/run_scripts/entry/postproc.sh @@ -7,13 +7,12 @@ source /entry/project_env.sh ## === === === === User-set configuration === === === === KAM_REPO_DIR=$(~/.config/kamera/repo_dir.bash) -source ${KAM_REPO_DIR}/src/cfg/cfg-aliases.sh # get cq - ConfigQuery ## tell the system hostname of the node acting as ROS master host -export MASTER_HOST=$(cq '.master_host') +export MASTER_HOST=$(kamera-cfg '.master_host') NODE_HOSTNAME=${NODE_HOSTNAME:-$(hostname)} -CAM_FOV=$(cq ".arch.hosts[\"${NODE_HOSTNAME}\"].fov") +CAM_FOV=$(kamera-cfg ".arch.hosts[\"${NODE_HOSTNAME}\"].fov") export NODE_HOSTNAME export CAM_FOV @@ -28,7 +27,7 @@ WS_KAMERA=/root/kamera_ws -for VNAME in CFG_ALIAS_SET DATA_MOUNT_POINT +for VNAME in SYSTEM_NAME DATA_MOUNT_POINT do if [[ -z "${!VNAME}" ]] then diff --git a/src/run_scripts/entry/viame.sh b/src/run_scripts/entry/viame.sh index 86272cef..3fcbf464 100755 --- a/src/run_scripts/entry/viame.sh +++ b/src/run_scripts/entry/viame.sh @@ -3,11 +3,10 @@ ## === === === === User-set configuration === === === === source /entry/project_env.sh -source ${KAM_REPO_DIR}/src/cfg/cfg-aliases.sh # get cq - ConfigQuery ## tell the system hostname of the node acting as ROS master host -export MASTER_HOST=$(cq '.master_host') -export REDIS_HOST=$(cq '.redis_host') +export MASTER_HOST=$(kamera-cfg '.master_host') +export REDIS_HOST=$(kamera-cfg '.redis_host') NODE_HOSTNAME=${NODE_HOSTNAME:-$(hostname)} CAM_FOV="$(redis-cli -h ${REDIS_HOST} -p 6379 get "/sys/arch/hosts/${NODE_HOSTNAME}/fov")" @@ -47,7 +46,7 @@ fi source "${KAM_REPO_DIR}/src/run_scripts/setup/setup_viame_runtime.sh" -for VNAME in CFG_ALIAS_SET CAM_FOV MASTER_HOST WS_DEVEL VIAME_INSTALL +for VNAME in SYSTEM_NAME CAM_FOV MASTER_HOST WS_DEVEL VIAME_INSTALL do if [[ -z "${!VNAME}" ]] then diff --git a/src/run_scripts/inpath/kamera-cfg b/src/run_scripts/inpath/kamera-cfg new file mode 100755 index 00000000..71d02531 --- /dev/null +++ b/src/run_scripts/inpath/kamera-cfg @@ -0,0 +1,8 @@ +#!/usr/bin/env bash + +# Query this system's config.json with jq, e.g. `kamera-cfg .master_host`. +# The config is found relative to this script, so it works both on a host and +# in a container. + +CFG_DIR="$(dirname "$(readlink -f "${BASH_SOURCE[0]}")")/../../cfg" +exec jq -r "$1" "${CFG_DIR}/${SYSTEM_NAME}/config.json" From 36c182bfa1c08af97b52b1d0f7e63f3edb9f2cdb Mon Sep 17 00:00:00 2001 From: Adam Romlein Date: Tue, 29 Sep 2026 10:49:26 -0400 Subject: [PATCH 6/6] Remove dead inpath symlinks and the GUI halt command that used one The kamera.* links, mount_nas, assert_nas and diskfull pointed into src/run_scripts/newstartup and startup, which no longer exist. SystemCommands' halt target was never sent by the GUI and ran the dead kamera.halt link through an unimported subprocess. scripts/kamera.desktop only launched the dead kamera.run and nothing installs it. --- scripts/kamera.desktop | 6 ------ .../src/wxpython_gui/SystemCommands.py | 15 --------------- src/run_scripts/inpath/assert_nas | 1 - src/run_scripts/inpath/diskfull | 1 - src/run_scripts/inpath/kamera.cams | 1 - src/run_scripts/inpath/kamera.central | 1 - src/run_scripts/inpath/kamera.detector | 1 - src/run_scripts/inpath/kamera.fixip | 1 - src/run_scripts/inpath/kamera.gui | 1 - src/run_scripts/inpath/kamera.halt | 1 - src/run_scripts/inpath/kamera.master | 1 - src/run_scripts/inpath/kamera.nexus | 1 - src/run_scripts/inpath/kamera.pod | 1 - src/run_scripts/inpath/kamera.run | 1 - src/run_scripts/inpath/mount_nas | 1 - 15 files changed, 34 deletions(-) delete mode 100755 scripts/kamera.desktop delete mode 120000 src/run_scripts/inpath/assert_nas delete mode 120000 src/run_scripts/inpath/diskfull delete mode 120000 src/run_scripts/inpath/kamera.cams delete mode 120000 src/run_scripts/inpath/kamera.central delete mode 120000 src/run_scripts/inpath/kamera.detector delete mode 120000 src/run_scripts/inpath/kamera.fixip delete mode 120000 src/run_scripts/inpath/kamera.gui delete mode 120000 src/run_scripts/inpath/kamera.halt delete mode 120000 src/run_scripts/inpath/kamera.master delete mode 120000 src/run_scripts/inpath/kamera.nexus delete mode 120000 src/run_scripts/inpath/kamera.pod delete mode 120000 src/run_scripts/inpath/kamera.run delete mode 120000 src/run_scripts/inpath/mount_nas diff --git a/scripts/kamera.desktop b/scripts/kamera.desktop deleted file mode 100755 index f94be92c..00000000 --- a/scripts/kamera.desktop +++ /dev/null @@ -1,6 +0,0 @@ -[Desktop Entry] -Exec=bash -c 'kamera.run' -Name=kamera -Terminal=true -Type=Application -Name[en_US]=kamera.desktop diff --git a/src/kitware-ros-pkg/wxpython_gui/src/wxpython_gui/SystemCommands.py b/src/kitware-ros-pkg/wxpython_gui/src/wxpython_gui/SystemCommands.py index d2c1541a..303cd09f 100644 --- a/src/kitware-ros-pkg/wxpython_gui/src/wxpython_gui/SystemCommands.py +++ b/src/kitware-ros-pkg/wxpython_gui/src/wxpython_gui/SystemCommands.py @@ -1,4 +1,3 @@ -from wxpython_gui.cfg import kv, DOCK_KAM_REPO_DIR, REAL_KAM_REPO_DIR from roskv.util import filter_hosts_by_system import time import xmlrpc.client as xmlrpclib @@ -20,7 +19,6 @@ def __init__(self, hosts): self.commands = ["up", "down", "restart"] self.cams = ["ir", "rgb", "uv"] self.devices = ["ins", "daq"] - self.halt = "%s/src/run_scripts/inpath/kamera.halt" % REAL_KAM_REPO_DIR self.processes = "" self.cmd = "" @@ -102,22 +100,12 @@ def command_central(self, host, cmd, devices): devices = [devices] self.processes = devices - def command_halt(self): - # WARNING will kill the GUI (itself) - self.bash = [self.halt] - self.run_bash() - def command_postproc(self, host, command, postproc): print("Final command: (%s %s)" % (command, postproc)) self.host = host self.cmd = command self.processes = ["postproc:%s" % postproc] - def run_bash(self): - bash_cmd = " ".join(self.bash) - if len(self.bash) > 0: - return_code = subprocess.Popen(bash_cmd, shell=True) - class SystemCommands(object): def __init__(self, hosts): @@ -142,9 +130,6 @@ def run_command( elif target == "central": self.scc.command_central(host, command, containers) self.scc.run() - elif target == "halt": - self.scc.command_halt() - self.scc.run() elif target == "postproc": self.scc.command_postproc(host, command, postproc) self.scc.run() diff --git a/src/run_scripts/inpath/assert_nas b/src/run_scripts/inpath/assert_nas deleted file mode 120000 index 853b63b6..00000000 --- a/src/run_scripts/inpath/assert_nas +++ /dev/null @@ -1 +0,0 @@ -../newstartup/assert_nas.sh \ No newline at end of file diff --git a/src/run_scripts/inpath/diskfull b/src/run_scripts/inpath/diskfull deleted file mode 120000 index 7de08868..00000000 --- a/src/run_scripts/inpath/diskfull +++ /dev/null @@ -1 +0,0 @@ -../startup/diskfull.sh \ No newline at end of file diff --git a/src/run_scripts/inpath/kamera.cams b/src/run_scripts/inpath/kamera.cams deleted file mode 120000 index 84f8e692..00000000 --- a/src/run_scripts/inpath/kamera.cams +++ /dev/null @@ -1 +0,0 @@ -../newstartup/launchcams.sh \ No newline at end of file diff --git a/src/run_scripts/inpath/kamera.central b/src/run_scripts/inpath/kamera.central deleted file mode 120000 index 61e8aa80..00000000 --- a/src/run_scripts/inpath/kamera.central +++ /dev/null @@ -1 +0,0 @@ -../newstartup/launchcentral.sh \ No newline at end of file diff --git a/src/run_scripts/inpath/kamera.detector b/src/run_scripts/inpath/kamera.detector deleted file mode 120000 index 5ce8072d..00000000 --- a/src/run_scripts/inpath/kamera.detector +++ /dev/null @@ -1 +0,0 @@ -../newstartup/launchdetector.sh \ No newline at end of file diff --git a/src/run_scripts/inpath/kamera.fixip b/src/run_scripts/inpath/kamera.fixip deleted file mode 120000 index ebb51ec3..00000000 --- a/src/run_scripts/inpath/kamera.fixip +++ /dev/null @@ -1 +0,0 @@ -../newstartup/fixcamip.sh \ No newline at end of file diff --git a/src/run_scripts/inpath/kamera.gui b/src/run_scripts/inpath/kamera.gui deleted file mode 120000 index 61838676..00000000 --- a/src/run_scripts/inpath/kamera.gui +++ /dev/null @@ -1 +0,0 @@ -../newstartup/launchgui.sh \ No newline at end of file diff --git a/src/run_scripts/inpath/kamera.halt b/src/run_scripts/inpath/kamera.halt deleted file mode 120000 index 1baea443..00000000 --- a/src/run_scripts/inpath/kamera.halt +++ /dev/null @@ -1 +0,0 @@ -../newstartup/kamera_halt.sh \ No newline at end of file diff --git a/src/run_scripts/inpath/kamera.master b/src/run_scripts/inpath/kamera.master deleted file mode 120000 index 6556f90b..00000000 --- a/src/run_scripts/inpath/kamera.master +++ /dev/null @@ -1 +0,0 @@ -../newstartup/launchmaster.sh \ No newline at end of file diff --git a/src/run_scripts/inpath/kamera.nexus b/src/run_scripts/inpath/kamera.nexus deleted file mode 120000 index fd5d41c2..00000000 --- a/src/run_scripts/inpath/kamera.nexus +++ /dev/null @@ -1 +0,0 @@ -../newstartup/launchnexus.sh \ No newline at end of file diff --git a/src/run_scripts/inpath/kamera.pod b/src/run_scripts/inpath/kamera.pod deleted file mode 120000 index 3f03f63d..00000000 --- a/src/run_scripts/inpath/kamera.pod +++ /dev/null @@ -1 +0,0 @@ -../newstartup/launchpod.sh \ No newline at end of file diff --git a/src/run_scripts/inpath/kamera.run b/src/run_scripts/inpath/kamera.run deleted file mode 120000 index 343087a8..00000000 --- a/src/run_scripts/inpath/kamera.run +++ /dev/null @@ -1 +0,0 @@ -../newstartup/kamera_run.sh \ No newline at end of file diff --git a/src/run_scripts/inpath/mount_nas b/src/run_scripts/inpath/mount_nas deleted file mode 120000 index b82d813a..00000000 --- a/src/run_scripts/inpath/mount_nas +++ /dev/null @@ -1 +0,0 @@ -../startup/mount_nas.sh \ No newline at end of file