Skip to content
Merged
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
Jump to file
Failed to load files.
Loading
Diff view
Diff view
203 changes: 185 additions & 18 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -103,17 +103,115 @@ make coverage-html
make clean-coverage
```

### Web Control Panel Development

```bash
# Build and run axon_panel web interface
cd apps/axon_panel
npm install # Install dependencies (first time only)
npm run dev # Start development server (http://localhost:5173)
npm run build # Build for production (outputs to dist/)
npm run preview # Preview production build
```

## Application Architecture

Axon consists of four main components that work together:

| Component | Purpose | Technology | Location |
|-----------|---------|------------|----------|
| **axon_recorder** | Core recording engine with HTTP RPC API | C++17 | [apps/axon_recorder/](apps/axon_recorder/) |
| **axon_transfer** | S3 transfer daemon (standalone) | C++17 | [apps/axon_transfer/](apps/axon_transfer/) |
| **axon_panel** | Web-based control UI (frontend only) | Vue 3 + Vite | [apps/axon_panel/](apps/axon_panel/) |
| **axon_config** | Robot initialization and config collection | C++17 | [apps/axon_config/](apps/axon_config/) |

### Application Interaction

```
┌─────────────────────┐
│ axon_config │ Robot initialization (one-time setup)
│ (CLI Tool) │ → Collects robot type, SN, sensor config, URDF
└─────────────────────┘
│ Config files
┌─────────────────────┐ HTTP RPC ┌─────────────────────┐
│ axon_panel │◄──────────────────►│ axon_recorder │
│ (Vue 3 Web UI) │ State Control │ (C++ Backend) │
│ - Monitor state │ - config │ - HTTP RPC Server │
│ - Control buttons │ - begin │ - Plugin Loader │
│ - View stats │ - pause/resume │ - MCAP Writer │
│ - Activity log │ - finish/cancel │ - Worker Threads │
└─────────────────────┘ └──────────┬──────────┘
│ Upload requests
┌─────────────────────┐
│ axon_transfer │
│ (Transfer Daemon) │
│ - S3 multipart │
│ - Retry logic │
│ - State recovery │
└──────────┬──────────┘
┌─────────────────────┐
│ S3 Storage │
└─────────────────────┘
```

Comment on lines +140 to +162
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Outdated repo layout docs

CLAUDE.md still documents tools/axon_panel, but this PR moved the panel to apps/axon_panel (per PR summary and file tree). As written, the documented repo structure is now incorrect.

Update the tree snippet under “Axon/” to reflect the current location and remove the stale tools/axon_panel entry.

Prompt To Fix With AI
This is a comment left during a code review.
Path: CLAUDE.md
Line: 140:162

Comment:
**Outdated repo layout docs**

`CLAUDE.md` still documents `tools/axon_panel`, but this PR moved the panel to `apps/axon_panel` (per PR summary and file tree). As written, the documented repo structure is now incorrect.

Update the tree snippet under “Axon/” to reflect the current location and remove the stale `tools/axon_panel` entry.

How can I resolve this? If you propose a fix, please make it concise.

**Panel Control Flow:** `axon_panel` (Vue 3 frontend) sends HTTP RPC commands to `axon_recorder` to control state transitions:
- `POST /rpc/config` → IDLE → READY
- `POST /rpc/begin` → READY → RECORDING
- `POST /rpc/pause` → RECORDING → PAUSED
- `POST /rpc/resume` → PAUSED → RECORDING
- `POST /rpc/finish` → RECORDING/PAUSED → IDLE

**Note on Current Status:**
- `axon_recorder`: Fully implemented C++ application
- `axon_transfer`: Standalone daemon pending design; currently uses [core/axon_uploader/](core/axon_uploader/) library integrated into recorder
- `axon_panel`: Fully implemented Vue 3 SPA at [apps/axon_panel/](apps/axon_panel/)
- `axon_config`: Placeholder only; CLI interface and functionality pending design

### axon_panel - Web Control Panel

**Location:** [apps/axon_panel/](apps/axon_panel/)

**Purpose:** Browser-based interface for monitoring and controlling the recorder

**Features:**
- Real-time state monitoring and statistics
- Visual state machine diagram with Vue Flow
- Recording control (config/begin/pause/resume/finish/cancel)
- Activity logging with color-coded messages
- Responsive design (desktop + mobile)

**Development:**
```bash
cd apps/axon_panel
npm install
npm run dev # Development server (http://localhost:5173)
npm run build # Production build to dist/
```

**Key Files:**
- `apps/axon_panel/src/App.vue` - Root component with state management
- `apps/axon_panel/src/api/rpc.js` - RPC API client
- `apps/axon_panel/src/components/` - Vue components (StatePanel, ControlPanel, etc.)

**See:** [docs/designs/frontend-design.md](docs/designs/frontend-design.md) for complete architecture

## High-Level Architecture

The system follows a layered architecture with a 4-state task-centric FSM and a plugin-based middleware integration layer:

```
Server/Fleet Manager (ros-bridge) → Recording Services → State Machine → MCAP Writer
↓ ↓
HTTP Callbacks Worker Threads SPSC Queues
↓ ↓
CachedRecordingConfig Start/Finish Lock-free
(YAML Configuration) Notify Message Transfer
Server/Fleet Manager → Recording Services → State Machine → MCAP Writer
↓ ↓
HTTP RPC API HTTP Callbacks Worker Threads SPSC Queues
↓ ↓
Task Config Start/Finish Lock-free Message Transfer
(YAML) Notify Transfer
```

### Plugin-Based Middleware Architecture
Expand All @@ -132,23 +230,34 @@ Axon/
├── core/ # Middleware-agnostic core libraries
│ ├── axon_mcap/ # MCAP writer (no ROS dependencies)
│ ├── axon_logging/ # Logging infrastructure (no ROS dependencies)
│ └── axon_uploader/ # S3 uploader (no ROS dependencies)
│ └── axon_uploader/ # S3 uploader library (no ROS dependencies)
├── middlewares/ # Middleware-specific plugins and filters
│ ├── ros1/ # ROS1 (Noetic) plugin → libaxon_ros1.so
│ ├── ros2/ # ROS2 (Humble/Jazzy/Rolling) plugin → libaxon_ros2.so
│ │ └── src/ros2_plugin/ # ROS2 plugin implementation
│ ├── zenoh/ # Zenoh plugin → libaxon_zenoh.so
│ ├── mock/ # Mock plugin for testing (no ROS required)
│ │ └── src/mock_plugin/ # Mock plugin implementation
│ └── filters/ # Data processing filters (shared across plugins)
│ └── depthlitez/ # Depth image compression library
│ ├── include/ # Depth compressor header
│ ├── src/ # Depth compressor implementation
│ └── depthlitez/ # DepthLiteZ library (private submodule)
├── apps/ # Main applications
│ ├── axon_recorder/ # Plugin loader and HTTP RPC server
│ └── plugin_example/ # Example plugin implementation
│ ├── axon_panel/ # Vue 3 web control panel
│ ├── axon_config/ # Robot configuration CLI tool (placeholder)
│ └── axon_transfer/ # S3 transfer daemon (placeholder)
├── python/ # Python client library
│ └── axon_client/ # Async/sync HTTP client
└── docs/designs/ # Design documents
├── rpc-api-design.md # HTTP RPC API specification
└── depth-compression-filter.md # Depth compression design
├── frontend-design.md # AxonPanel web UI architecture
├── middleware-plugin-architecture-design.md # Plugin architecture
├── license-management-design.md # REUSE licensing
└── depth-compression-filter.md # Depth compression design
```

**Plugin ABI Interface:**
Expand All @@ -165,6 +274,13 @@ The plugin interface is defined in [apps/axon_recorder/plugin_loader.hpp](apps/a
5. Middleware-specific bugs are isolated to plugin code
6. Filters in `middlewares/filters/` can be shared across plugins

**Mock Plugin for Testing:**
The mock plugin ([middlewares/mock/src/mock_plugin/](middlewares/mock/src/mock_plugin/)) provides a reference implementation for E2E testing without ROS dependencies:
- Simulates message publishing and subscription
- Implements the full plugin C ABI interface
- Enables CI testing without requiring ROS installation
- Test scripts: [test_e2e_with_mock.sh](middlewares/mock/test_e2e_with_mock.sh), [test_full_workflow.sh](middlewares/mock/test_full_workflow.sh)

### State Machine

```
Expand Down Expand Up @@ -448,6 +564,34 @@ Keep descriptions under 72 characters. Use imperative mood ("add" not "added").

**Note**: With the new plugin architecture, most ROS-specific code is isolated within `middlewares/ros1/` and `middlewares/ros2/` plugins. Core code in `core/` and `apps/` should remain middleware-agnostic.

### License Management (REUSE)

This project uses [REUSE](https://reuse.software/) for license compliance. All source files must include SPDX headers:

```c
/*
* SPDX-FileCopyrightText: 2026 ArcheBase
*
* SPDX-License-Identifier: MulanPSL-2.0
*/
```

**Adding licenses to new files:**
```bash
# Auto-add headers to C/C++ files
reuse annotate --year 2026 --copyright "ArcheBase" --license "MulanPSL-2.0" --style c <files>

# Check compliance
reuse lint
```

**Project-wide rules in [REUSE.toml](REUSE.toml):**
- Frontend assets (`apps/axon_panel/**`) are covered by a single annotation
- Mock files follow the pattern `**/*_mock.*`
- Dependencies and build artifacts are excluded

**Note**: With the new plugin architecture, most ROS-specific code is isolated within `middlewares/ros1/` and `middlewares/ros2/` plugins. Core code in `core/` and `apps/` should remain middleware-agnostic.

## Refactoring Guidelines

**When refactoring code in this codebase, follow these principles:**
Expand Down Expand Up @@ -604,17 +748,21 @@ grep -r "AXON_ROS1\|AXON_ROS2" build/
| Purpose | Location |
|---------|----------|
| Core libraries | `core/axon_*/` |
| ROS1 plugin | `middlewares/ros1/src/ros1_plugin/` (CMake) |
| ROS2 plugin | `middlewares/ros2/src/ros2_plugin/` (CMake) |
| Zenoh plugin | `middlewares/zenoh/` (CMake) |
| ROS1 plugin | `middlewares/ros1/` |
| ROS2 plugin | `middlewares/ros2/` |
| Zenoh plugin | `middlewares/zenoh/` |
| Mock plugin (testing) | `middlewares/mock/src/mock_plugin/` |
| Filters | `middlewares/filters/` (shared data processing) |
| Depth compression | `middlewares/filters/depthlitez/` |
| Main app (HTTP RPC) | `apps/axon_recorder/` |
| Plugin example | `apps/plugin_example/` |
| Depth compression | `middlewares/filters/depthlitez/` (private) |
| Recorder app (HTTP RPC) | `apps/axon_recorder/` |
| Transfer daemon | `apps/axon_transfer/` |
| Web control panel | `apps/axon_panel/` (Vue 3) |
| Config tool CLI | `apps/axon_config/` |
| Plugin ABI interface | `apps/axon_recorder/plugin_loader.hpp` |
| Tests | `*/test/` or `*/test_*.cpp` |
| CMake modules | `cmake/` |
| Design docs | `docs/designs/` |
| Python client | `python/axon_client/` |

### Plugin Development

Expand All @@ -623,9 +771,28 @@ To create a new middleware plugin:
1. **Define the plugin ABI** - Implement the C interface in [apps/axon_recorder/plugin_loader.hpp](apps/axon_recorder/plugin_loader.hpp)
2. **Export descriptor function** - Each plugin must export `axon_get_plugin_descriptor()`
3. **Compile as shared library** - Build as `.so` with C linkage for ABI functions
4. **Example reference** - See [apps/plugin_example/](apps/plugin_example/) and [middlewares/ros2/src/ros2_plugin/](middlewares/ros2/src/ros2_plugin/)
4. **Example reference** - See [middlewares/mock/src/mock_plugin/](middlewares/mock/src/mock_plugin/) for a minimal plugin, or [middlewares/ros2/](middlewares/ros2/) for a full ROS2 implementation

**ABI Versioning:**
- `AxonPluginDescriptor` contains `abi_version_major` and `abi_version_minor`
- Always verify compatibility before loading plugins
- Reserve space in vtable for future extensions

### Application Development Workflows

**Current Status:**
- `axon_panel`: Fully implemented Vue 3 SPA at [apps/axon_panel/](apps/axon_panel/)
- `axon_transfer`: Standalone daemon pending design; currently uses [core/axon_uploader/](core/axon_uploader/) library integrated into recorder
- `axon_config`: Placeholder only; CLI interface and functionality pending design

**axon_panel Development:**
```bash
# Terminal 1: Start recorder
./build/axon_recorder/axon_recorder --plugin ./build/middlewares/libaxon_ros2.so

# Terminal 2: Start panel dev server
cd apps/axon_panel
npm run dev # Starts at http://localhost:5173
```

**See:** [docs/designs/frontend-design.md](docs/designs/frontend-design.md) for complete panel architecture
51 changes: 50 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,13 @@ help:
@printf "%s\n" " $(BLUE)make app-axon-recorder$(NC) - Build axon_recorder plugin loader"
@printf "%s\n" " $(BLUE)make app-plugin-example$(NC) - Build plugin example"
@echo ""
@printf "%s\n" "$(YELLOW)Mock Middleware (Testing):$(NC)"
@printf "%s\n" " $(BLUE)make build-mock$(NC) - Build mock middleware plugin"
@printf "%s\n" " $(BLUE)make test-mock-e2e$(NC) - Run mock plugin E2E test (standalone)"
@printf "%s\n" " $(BLUE)make test-mock-load$(NC) - Run mock plugin load test"
@printf "%s\n" " $(BLUE)make test-mock-integration$(NC) - Run mock middleware integration E2E test"
@printf "%s\n" " $(BLUE)make test-mock-all$(NC) - Run all mock middleware tests"
@echo ""
@printf "%s\n" "$(YELLOW)ROS Middlewares:$(NC)"
@printf "%s\n" " $(BLUE)make build$(NC) - Build (auto-detects ROS1/ROS2)"
@printf "%s\n" " $(BLUE)make build-ros1$(NC) - Build ROS1 (Noetic)"
Expand Down Expand Up @@ -416,6 +423,46 @@ app-axon-recorder: build-core
app-plugin-example: build-core
@printf "%s\n" "$(GREEN)✓ plugin example built$(NC)"

# =============================================================================
# Mock Middleware Targets
# =============================================================================

# Build mock middleware
build-mock:
@printf "%s\n" "$(YELLOW)Building mock middleware...$(NC)"
@mkdir -p middlewares/mock/src/mock_plugin/build
@cd middlewares/mock/src/mock_plugin/build && \
cmake .. \
-DCMAKE_BUILD_TYPE=$(BUILD_TYPE) \
-DCMAKE_INSTALL_PREFIX=$(PROJECT_ROOT)/middlewares/mock/install && \
cmake --build . -j$(NPROC)
@printf "%s\n" "$(GREEN)✓ Mock middleware built$(NC)"

# Test mock plugin E2E
test-mock-e2e: build-mock
@printf "%s\n" "$(YELLOW)Running mock plugin E2E test...$(NC)"
@cd middlewares/mock/src/mock_plugin/build && ./test_mock_plugin_e2e
@printf "%s\n" "$(GREEN)✓ Mock plugin E2E test passed$(NC)"

# Test mock plugin load
test-mock-load: build-mock
@printf "%s\n" "$(YELLOW)Running mock plugin load test...$(NC)"
@cd middlewares/mock/src/mock_plugin/build && \
./test_mock_plugin_load ./libmock_plugin.so
@printf "%s\n" "$(GREEN)✓ Mock plugin load test passed$(NC)"

# Test mock middleware integration with axon_recorder
test-mock-integration: build-mock build-core
@printf "%s\n" "$(YELLOW)Running mock middleware integration E2E test...$(NC)"
@cd middlewares/mock && ./test_e2e_with_mock.sh
@printf "%s\n" "$(GREEN)✓ Mock middleware integration test passed$(NC)"

# Run all mock middleware tests
test-mock-all: build-mock
@printf "%s\n" "$(YELLOW)Running all mock middleware tests...$(NC)"
@cd middlewares/mock && ./test_full_workflow.sh
@printf "%s\n" "$(GREEN)✓ All mock middleware tests passed$(NC)"

# =============================================================================
# ROS Middleware Targets
# =============================================================================
Expand Down Expand Up @@ -483,6 +530,9 @@ test: test-core
clean:
@printf "%s\n" "$(YELLOW)Cleaning build artifacts...$(NC)"
@rm -rf $(BUILD_DIR) $(COVERAGE_DIR)
@cd middlewares/ros2 && rm -rf build install log 2>/dev/null || true
@cd middlewares/ros1 && catkin clean --yes 2>/dev/null || true
@rm -rf middlewares/mock/src/mock_plugin/build middlewares/mock/install 2>/dev/null || true
@printf "%s\n" "$(GREEN)✓ All build artifacts cleaned$(NC)"

# Install target
Expand Down Expand Up @@ -1174,4 +1224,3 @@ format-ci:
printf "%s\n" "$(YELLOW)Or format files individually: $(CLANG_FORMAT) -i <file>$(NC)" && \
exit 1)
@printf "%s\n" "$(GREEN)✓ Code formatting check passed$(NC)"

11 changes: 9 additions & 2 deletions REUSE.toml
Original file line number Diff line number Diff line change
Expand Up @@ -161,8 +161,8 @@ SPDX-License-Identifier = "NO-COPYRIGHT"

[[annotations]]
path = "**/*_mock.*"
SPDX-FileCopyrightText = "NO-COPYRIGHT"
SPDX-License-Identifier = "NO-COPYRIGHT"
SPDX-FileCopyrightText = "Copyright (c) 2026 ArcheBase"
SPDX-License-Identifier = "MulanPSL-2.0"

# Ignore dependency directories
[[annotations]]
Expand All @@ -174,3 +174,10 @@ SPDX-License-Identifier = "NO-COPYRIGHT"
path = "install/**"
SPDX-FileCopyrightText = "NO-COPYRIGHT"
SPDX-License-Identifier = "NO-COPYRIGHT"

# Frontend assets (JavaScript, CSS, HTML, Vue components)
[[annotations]]
path = "apps/axon_panel/**"
precedence = "override"
SPDX-FileCopyrightText = "Copyright (c) 2026 ArcheBase"
SPDX-License-Identifier = "MulanPSL-2.0"
8 changes: 8 additions & 0 deletions apps/axon_config/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
cmake_minimum_required(VERSION 3.16)
project(axon_config LANGUAGES CXX)

# C++17 standard
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

# TODO: Add executable, CLI argument parsing, and configuration modules
17 changes: 17 additions & 0 deletions apps/axon_config/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# Axon Config Application

**Status:** Placeholder - Design pending

## Purpose

Robot initialization and configuration collection tool.

## Design Notes

TODO: Define CLI interface for:
- Robot type discovery
- Serial number collection
- Sensor configuration
- URDF file collection

This tool will implement configuration management functionality directly (no separate library).
Loading