Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
3 changes: 3 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
.venv
**/__pycache__
**/*.pyc
30 changes: 30 additions & 0 deletions .github/workflows/gui-build.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
name: GUI build

on:
push:
paths:
- ".github/workflows/gui-build.yml"
- "docker/base/gui-deps.dockerfile"
- "docker/gui.dockerfile"
- "docker-compose.yml"
- "Makefile"
pull_request:
paths:
- ".github/workflows/gui-build.yml"
- "docker/base/gui-deps.dockerfile"
- "docker/gui.dockerfile"
- "docker-compose.yml"
- "Makefile"

# NOTE: This is config validation only, not an image build. A real `make gui`
# build requires the published Noetic core-deps image as a base and a display
# for the wx smoke test. Upgrade this to an actual layer build (e.g. build
# gui-deps against a published core-deps) when CI infrastructure allows.
jobs:
validate-compose:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- name: Validate gui compose config
run: docker compose --profile gui config
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
**__pycache__
**.swp
**.pyc
**.DS_Store
artifacts
build
devel
provision/ansible/.password
.catkin_tools
.venv
106 changes: 106 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
# Changelog

All notable changes to KAMERA are documented in this file.

The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [Unreleased]

## [0.5.0] - 2026-07-21

### Added

- Dropdown selectors for Phase One shutter speed, gain, and aperture, with proper
electronic/leaf shutter mapping.
- The 'Set' button lights up whenever a camera parameter changes, making pending
changes obvious.
- Optional GPU JPEG compression via nvJPEG, enabled with the `/sys/arch/use_nvjpeg` flag.
- Power management (system startup/shutdown/reboot) as a simple stateful REST API,
managed by kamerad and supervisor.
- kamerad runs on system startup and auto-restarts.
- Default camera configuration JSONs ship with the repo; defaults load based on the
system name.
- Additional color status indicators in the GUI, and a warning when no detector
pipefile is configured.
- Ansible tasks for system stop/start and docker restarts.
- Local docker registry on leader machines for distributing images to the rest of
the system; leader machines also build the core and VIAME images.
- Tailscale installed with the system for remote access.
- Desktop shortcuts installed during provisioning, including a convenience symlink
to the NAS.
- Script to seed the redis configuration during provisioning.
- nayak system support: tailored configuration (no IR/UV cameras) and a local
stratum-3 NTP server so systems stay synchronized offline.

### Changed

- GUI ported to ROS Noetic: all images now build on Ubuntu 20.04 with Python 3 and
wxPython 4.
- Save is now a single button: it finalizes changes, writes camera configurations to
disk, and refreshes the main panel dropdown.
- Shutter speed is displayed directly instead of exposure in milliseconds.
- Flight number entry is more forgiving and no longer errors on every change.
- Contrast control is greyed out when the server manages it; disabled controls now
show their values in a clearer disabled style.
- GUI layout overhauled: INS data in two columns, wider camera dropdowns, working
About dialog, and many scaling fixes to eliminate clipped text and squished panels.
- Icons refreshed and properly labeled.
- `kamera_run` now just launches the GUI when the system is already up, so a
separate GUI desktop icon is no longer needed.
- Hostnames follow a new center/left/right convention (hyphen-free for ROS
compatibility), and start/stop scripts use it uniformly.
- Startup calls tmux directly, and environment/image-tag configuration is
consolidated into supervisord globals and a `.env` file.
- Clear configuration boundaries: yaml files hold static, system-specific options;
`system_state.json` holds mutable, GUI-facing state.
- Configuration conflict resolution reports what changed instead of failing silently.
- redis configuration consolidated.
- Docker build chain cleaned up: concrete makefile steps and explicit compose builds
that respect `depends_on` order.
- NFS version pinned and NAS mount points created ahead of mounting, for more
reliable NAS access.
- GUI relicensed under Apache 2.0; old license headers removed.

### Fixed

- INS panel incorrectly showing yellow (string vs. int comparison).
- ~10-frame lag in the image counter display; the frame buffer is also flushed when
archiving stops, so counts stay accurate.
- GUI no longer hangs during SSD / NAS health checks (moved to a background thread).
- Race condition where the detector gauge started red.
- Intermittent X Windows errors when launching the GUI (containers now use
`ipc: host`).
- Phase One debayering failures: added error handling around queue writes and
removed a hardcoded output path.
- The image-processing queue is recreated on each run, guaranteeing every file gets
processed.
- Detector pipefile loading is more robust.

### Removed

- Legacy ROS Kinetic / Python 2 code paths and shims.
- tmuxinator dependency.

## [0.4.0] - 2025-07-28

_Released before this changelog was introduced; see the git history for details._

## [0.3.0] - 2025-03-25

_Released before this changelog was introduced; see the git history for details._

## [0.2.0] - 2025-01-12

_Released before this changelog was introduced; see the git history for details._

## [0.1.0] - 2024-11-23

_Released before this changelog was introduced; see the git history for details._

[Unreleased]: https://github.com/Kitware/kamera/compare/v0.5.0...develop
[0.5.0]: https://github.com/Kitware/kamera/compare/v0.4.0...v0.5.0
[0.4.0]: https://github.com/Kitware/kamera/compare/v0.3.0...v0.4.0
[0.3.0]: https://github.com/Kitware/kamera/compare/v0.2.0...v0.3.0
[0.2.0]: https://github.com/Kitware/kamera/compare/v0.1.0...v0.2.0
[0.1.0]: https://github.com/Kitware/kamera/releases/tag/v0.1.0
78 changes: 47 additions & 31 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,45 +1,61 @@
CMD ?= bash
runtime ?= runc
network ?= host
name ?= kamera
DAQDEV ?= mcc_daq
REPO_DIR ?= $(shell realpath ${PWD})
REPO_DIR_BASEDIR ?= $(shell dirname $(REPO_DIR))
ROS_MASTER_URI ?= not_set_your_config_is_bad
## Docker buildkit - disable by setting to 0 if you have issues

DAQPATH = $(shell readlink -f "/dev/$(DAQDEV)")
PROJ_DIR=/root/kamera
WS_DIR=/root/kamera
ROS_DISTRO=noetic
BRANCH=latest

.PHONY: info
info:
@echo REPO_DIR_BASEDIR=$(REPO_DIR_BASEDIR)
@echo ROS_MASTER_URI=$(ROS_MASTER_URI)
@echo REDIS_HOST=$(REDIS_HOST)

.PHONY: build
ROS_DISTRO ?= noetic
PYTHON_VERSION ?= 3.10

.PHONY: install build core viame gui postflight follower leader all clean

# Build .venv on top of an activated conda env from environment.yml
install:
@echo "🚀 Creating virtual environment using uv"
@uv venv --system-site-packages --python=$(PYTHON_VERSION)
@uv sync --frozen --no-cache

build:
docker compose build

.PHONY: nuvo
nuvo:
docker compose --profile nuvo build
## --- individual layer targets ---

core:
docker compose --profile core build core-ros
docker compose --profile core build core-deps
docker compose --profile core build

.PHONY: viame
viame:
docker compose --profile viame build viame-base
docker compose --profile viame build

.PHONY: gui
gui:
ROS_DISTRO=kinetic docker compose --profile gui build
docker compose --profile gui build core-ros
docker compose --profile gui build core-deps
docker compose --profile gui build gui-deps
docker compose --profile gui build gui

.PHONY: postflight
postflight:
docker compose --profile pf build

.PHONY: clean
## --- deployment-target targets ---

# Follower node: headless sensor node — core + VIAME + postproc
follower:
docker compose --profile follower build core-ros
docker compose --profile follower build core-deps
docker compose --profile follower build viame-base
docker compose --profile follower build

# Leader node: operator workstation — GUI + VIAME + postproc
leader:
docker compose --profile leader build core-ros
docker compose --profile leader build core-deps
docker compose --profile leader build viame-base
docker compose --profile leader build gui-deps
docker compose --profile leader build

# Everything
all:
docker compose --profile all build core-ros
docker compose --profile all build core-deps
docker compose --profile all build viame-base
docker compose --profile all build gui-deps
docker compose --profile all build

clean:
rm -rf .ros .catkin_tools .cmake .config build* devel* logs*
2 changes: 1 addition & 1 deletion NOTICE
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
Copyright 2024 Kitware, Inc.
KAMERA
=============================================================

Licensed under the Apache License, Version 2.0 (the "License");
Expand Down
34 changes: 32 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,41 @@ KAMERA, or the **K**nowledge-guided Image **A**cquisition **M**anag**ER** and **

## Installation

### Post-processing (native, Windows or Linux)

GDAL and pycolmap come from conda-forge; [uv](https://docs.astral.sh/uv/)
installs the rest into `.venv`. Requires
[conda](https://conda-forge.org/download/).

Linux/macOS:

```bash
git clone https://github.com/Kitware/kamera.git
cd kamera
# For the pure post-processing and generating flight summary, you can install
# the requirements in requirements.txt, or use the provided dockerfile
conda env create -f environment.yml
conda activate kamera
make install
source .venv/bin/activate
```

Windows (PowerShell or Anaconda Prompt):

```powershell
git clone https://github.com/Kitware/kamera.git
cd kamera
conda env create -f environment.yml
conda activate kamera
pip install -e .
```

Afterwards, `conda activate kamera` is all you need. Conda installs the CUDA
build of pycolmap automatically with NVIDIA driver 575+ (CUDA 12.9),
otherwise the CPU build; GPU only matters for full camera model calibration.

### Docker images

```bash
# post-processing / flight summary image
make postflight
# Builds the core docker images for use in the onboard sytems
make nuvo
Expand Down
5 changes: 5 additions & 0 deletions compose/.env
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
KAMERA_CORE_IMAGE=kitware/kamera:core
KAMERA_KAMERAD_IMAGE=kitware/kamera:kamerad
KAMERA_VIAME_IMAGE=kitware/kamera:viame
KAMERA_POSTPROC_IMAGE=kitware/kamera:postproc
KAMERA_GUI_IMAGE=kitware/kamera:gui
6 changes: 3 additions & 3 deletions compose/cam_ir.yml
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
---
## Auxiliary node to attach to master
version: '3.7'
services:
cam_ir:
container_name: "cam-ir-${CAM_FOV}"
image: kitware/kamera:core
image: ${KAMERA_CORE_IMAGE}
init: true
tty: true
environment:
ROS_MASTER_URI: "${ROS_MASTER_URI}"
Expand All @@ -23,5 +23,5 @@ services:
- "/mnt:/mnt"
- "${PWD}/src:${DOCKER_KAMERA_DIR}/src:ro"
command: ["/entry/cam_ir.sh"]
restart: unless-stopped
restart: no
...
6 changes: 3 additions & 3 deletions compose/cam_param_monitor.yml
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
---
## Core processes
version: '3.7'
services:
cam_param_monitor:
container_name: cam_param_monitor
image: kitware/kamera:core
image: ${KAMERA_CORE_IMAGE}
init: true
tty: true
environment:
ROS_MASTER_URI: "${ROS_MASTER_URI}"
Expand All @@ -20,5 +20,5 @@ services:
- "/mnt:/mnt"
- "${PWD}/src:${DOCKER_KAMERA_DIR}/src:ro"
command: ["/entry/cam_param_monitor.sh"]
restart: unless-stopped
restart: no
...
6 changes: 3 additions & 3 deletions compose/cam_rgb.yml
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
---
## Auxiliary node to attach to master
version: '3.7'
services:
## =========================== headless nodes =============================
cam_rgb:
container_name: "cam-rgb-${CAM_FOV}"
image: kitware/kamera:core
image: ${KAMERA_CORE_IMAGE}
init: true
tty: true
environment:
ROS_MASTER_URI: "${ROS_MASTER_URI}"
Expand All @@ -25,7 +25,7 @@ services:
- "${PWD}/src:${DOCKER_KAMERA_DIR}/src:ro"
command: ["/entry/cam_phaseone.sh"]
#command: ["bash"]
restart: unless-stopped
restart: no
deploy:
resources:
reservations:
Expand Down
6 changes: 3 additions & 3 deletions compose/cam_uv.yml
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
---
## Auxiliary node to attach to master
version: '3.7'
services:
## =========================== headless nodes =============================
cam_uv:
container_name: "cam-uv-${CAM_FOV}"
image: kitware/kamera:core
image: ${KAMERA_CORE_IMAGE}
init: true
tty: true
environment:
ROS_MASTER_URI: "${ROS_MASTER_URI}"
Expand All @@ -25,5 +25,5 @@ services:
- "${PWD}/src:${DOCKER_KAMERA_DIR}/src:ro"
# command: ["bash"]
command: ["/entry/cam_prosilica.sh", "uv"]
restart: unless-stopped
restart: no
...
Loading
Loading