feat: use AprilTag instead of QR code
79
APRILTAG_MIGRATION.md
Normal file
@@ -0,0 +1,79 @@
|
|||||||
|
# AprilTag Migration Summary
|
||||||
|
|
||||||
|
## Completed Changes
|
||||||
|
|
||||||
|
### 1. Database Migration ✅
|
||||||
|
- Migrated from `qr_code` string field to `apriltag_id` integer field
|
||||||
|
- Added constraint to ensure valid AprilTag IDs (0-586)
|
||||||
|
- Created unique index for apriltag_id
|
||||||
|
- Preserved old qr_code data as qr_code_old for rollback safety
|
||||||
|
|
||||||
|
### 2. Schema Updates ✅
|
||||||
|
- Updated `StorageLocation` schema to use `apriltag_id` instead of `qr_code`
|
||||||
|
- Added validation for AprilTag ID range (0-586)
|
||||||
|
- Implemented auto-assignment of next available ID
|
||||||
|
- Added unique constraint validation
|
||||||
|
|
||||||
|
### 3. Business Logic Refactoring ✅
|
||||||
|
- Replaced `ComponentsElixir.QRCode` module with `ComponentsElixir.AprilTag` module
|
||||||
|
- Updated inventory functions to use AprilTag IDs instead of QR code strings
|
||||||
|
- Implemented AprilTag ID availability checking
|
||||||
|
- Added bulk SVG generation functionality
|
||||||
|
|
||||||
|
### 4. UI/UX Improvements ✅
|
||||||
|
- Replaced dropdown with 587 options with better UX:
|
||||||
|
- Radio buttons for "Auto-assign" vs "Manual selection"
|
||||||
|
- Number input for specific ID selection when manual mode selected
|
||||||
|
- Shows available ID count and examples
|
||||||
|
- Different interface for add vs edit forms
|
||||||
|
- Updated templates to show AprilTag information instead of QR codes
|
||||||
|
- Added download functionality for AprilTag SVGs
|
||||||
|
|
||||||
|
### 5. AprilTag Generation ✅
|
||||||
|
- Created `ComponentsElixir.AprilTag` module for managing tag36h11 family
|
||||||
|
- Generated all 587 placeholder SVG files with human-readable IDs
|
||||||
|
- Added Mix task `mix apriltag.generate_all` for batch generation
|
||||||
|
- SVG files served statically at `/apriltags/tag36h11_id_XXX.svg`
|
||||||
|
|
||||||
|
### 6. Event Handling ✅
|
||||||
|
- Updated LiveView event handlers for AprilTag scanning/assignment
|
||||||
|
- Added mode switching for manual vs automatic assignment
|
||||||
|
- Implemented proper form state management for different modes
|
||||||
|
|
||||||
|
## Benefits Achieved
|
||||||
|
|
||||||
|
1. **Better UX**: No more 587-option dropdown menu
|
||||||
|
2. **Future-Ready**: AprilTags designed for multi-tag detection scenarios
|
||||||
|
3. **Robust**: 587 unique IDs provide ample space without conflicts
|
||||||
|
4. **Maintainable**: Simpler integer ID system vs complex string encoding
|
||||||
|
5. **Industry Standard**: AprilTags widely used in robotics/AR applications
|
||||||
|
|
||||||
|
## Current State
|
||||||
|
|
||||||
|
- ✅ Database schema updated
|
||||||
|
- ✅ All 587 placeholder SVG files generated
|
||||||
|
- ✅ UI forms updated with better UX
|
||||||
|
- ✅ Business logic migrated to AprilTag system
|
||||||
|
- ⏳ **Next**: Real AprilTag pattern generation (future enhancement)
|
||||||
|
- ⏳ **Next**: Camera detection integration (future enhancement)
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
### Generate AprilTag SVGs
|
||||||
|
```bash
|
||||||
|
mix apriltag.generate_all # Generate missing files
|
||||||
|
mix apriltag.generate_all --force # Regenerate all files
|
||||||
|
```
|
||||||
|
|
||||||
|
### Available AprilTag IDs
|
||||||
|
- Range: 0-586 (tag36h11 family)
|
||||||
|
- Auto-assignment picks next available ID
|
||||||
|
- Manual assignment allows specific ID selection
|
||||||
|
- Unique constraint prevents conflicts
|
||||||
|
|
||||||
|
### File Locations
|
||||||
|
- SVG files: `priv/static/apriltags/tag36h11_id_XXX.svg`
|
||||||
|
- URL pattern: `/apriltags/tag36h11_id_XXX.svg`
|
||||||
|
- Placeholder pattern includes human-readable ID label
|
||||||
|
|
||||||
|
The system is now ready for use with AprilTags instead of QR codes! The placeholder SVGs will work perfectly for testing and development until we implement actual AprilTag pattern generation.
|
||||||
27
README.md
@@ -37,8 +37,8 @@ A modern, idiomatic Elixir/Phoenix port of the original PHP-based component inve
|
|||||||
- **Search & Filter**: Fast search across component names, descriptions, and keywords
|
- **Search & Filter**: Fast search across component names, descriptions, and keywords
|
||||||
- **Category Organization**: Hierarchical category system for better organization
|
- **Category Organization**: Hierarchical category system for better organization
|
||||||
- **Category Management**: Add, edit, delete categories through the web interface with hierarchical support
|
- **Category Management**: Add, edit, delete categories through the web interface with hierarchical support
|
||||||
- **Storage Location System**: Hierarchical storage locations (shelf → drawer → box) with automatic QR code generation
|
- **Storage Location System**: Hierarchical storage locations (shelf → drawer → box) with automatic AprilTag generation
|
||||||
- **QR Code Integration**: Automatic QR code generation and display for all storage locations with download capability
|
- **AprilTag Integration**: Automatic AprilTag generation and display for all storage locations with download capability
|
||||||
- **Datasheet Links**: Direct links to component datasheets
|
- **Datasheet Links**: Direct links to component datasheets
|
||||||
- **Real-time Updates**: All changes are immediately reflected in the interface
|
- **Real-time Updates**: All changes are immediately reflected in the interface
|
||||||
|
|
||||||
@@ -100,7 +100,7 @@ The application uses a simple password-based authentication system:
|
|||||||
- **`ComponentsElixirWeb.LoginLive`**: Authentication interface
|
- **`ComponentsElixirWeb.LoginLive`**: Authentication interface
|
||||||
- **`ComponentsElixirWeb.ComponentsLive`**: Main component management interface
|
- **`ComponentsElixirWeb.ComponentsLive`**: Main component management interface
|
||||||
- **`ComponentsElixirWeb.CategoriesLive`**: Category management interface
|
- **`ComponentsElixirWeb.CategoriesLive`**: Category management interface
|
||||||
- **`ComponentsElixirWeb.StorageLocationsLive`**: Hierarchical storage location management with QR codes
|
- **`ComponentsElixirWeb.StorageLocationsLive`**: Hierarchical storage location management with AprilTags
|
||||||
|
|
||||||
### Key Features
|
### Key Features
|
||||||
- **Real-time updates**: Changes are immediately reflected without page refresh
|
- **Real-time updates**: Changes are immediately reflected without page refresh
|
||||||
@@ -118,16 +118,16 @@ The application uses a simple password-based authentication system:
|
|||||||
| Manual editing | `Inventory.update_component/2` | **NEW**: Full edit functionality with validation |
|
| Manual editing | `Inventory.update_component/2` | **NEW**: Full edit functionality with validation |
|
||||||
| `changeAmount.php` | `Inventory.update_component_count/2` | Atomic operations, constraints |
|
| `changeAmount.php` | `Inventory.update_component_count/2` | Atomic operations, constraints |
|
||||||
| Manual category management | `CategoriesLive` + `Inventory.create_category/1` | **NEW**: Full category CRUD with web interface |
|
| Manual category management | `CategoriesLive` + `Inventory.create_category/1` | **NEW**: Full category CRUD with web interface |
|
||||||
| Manual location tracking | `StorageLocationsLive` + `Inventory` context | **NEW**: Hierarchical storage locations with automatic QR codes |
|
| Manual location tracking | `StorageLocationsLive` + `Inventory` context | **NEW**: Hierarchical storage locations with automatic AprilTags |
|
||||||
| `imageUpload.php` | Phoenix LiveView file uploads with `.live_file_input` | **IMPLEMENTED**: Full image upload with preview, validation, and automatic cleanup |
|
| `imageUpload.php` | Phoenix LiveView file uploads with `.live_file_input` | **IMPLEMENTED**: Full image upload with preview, validation, and automatic cleanup |
|
||||||
| Session management | Phoenix sessions + LiveView | Built-in CSRF protection |
|
| Session management | Phoenix sessions + LiveView | Built-in CSRF protection |
|
||||||
|
|
||||||
## 🚀 Future Enhancements
|
## 🚀 Future Enhancements
|
||||||
|
|
||||||
### Component Management
|
### Component Management
|
||||||
- **Barcode Support** - Generate and scan traditional barcodes in addition to QR codes
|
- **Barcode Support** - Generate and scan traditional barcodes in addition to AprilTags
|
||||||
- **Camera Integration** - JavaScript-based QR scanning with camera access for mobile/desktop
|
- **Camera Integration** - JavaScript-based AprilTag scanning with camera access for mobile/desktop
|
||||||
- **Multi-QR Code Detection** - Spatial analysis and disambiguation for multiple codes in same image
|
- **Multi-AprilTag Detection** - Spatial analysis and disambiguation for multiple tags in same image
|
||||||
- **Bulk Operations** - Import/export components from CSV, batch updates
|
- **Bulk Operations** - Import/export components from CSV, batch updates
|
||||||
- **Search and Filtering** - Advanced search by specifications, tags, location
|
- **Search and Filtering** - Advanced search by specifications, tags, location
|
||||||
- **Component Templates** - Reusable templates for common component types
|
- **Component Templates** - Reusable templates for common component types
|
||||||
@@ -135,7 +135,7 @@ The application uses a simple password-based authentication system:
|
|||||||
|
|
||||||
### Storage Organization
|
### Storage Organization
|
||||||
- **Physical Layout Mapping** - Visual representation of shelves, drawers, and boxes
|
- **Physical Layout Mapping** - Visual representation of shelves, drawers, and boxes
|
||||||
- **Bulk QR Code Printing** - Generate printable sheets of QR codes for labeling
|
- **Bulk AprilTag Printing** - Generate printable sheets of AprilTags for labeling
|
||||||
|
|
||||||
## ✅ Recently Implemented Features
|
## ✅ Recently Implemented Features
|
||||||
|
|
||||||
@@ -146,11 +146,12 @@ The application uses a simple password-based authentication system:
|
|||||||
- **Web Interface** ✅ Complete - Storage locations management page with navigation
|
- **Web Interface** ✅ Complete - Storage locations management page with navigation
|
||||||
- **Component-Storage Integration** ✅ Complete - Components can now be assigned to storage locations via dropdown interface
|
- **Component-Storage Integration** ✅ Complete - Components can now be assigned to storage locations via dropdown interface
|
||||||
|
|
||||||
### QR Code System - Still Needed 🚧 **PARTIALLY IMPLEMENTED**
|
### AprilTag System 🚧 **PARTIALLY IMPLEMENTED**
|
||||||
- **Visual QR Code Generation** ✅ Complete - QR code images are generated and displayed for all storage locations
|
- **Visual AprilTag Generation** ❌ Partially Implemented - Placeholder SVGs generated
|
||||||
- **QR Code Scanning** ❌ Missing - No camera integration or scanning functionality
|
- **Flexible Assignment Options** ✅ Complete - Auto-assign, manual selection, or no AprilTag assignment for storage locations
|
||||||
- **QR Code Processing** ❌ Missing - Backend logic for processing scanned codes
|
- **AprilTag Download** ✅ Complete - Individual AprilTag SVG files can be downloaded for printing
|
||||||
- **Multi-QR Disambiguation** ❌ Missing - No handling of multiple QR codes in same image
|
- **AprilTag Scanning** ❌ Missing - No camera integration or scanning functionality (future enhancement)
|
||||||
|
- **AprilTag Processing** ❌ Missing - Backend logic for processing scanned tags (future enhancement)
|
||||||
|
|
||||||
### Image Upload System ✅ **COMPLETED**
|
### Image Upload System ✅ **COMPLETED**
|
||||||
- **Phoenix LiveView file uploads** with `.live_file_input` component
|
- **Phoenix LiveView file uploads** with `.live_file_input` component
|
||||||
|
|||||||
@@ -66,6 +66,22 @@ window.addEventListener("phx:download_file", (event) => {
|
|||||||
window.URL.revokeObjectURL(url)
|
window.URL.revokeObjectURL(url)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// Add AprilTag download functionality
|
||||||
|
window.addEventListener("phx:download_apriltag", (event) => {
|
||||||
|
const { filename, url } = event.detail
|
||||||
|
|
||||||
|
// Create download link using the static file URL
|
||||||
|
const link = document.createElement('a')
|
||||||
|
link.href = url
|
||||||
|
link.download = filename
|
||||||
|
link.setAttribute('target', '_blank') // Open in new tab as fallback
|
||||||
|
document.body.appendChild(link)
|
||||||
|
link.click()
|
||||||
|
|
||||||
|
// Clean up
|
||||||
|
document.body.removeChild(link)
|
||||||
|
})
|
||||||
|
|
||||||
// expose liveSocket on window for web console debug logs and latency simulation:
|
// expose liveSocket on window for web console debug logs and latency simulation:
|
||||||
// >> liveSocket.enableDebug()
|
// >> liveSocket.enableDebug()
|
||||||
// >> liveSocket.enableLatencySim(1000) // enabled for duration of browser session
|
// >> liveSocket.enableLatencySim(1000) // enabled for duration of browser session
|
||||||
|
|||||||
325
design_docs/apriltag_storage_system.md
Normal file
@@ -0,0 +1,325 @@
|
|||||||
|
# AprilTag Storage Location System Design
|
||||||
|
|
||||||
|
## Overview
|
||||||
|
Implement a hierarchical storage location system with AprilTag tag36h11 generation and assignment capabilities to enable quick component location entry and filtering.
|
||||||
|
|
||||||
|
## Database Schema
|
||||||
|
|
||||||
|
### 1. Storage Locations Table
|
||||||
|
```sql
|
||||||
|
CREATE TABLE storage_locations (
|
||||||
|
id SERIAL PRIMARY KEY,
|
||||||
|
name VARCHAR(255) NOT NULL,
|
||||||
|
description TEXT,
|
||||||
|
apriltag_id INTEGER UNIQUE,
|
||||||
|
parent_id INTEGER REFERENCES storage_locations(id),
|
||||||
|
level INTEGER NOT NULL DEFAULT 0,
|
||||||
|
path TEXT NOT NULL, -- Materialized path: "shelf1/drawer2/box3"
|
||||||
|
is_active BOOLEAN DEFAULT TRUE,
|
||||||
|
created_at TIMESTAMP DEFAULT NOW(),
|
||||||
|
updated_at TIMESTAMP DEFAULT NOW(),
|
||||||
|
|
||||||
|
CONSTRAINT apriltag_id_range CHECK (apriltag_id >= 0 AND apriltag_id <= 586)
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE INDEX idx_storage_locations_parent_id ON storage_locations(parent_id);
|
||||||
|
CREATE UNIQUE INDEX idx_storage_locations_apriltag_id ON storage_locations(apriltag_id);
|
||||||
|
CREATE INDEX idx_storage_locations_path ON storage_locations USING gin(path gin_trgm_ops);
|
||||||
|
CREATE UNIQUE INDEX idx_storage_locations_name_parent ON storage_locations(name, parent_id);
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. Modified Components Table
|
||||||
|
```sql
|
||||||
|
-- Migration to add storage_location_id to components
|
||||||
|
ALTER TABLE components
|
||||||
|
ADD COLUMN storage_location_id INTEGER REFERENCES storage_locations(id),
|
||||||
|
ADD COLUMN legacy_position VARCHAR(255); -- Keep old position data for migration
|
||||||
|
|
||||||
|
-- Move existing position data to legacy_position
|
||||||
|
UPDATE components SET legacy_position = position;
|
||||||
|
```
|
||||||
|
|
||||||
|
## AprilTag Design Strategy
|
||||||
|
|
||||||
|
### AprilTag tag36h11 Family
|
||||||
|
- **Total tags available**: 587 (IDs 0-586)
|
||||||
|
- **Format**: Pre-generated SVG files with human-readable ID labels
|
||||||
|
- **Storage**: `/priv/static/apriltags/tag36h11_id_XXX.svg`
|
||||||
|
- **Assignment**: One-to-one mapping between AprilTag ID and storage location
|
||||||
|
|
||||||
|
### AprilTag Components:
|
||||||
|
- **AprilTag ID**: Integer (0-586) stored in database
|
||||||
|
- **SVG File**: Pre-generated with 2-module margin and ID label
|
||||||
|
- **Human Readable**: "ID XXX" format for easy identification
|
||||||
|
- **Uniqueness**: Database constraint ensures no duplicate assignments
|
||||||
|
|
||||||
|
### Advantages over QR Codes:
|
||||||
|
1. **Robust Detection**: AprilTags designed for reliable multi-tag detection
|
||||||
|
2. **Standard Format**: Well-established robotics/AR standard
|
||||||
|
3. **Better Performance**: More resistant to lighting/angle variations
|
||||||
|
4. **Multi-tag Support**: Designed specifically for multiple tags in same view
|
||||||
|
|
||||||
|
## Multi-AprilTag Detection Strategy
|
||||||
|
|
||||||
|
### 1. Spatial Independence
|
||||||
|
```
|
||||||
|
Unlike QR codes, AprilTags are designed for multi-tag scenarios:
|
||||||
|
- Each tag has unique geometric properties
|
||||||
|
- No interference between nearby tags
|
||||||
|
- Reliable detection at various scales and angles
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. Detection Priority
|
||||||
|
```
|
||||||
|
Selection Priority:
|
||||||
|
1. User selection (tap/click on detected tag)
|
||||||
|
2. Closest tag to center of frame
|
||||||
|
3. Largest tag in frame (closest to camera)
|
||||||
|
4. Most recent successfully scanned tag
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. Visual Feedback
|
||||||
|
```
|
||||||
|
Camera Overlay:
|
||||||
|
- Draw bounding boxes around each detected AprilTag
|
||||||
|
- Show AprilTag ID and location name
|
||||||
|
- Highlight "best candidate" with different color
|
||||||
|
- Allow tap-to-select for disambiguation
|
||||||
|
```
|
||||||
|
|
||||||
|
## Implementation Components
|
||||||
|
|
||||||
|
### 1. Elixir Modules
|
||||||
|
|
||||||
|
#### Storage Location Schema
|
||||||
|
```elixir
|
||||||
|
defmodule ComponentsElixir.Inventory.StorageLocation do
|
||||||
|
use Ecto.Schema
|
||||||
|
import Ecto.Changeset
|
||||||
|
|
||||||
|
schema "storage_locations" do
|
||||||
|
field :name, :string
|
||||||
|
field :description, :string
|
||||||
|
field :apriltag_id, :integer
|
||||||
|
field :level, :integer, virtual: true
|
||||||
|
field :path, :string, virtual: true
|
||||||
|
field :is_active, :boolean, default: true
|
||||||
|
|
||||||
|
belongs_to :parent, __MODULE__
|
||||||
|
has_many :children, __MODULE__, foreign_key: :parent_id
|
||||||
|
has_many :components, Component
|
||||||
|
|
||||||
|
timestamps()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
```
|
||||||
|
|
||||||
|
#### AprilTag Management
|
||||||
|
```elixir
|
||||||
|
defmodule ComponentsElixir.AprilTag do
|
||||||
|
def generate_apriltag_svg(apriltag_id, opts \\ []) do
|
||||||
|
# Generate SVG with actual AprilTag pattern
|
||||||
|
# Include human-readable ID below tag
|
||||||
|
end
|
||||||
|
|
||||||
|
def get_apriltag_url(storage_location) do
|
||||||
|
# Return URL to pre-generated SVG file
|
||||||
|
end
|
||||||
|
|
||||||
|
def available_apriltag_ids() do
|
||||||
|
# Return list of unused AprilTag IDs (0-586)
|
||||||
|
end
|
||||||
|
|
||||||
|
def generate_all_apriltag_svgs() do
|
||||||
|
# Pre-generate all 587 SVG files
|
||||||
|
end
|
||||||
|
end
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. Phoenix LiveView Components
|
||||||
|
|
||||||
|
#### AprilTag Assignment Interface
|
||||||
|
```elixir
|
||||||
|
defmodule ComponentsElixirWeb.StorageLocationsLive do
|
||||||
|
use ComponentsElixirWeb, :live_view
|
||||||
|
|
||||||
|
def mount(_params, _session, socket) do
|
||||||
|
socket =
|
||||||
|
socket
|
||||||
|
|> assign(:scanning, false)
|
||||||
|
|> assign(:available_apriltag_ids, AprilTag.available_apriltag_ids())
|
||||||
|
|> assign(:selected_location, nil)
|
||||||
|
|
||||||
|
{:ok, socket}
|
||||||
|
end
|
||||||
|
|
||||||
|
def handle_event("assign_apriltag", %{"apriltag_id" => id}, socket) do
|
||||||
|
# Assign specific AprilTag ID to storage location
|
||||||
|
end
|
||||||
|
|
||||||
|
def handle_event("apriltag_detected", %{"ids" => ids}, socket) do
|
||||||
|
# Handle multiple AprilTag detection
|
||||||
|
parsed_tags = Enum.map(ids, &resolve_storage_location/1)
|
||||||
|
|
||||||
|
socket =
|
||||||
|
socket
|
||||||
|
|> assign(:detected_tags, parsed_tags)
|
||||||
|
|> maybe_auto_select_location(parsed_tags)
|
||||||
|
|
||||||
|
{:noreply, socket}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. JavaScript AprilTag Detection (Future)
|
||||||
|
|
||||||
|
#### Camera Integration
|
||||||
|
```javascript
|
||||||
|
// assets/js/apriltag_scanner.js
|
||||||
|
import { AprilTagDetector } from "apriltag-js";
|
||||||
|
|
||||||
|
export const AprilTagScanner = {
|
||||||
|
mounted() {
|
||||||
|
this.detector = new AprilTagDetector();
|
||||||
|
this.video = this.el.querySelector('video');
|
||||||
|
this.canvas = this.el.querySelector('canvas');
|
||||||
|
|
||||||
|
this.startCamera();
|
||||||
|
this.scanLoop();
|
||||||
|
},
|
||||||
|
|
||||||
|
scanLoop() {
|
||||||
|
if (this.video.readyState === this.video.HAVE_ENOUGH_DATA) {
|
||||||
|
const detections = this.detector.detect(this.canvas);
|
||||||
|
|
||||||
|
if (detections.length > 0) {
|
||||||
|
const apriltag_ids = detections.map(d => d.id);
|
||||||
|
this.pushEvent("apriltag_detected", { ids: apriltag_ids });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
requestAnimationFrame(() => this.scanLoop());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
## User Experience Flow
|
||||||
|
|
||||||
|
### 1. Adding Components with AprilTag Scan
|
||||||
|
```
|
||||||
|
1. User clicks "Add Component"
|
||||||
|
2. Position field shows camera icon
|
||||||
|
3. Click camera → AprilTag scanner opens
|
||||||
|
4. Scan storage location AprilTag
|
||||||
|
5. If multiple tags detected:
|
||||||
|
- Show overlay with detected locations
|
||||||
|
- User taps to select specific location
|
||||||
|
6. Location path auto-filled: "Shelf A → Drawer 2 → Box 5"
|
||||||
|
7. Component saved with storage_location_id
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. Storage Location Management
|
||||||
|
```
|
||||||
|
1. New "Storage Locations" section in admin
|
||||||
|
2. Add/edit locations with AprilTag ID selection
|
||||||
|
3. Auto-assign next available ID or manual selection
|
||||||
|
4. Download AprilTag SVG with location info
|
||||||
|
5. Print labels for physical attachment
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. AprilTag Assignment
|
||||||
|
```
|
||||||
|
1. Available AprilTag IDs shown in dropdown (0-586)
|
||||||
|
2. Current assignments displayed
|
||||||
|
3. Bulk assignment for initial setup
|
||||||
|
4. Re-assignment with validation
|
||||||
|
5. Conflict prevention (one tag per location)
|
||||||
|
```
|
||||||
|
|
||||||
|
## Handling Multiple AprilTags in Same Image
|
||||||
|
|
||||||
|
### Strategy 1: Designed for Multi-Tag
|
||||||
|
- AprilTags inherently support multiple detection
|
||||||
|
- No spatial interference between tags
|
||||||
|
- Each tag independently detectable
|
||||||
|
|
||||||
|
### Strategy 2: User Selection
|
||||||
|
- Display all detected tags with IDs
|
||||||
|
- Show corresponding location names
|
||||||
|
- Allow tap/click to select intended tag
|
||||||
|
- Remember user preferences
|
||||||
|
|
||||||
|
### Strategy 3: Smart Defaults
|
||||||
|
- Prioritize by distance to frame center
|
||||||
|
- Consider tag size (closer = larger)
|
||||||
|
- Use most recently accessed locations
|
||||||
|
- Provide manual override always
|
||||||
|
|
||||||
|
## Migration Strategy
|
||||||
|
|
||||||
|
### Phase 1: Database Migration
|
||||||
|
1. Run migration to add apriltag_id field
|
||||||
|
2. Remove qr_code field and constraints
|
||||||
|
3. Update schema and validation rules
|
||||||
|
|
||||||
|
### Phase 2: AprilTag Generation
|
||||||
|
1. Generate all 587 SVG files using Mix task
|
||||||
|
2. Serve static files via Phoenix
|
||||||
|
3. Update UI to show AprilTag instead of QR code
|
||||||
|
|
||||||
|
### Phase 3: Assignment Interface
|
||||||
|
1. Add AprilTag selection to location forms
|
||||||
|
2. Implement auto-assignment logic
|
||||||
|
3. Create bulk assignment tools
|
||||||
|
4. Add conflict detection
|
||||||
|
|
||||||
|
### Phase 4: Detection (Future)
|
||||||
|
1. Integrate AprilTag detection library
|
||||||
|
2. Implement multi-tag camera interface
|
||||||
|
3. Add disambiguation UI
|
||||||
|
4. Test detection robustness
|
||||||
|
|
||||||
|
## Technical Dependencies
|
||||||
|
|
||||||
|
### Elixir Dependencies
|
||||||
|
```elixir
|
||||||
|
# mix.exs - no additional dependencies needed for generation
|
||||||
|
# Future detection would require:
|
||||||
|
# {:apriltag, "~> 0.1"} # hypothetical
|
||||||
|
```
|
||||||
|
|
||||||
|
### JavaScript Dependencies (Future Detection)
|
||||||
|
```javascript
|
||||||
|
// package.json
|
||||||
|
{
|
||||||
|
"apriltag-js": "^1.0.0", // hypothetical
|
||||||
|
"camera-utils": "^2.0.0" // camera access utilities
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Database Indexes for Performance
|
||||||
|
```sql
|
||||||
|
-- Fast location lookups
|
||||||
|
CREATE INDEX idx_components_storage_location_id ON components(storage_location_id);
|
||||||
|
|
||||||
|
-- Hierarchical queries
|
||||||
|
CREATE INDEX idx_storage_locations_path_gin ON storage_locations USING gin(path gin_trgm_ops);
|
||||||
|
|
||||||
|
-- AprilTag uniqueness and fast lookup
|
||||||
|
CREATE UNIQUE INDEX idx_storage_locations_apriltag_id ON storage_locations(apriltag_id);
|
||||||
|
|
||||||
|
-- Valid AprilTag ID range constraint
|
||||||
|
ALTER TABLE storage_locations ADD CONSTRAINT apriltag_id_range
|
||||||
|
CHECK (apriltag_id >= 0 AND apriltag_id <= 586);
|
||||||
|
```
|
||||||
|
|
||||||
|
## Benefits Over QR Code System
|
||||||
|
|
||||||
|
1. **Robust Multi-Tag Detection**: AprilTags designed specifically for multiple tags in same view
|
||||||
|
2. **Better Performance**: More reliable detection under various lighting and angle conditions
|
||||||
|
3. **Industry Standard**: Widely used in robotics and AR applications
|
||||||
|
4. **No Encoding Needed**: Simple integer ID mapping instead of complex string encoding
|
||||||
|
5. **Collision Avoidance**: 587 unique IDs provide ample space without conflicts
|
||||||
|
6. **Future-Proof**: Ready for advanced detection and tracking features
|
||||||
|
|
||||||
|
This design provides a robust foundation for AprilTag-based storage management while leveraging the inherent advantages of AprilTags for multi-tag detection scenarios.
|
||||||
@@ -361,13 +361,7 @@ export const QRScanner = {
|
|||||||
```
|
```
|
||||||
|
|
||||||
### JavaScript Dependencies
|
### JavaScript Dependencies
|
||||||
```json
|
???
|
||||||
// package.json
|
|
||||||
{
|
|
||||||
"jsqr": "^1.4.0",
|
|
||||||
"qr-scanner": "^1.4.2"
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## Database Indexes for Performance
|
## Database Indexes for Performance
|
||||||
```sql
|
```sql
|
||||||
|
|||||||
226
lib/components_elixir/apriltag.ex
Normal file
@@ -0,0 +1,226 @@
|
|||||||
|
defmodule ComponentsElixir.AprilTag do
|
||||||
|
@moduledoc """
|
||||||
|
AprilTag generation and management for storage locations.
|
||||||
|
|
||||||
|
Provides functionality to generate AprilTag images for storage locations
|
||||||
|
and manage the tag36h11 family (IDs 0-586).
|
||||||
|
"""
|
||||||
|
|
||||||
|
import Ecto.Query
|
||||||
|
|
||||||
|
@tag36h11_count 587
|
||||||
|
@apriltag_size 200
|
||||||
|
|
||||||
|
@doc """
|
||||||
|
Returns the total number of available AprilTags in the tag36h11 family.
|
||||||
|
"""
|
||||||
|
def tag36h11_count, do: @tag36h11_count
|
||||||
|
|
||||||
|
@doc """
|
||||||
|
Validates if an AprilTag ID is valid for tag36h11 family.
|
||||||
|
|
||||||
|
## Examples
|
||||||
|
|
||||||
|
iex> ComponentsElixir.AprilTag.valid_apriltag_id?(42)
|
||||||
|
true
|
||||||
|
|
||||||
|
iex> ComponentsElixir.AprilTag.valid_apriltag_id?(587)
|
||||||
|
false
|
||||||
|
"""
|
||||||
|
def valid_apriltag_id?(id) when is_integer(id) do
|
||||||
|
id >= 0 and id < @tag36h11_count
|
||||||
|
end
|
||||||
|
def valid_apriltag_id?(_), do: false
|
||||||
|
|
||||||
|
@doc """
|
||||||
|
Gets the SVG file path for a given AprilTag ID.
|
||||||
|
|
||||||
|
## Examples
|
||||||
|
|
||||||
|
iex> ComponentsElixir.AprilTag.get_apriltag_svg_path(42)
|
||||||
|
"/apriltags/tag36h11_id_042.svg"
|
||||||
|
"""
|
||||||
|
def get_apriltag_svg_path(apriltag_id) when is_integer(apriltag_id) do
|
||||||
|
if valid_apriltag_id?(apriltag_id) do
|
||||||
|
"/apriltags/tag36h11_id_#{String.pad_leading(to_string(apriltag_id), 3, "0")}.svg"
|
||||||
|
else
|
||||||
|
nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
@doc """
|
||||||
|
Gets the SVG file URL for a storage location's AprilTag.
|
||||||
|
|
||||||
|
## Examples
|
||||||
|
|
||||||
|
iex> location = %StorageLocation{apriltag_id: 42}
|
||||||
|
iex> ComponentsElixir.AprilTag.get_apriltag_url(location)
|
||||||
|
"/apriltags/tag36h11_id_042.svg"
|
||||||
|
"""
|
||||||
|
def get_apriltag_url(storage_location) do
|
||||||
|
case storage_location.apriltag_id do
|
||||||
|
nil -> nil
|
||||||
|
apriltag_id -> get_apriltag_svg_path(apriltag_id)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
@doc """
|
||||||
|
Returns a list of all available AprilTag IDs.
|
||||||
|
"""
|
||||||
|
def all_apriltag_ids do
|
||||||
|
0..(@tag36h11_count - 1) |> Enum.to_list()
|
||||||
|
end
|
||||||
|
|
||||||
|
@doc """
|
||||||
|
Returns a list of used AprilTag IDs in the system.
|
||||||
|
"""
|
||||||
|
def used_apriltag_ids do
|
||||||
|
ComponentsElixir.Repo.all(
|
||||||
|
from sl in ComponentsElixir.Inventory.StorageLocation,
|
||||||
|
where: not is_nil(sl.apriltag_id),
|
||||||
|
select: sl.apriltag_id
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
@doc """
|
||||||
|
Returns a list of available (unused) AprilTag IDs.
|
||||||
|
"""
|
||||||
|
def available_apriltag_ids do
|
||||||
|
used = used_apriltag_ids()
|
||||||
|
all_apriltag_ids() -- used
|
||||||
|
end
|
||||||
|
|
||||||
|
@doc """
|
||||||
|
Gets the next available AprilTag ID, or nil if all are used.
|
||||||
|
"""
|
||||||
|
def next_available_apriltag_id do
|
||||||
|
available_apriltag_ids() |> List.first()
|
||||||
|
end
|
||||||
|
|
||||||
|
@doc """
|
||||||
|
Generates label data for a storage location with AprilTag.
|
||||||
|
|
||||||
|
This could be used to generate PDF labels or send to a label printer.
|
||||||
|
"""
|
||||||
|
def generate_label_data(storage_location) do
|
||||||
|
%{
|
||||||
|
apriltag_id: storage_location.apriltag_id,
|
||||||
|
apriltag_url: get_apriltag_url(storage_location),
|
||||||
|
name: storage_location.name,
|
||||||
|
path: storage_location.path,
|
||||||
|
level: storage_location.level,
|
||||||
|
description: storage_location.description
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
@doc """
|
||||||
|
Generates an SVG string for an AprilTag with the given ID.
|
||||||
|
|
||||||
|
This creates a basic SVG representation of the AprilTag pattern
|
||||||
|
with the ID displayed below it for human readability.
|
||||||
|
|
||||||
|
Note: This is a simplified implementation. For production use,
|
||||||
|
you'd want to use the actual AprilTag generation algorithm or
|
||||||
|
pre-generated assets.
|
||||||
|
"""
|
||||||
|
def generate_apriltag_svg(apriltag_id, opts \\ []) do
|
||||||
|
size = Keyword.get(opts, :size, @apriltag_size)
|
||||||
|
margin = Keyword.get(opts, :margin, div(size, 10))
|
||||||
|
|
||||||
|
# For now, create a placeholder square pattern
|
||||||
|
# In a real implementation, you'd generate the actual AprilTag pattern
|
||||||
|
square_size = size - (2 * margin)
|
||||||
|
|
||||||
|
"""
|
||||||
|
<svg width="#{size}" height="#{size + 30}" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<!-- White background -->
|
||||||
|
<rect width="#{size}" height="#{size + 30}" fill="white"/>
|
||||||
|
|
||||||
|
<!-- AprilTag placeholder (simplified) -->
|
||||||
|
<rect x="#{margin}" y="#{margin}" width="#{square_size}" height="#{square_size}"
|
||||||
|
fill="white" stroke="black" stroke-width="2"/>
|
||||||
|
|
||||||
|
<!-- Simplified tag pattern - in reality this would be the actual AprilTag -->
|
||||||
|
<rect x="#{margin + 10}" y="#{margin + 10}" width="#{square_size - 20}" height="#{square_size - 20}"
|
||||||
|
fill="black"/>
|
||||||
|
<rect x="#{margin + 20}" y="#{margin + 20}" width="#{square_size - 40}" height="#{square_size - 40}"
|
||||||
|
fill="white"/>
|
||||||
|
|
||||||
|
<!-- ID text below -->
|
||||||
|
<text x="#{size / 2}" y="#{size + 20}" text-anchor="middle"
|
||||||
|
font-family="Arial" font-size="14" font-weight="bold">
|
||||||
|
ID: #{String.pad_leading(to_string(apriltag_id), 3, "0")}
|
||||||
|
</text>
|
||||||
|
</svg>
|
||||||
|
"""
|
||||||
|
end
|
||||||
|
|
||||||
|
@doc """
|
||||||
|
Generates and saves all 587 AprilTag SVG files to the static directory.
|
||||||
|
|
||||||
|
This should be run once during setup to pre-generate all AprilTag images.
|
||||||
|
"""
|
||||||
|
def generate_all_apriltag_svgs(opts \\ []) do
|
||||||
|
static_dir = Path.join([
|
||||||
|
Application.app_dir(:components_elixir, "priv/static"),
|
||||||
|
"apriltags"
|
||||||
|
])
|
||||||
|
|
||||||
|
# Ensure directory exists
|
||||||
|
File.mkdir_p!(static_dir)
|
||||||
|
|
||||||
|
force_regenerate = Keyword.get(opts, :force_regenerate, false)
|
||||||
|
|
||||||
|
results =
|
||||||
|
all_apriltag_ids()
|
||||||
|
|> Task.async_stream(
|
||||||
|
fn apriltag_id ->
|
||||||
|
filename = "tag36h11_id_#{String.pad_leading(to_string(apriltag_id), 3, "0")}.svg"
|
||||||
|
file_path = Path.join(static_dir, filename)
|
||||||
|
|
||||||
|
if force_regenerate || !File.exists?(file_path) do
|
||||||
|
svg_content = generate_apriltag_svg(apriltag_id, opts)
|
||||||
|
|
||||||
|
case File.write(file_path, svg_content) do
|
||||||
|
:ok -> {:ok, apriltag_id, file_path}
|
||||||
|
{:error, reason} -> {:error, apriltag_id, reason}
|
||||||
|
end
|
||||||
|
else
|
||||||
|
{:ok, apriltag_id, file_path}
|
||||||
|
end
|
||||||
|
end,
|
||||||
|
timeout: :infinity,
|
||||||
|
max_concurrency: System.schedulers_online() * 2
|
||||||
|
)
|
||||||
|
|> Enum.map(fn {:ok, result} -> result end)
|
||||||
|
|
||||||
|
success_count = results |> Enum.count(&match?({:ok, _, _}, &1))
|
||||||
|
error_count = results |> Enum.count(&match?({:error, _, _}, &1))
|
||||||
|
|
||||||
|
%{
|
||||||
|
total: @tag36h11_count,
|
||||||
|
success: success_count,
|
||||||
|
errors: error_count,
|
||||||
|
results: results
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
@doc """
|
||||||
|
Cleans up AprilTag SVG file for a specific ID.
|
||||||
|
|
||||||
|
Should be called when storage locations are deleted to prevent orphaned files.
|
||||||
|
"""
|
||||||
|
def cleanup_apriltag_svg(apriltag_id) do
|
||||||
|
filename = "tag36h11_id_#{String.pad_leading(to_string(apriltag_id), 3, "0")}.svg"
|
||||||
|
file_path = Path.join([
|
||||||
|
Application.app_dir(:components_elixir, "priv/static/apriltags"),
|
||||||
|
filename
|
||||||
|
])
|
||||||
|
|
||||||
|
if File.exists?(file_path) do
|
||||||
|
File.rm(file_path)
|
||||||
|
else
|
||||||
|
:ok
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -24,11 +24,9 @@ defmodule ComponentsElixir.Inventory do
|
|||||||
processed_locations = compute_hierarchy_fields_batch(locations)
|
processed_locations = compute_hierarchy_fields_batch(locations)
|
||||||
|> Enum.sort_by(&{&1.level, &1.name})
|
|> Enum.sort_by(&{&1.level, &1.name})
|
||||||
|
|
||||||
# Ensure QR codes exist for all locations (in background)
|
# Ensure AprilTag SVGs exist for all locations
|
||||||
spawn(fn ->
|
spawn(fn ->
|
||||||
Enum.each(processed_locations, fn location ->
|
ComponentsElixir.AprilTag.generate_all_apriltag_svgs()
|
||||||
ComponentsElixir.QRCode.get_qr_image_url(location)
|
|
||||||
end)
|
|
||||||
end)
|
end)
|
||||||
|
|
||||||
processed_locations
|
processed_locations
|
||||||
@@ -109,11 +107,11 @@ defmodule ComponentsElixir.Inventory do
|
|||||||
end
|
end
|
||||||
|
|
||||||
@doc """
|
@doc """
|
||||||
Gets a storage location by QR code.
|
Gets a storage location by AprilTag ID.
|
||||||
"""
|
"""
|
||||||
def get_storage_location_by_qr_code(qr_code) do
|
def get_storage_location_by_apriltag_id(apriltag_id) do
|
||||||
StorageLocation
|
StorageLocation
|
||||||
|> where([sl], sl.qr_code == ^qr_code)
|
|> where([sl], sl.apriltag_id == ^apriltag_id)
|
||||||
|> preload(:parent)
|
|> preload(:parent)
|
||||||
|> Repo.one()
|
|> Repo.one()
|
||||||
|> case do
|
|> case do
|
||||||
@@ -138,8 +136,6 @@ defmodule ComponentsElixir.Inventory do
|
|||||||
|
|
||||||
case result do
|
case result do
|
||||||
{:ok, location} ->
|
{:ok, location} ->
|
||||||
# Automatically generate QR code image
|
|
||||||
spawn(fn -> ComponentsElixir.QRCode.get_qr_image_url(location) end)
|
|
||||||
{:ok, location}
|
{:ok, location}
|
||||||
error ->
|
error ->
|
||||||
error
|
error
|
||||||
@@ -159,8 +155,6 @@ defmodule ComponentsElixir.Inventory do
|
|||||||
|
|
||||||
case result do
|
case result do
|
||||||
{:ok, updated_location} ->
|
{:ok, updated_location} ->
|
||||||
# Automatically regenerate QR code image if name or hierarchy changed
|
|
||||||
spawn(fn -> ComponentsElixir.QRCode.get_qr_image_url(updated_location, force_regenerate: true) end)
|
|
||||||
{:ok, updated_location}
|
{:ok, updated_location}
|
||||||
error ->
|
error ->
|
||||||
error
|
error
|
||||||
@@ -171,9 +165,6 @@ defmodule ComponentsElixir.Inventory do
|
|||||||
Deletes a storage location.
|
Deletes a storage location.
|
||||||
"""
|
"""
|
||||||
def delete_storage_location(%StorageLocation{} = storage_location) do
|
def delete_storage_location(%StorageLocation{} = storage_location) do
|
||||||
# Clean up QR code image before deleting
|
|
||||||
ComponentsElixir.QRCode.cleanup_qr_image(storage_location.id)
|
|
||||||
|
|
||||||
Repo.delete(storage_location)
|
Repo.delete(storage_location)
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -185,17 +176,17 @@ defmodule ComponentsElixir.Inventory do
|
|||||||
end
|
end
|
||||||
|
|
||||||
@doc """
|
@doc """
|
||||||
Parses a QR code string and returns storage location information.
|
Parses an AprilTag ID and returns storage location information.
|
||||||
"""
|
"""
|
||||||
def parse_qr_code(qr_string) do
|
def parse_apriltag_id(apriltag_id) when is_integer(apriltag_id) do
|
||||||
case get_storage_location_by_qr_code(qr_string) do
|
case get_storage_location_by_apriltag_id(apriltag_id) do
|
||||||
nil ->
|
nil ->
|
||||||
{:error, :not_found}
|
{:error, :not_found}
|
||||||
location ->
|
location ->
|
||||||
{:ok, %{
|
{:ok, %{
|
||||||
type: :storage_location,
|
type: :storage_location,
|
||||||
location: location,
|
location: location,
|
||||||
qr_code: qr_string
|
apriltag_id: apriltag_id
|
||||||
}}
|
}}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -7,13 +7,14 @@ defmodule ComponentsElixir.Inventory.StorageLocation do
|
|||||||
"""
|
"""
|
||||||
use Ecto.Schema
|
use Ecto.Schema
|
||||||
import Ecto.Changeset
|
import Ecto.Changeset
|
||||||
|
import Ecto.Query
|
||||||
|
|
||||||
alias ComponentsElixir.Inventory.{StorageLocation, Component}
|
alias ComponentsElixir.Inventory.{StorageLocation, Component}
|
||||||
|
|
||||||
schema "storage_locations" do
|
schema "storage_locations" do
|
||||||
field :name, :string
|
field :name, :string
|
||||||
field :description, :string
|
field :description, :string
|
||||||
field :qr_code, :string
|
field :apriltag_id, :integer
|
||||||
field :is_active, :boolean, default: true
|
field :is_active, :boolean, default: true
|
||||||
|
|
||||||
# Computed/virtual fields - not stored in database
|
# Computed/virtual fields - not stored in database
|
||||||
@@ -31,13 +32,14 @@ defmodule ComponentsElixir.Inventory.StorageLocation do
|
|||||||
@doc false
|
@doc false
|
||||||
def changeset(storage_location, attrs) do
|
def changeset(storage_location, attrs) do
|
||||||
storage_location
|
storage_location
|
||||||
|> cast(attrs, [:name, :description, :parent_id, :is_active])
|
|> cast(attrs, [:name, :description, :parent_id, :is_active, :apriltag_id])
|
||||||
|> validate_required([:name])
|
|> validate_required([:name])
|
||||||
|> validate_length(:name, min: 1, max: 100)
|
|> validate_length(:name, min: 1, max: 100)
|
||||||
|> validate_length(:description, max: 500)
|
|> validate_length(:description, max: 500)
|
||||||
|
|> validate_apriltag_id()
|
||||||
|> foreign_key_constraint(:parent_id)
|
|> foreign_key_constraint(:parent_id)
|
||||||
|> validate_no_circular_reference()
|
|> validate_no_circular_reference()
|
||||||
|> put_qr_code()
|
|> put_apriltag_id()
|
||||||
end
|
end
|
||||||
|
|
||||||
# Prevent circular references (location being its own ancestor)
|
# Prevent circular references (location being its own ancestor)
|
||||||
@@ -79,19 +81,24 @@ defmodule ComponentsElixir.Inventory.StorageLocation do
|
|||||||
end
|
end
|
||||||
|
|
||||||
@doc """
|
@doc """
|
||||||
Returns the QR code format for this storage location.
|
Returns the AprilTag format for this storage location.
|
||||||
Format: SL:{level}:{qr_code}:{parent_qr_or_ROOT}
|
Returns the AprilTag ID that corresponds to this location.
|
||||||
"""
|
"""
|
||||||
def qr_format(storage_location, parent \\ nil) do
|
def apriltag_format(storage_location) do
|
||||||
parent_code = if parent, do: parent.qr_code, else: "ROOT"
|
storage_location.apriltag_id
|
||||||
"SL:#{storage_location.level}:#{storage_location.qr_code}:#{parent_code}"
|
|
||||||
end
|
end
|
||||||
|
|
||||||
# Private functions for changeset processing
|
# Private functions for changeset processing
|
||||||
|
|
||||||
defp put_qr_code(changeset) do
|
defp validate_apriltag_id(changeset) do
|
||||||
case get_field(changeset, :qr_code) do
|
changeset
|
||||||
nil -> put_change(changeset, :qr_code, generate_qr_code())
|
|> validate_number(:apriltag_id, greater_than_or_equal_to: 0, less_than_or_equal_to: 586)
|
||||||
|
|> unique_constraint(:apriltag_id, message: "AprilTag ID is already in use")
|
||||||
|
end
|
||||||
|
|
||||||
|
defp put_apriltag_id(changeset) do
|
||||||
|
case get_field(changeset, :apriltag_id) do
|
||||||
|
nil -> put_change(changeset, :apriltag_id, get_next_available_apriltag_id())
|
||||||
_ -> changeset
|
_ -> changeset
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -118,16 +125,22 @@ defmodule ComponentsElixir.Inventory.StorageLocation do
|
|||||||
"#{compute_path(parent)}/#{name}"
|
"#{compute_path(parent)}/#{name}"
|
||||||
end
|
end
|
||||||
|
|
||||||
defp generate_qr_code do
|
defp get_next_available_apriltag_id do
|
||||||
# Generate a unique 6-character alphanumeric code
|
# Get all used AprilTag IDs
|
||||||
chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
|
used_ids = ComponentsElixir.Repo.all(
|
||||||
|
from sl in ComponentsElixir.Inventory.StorageLocation,
|
||||||
|
where: not is_nil(sl.apriltag_id),
|
||||||
|
select: sl.apriltag_id
|
||||||
|
)
|
||||||
|
|
||||||
1..6
|
# Find the first available ID (0-586)
|
||||||
|> Enum.map(fn _ ->
|
0..586
|
||||||
chars
|
|> Enum.find(&(&1 not in used_ids))
|
||||||
|> String.graphemes()
|
|> case do
|
||||||
|> Enum.random()
|
nil ->
|
||||||
end)
|
# All IDs are used - this should be handled at the application level
|
||||||
|> Enum.join()
|
raise "All AprilTag IDs are in use"
|
||||||
|
id -> id
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ defmodule ComponentsElixirWeb do
|
|||||||
those modules here.
|
those modules here.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def static_paths, do: ~w(assets fonts images user_generated favicon.ico robots.txt)
|
def static_paths, do: ~w(assets fonts images user_generated apriltags favicon.ico robots.txt)
|
||||||
|
|
||||||
def router do
|
def router do
|
||||||
quote do
|
quote do
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
defmodule ComponentsElixirWeb.StorageLocationsLive do
|
defmodule ComponentsElixirWeb.StorageLocationsLive do
|
||||||
@moduledoc """
|
@moduledoc """
|
||||||
LiveView for managing storage locations and QR codes.
|
LiveView for managing storage locations and AprilTags.
|
||||||
"""
|
"""
|
||||||
use ComponentsElixirWeb, :live_view
|
use ComponentsElixirWeb, :live_view
|
||||||
|
|
||||||
alias ComponentsElixir.{Inventory, Auth}
|
alias ComponentsElixir.{Inventory, Auth}
|
||||||
alias ComponentsElixir.Inventory.StorageLocation
|
alias ComponentsElixir.Inventory.StorageLocation
|
||||||
alias ComponentsElixir.QRCode
|
alias ComponentsElixir.AprilTag
|
||||||
|
|
||||||
@impl true
|
@impl true
|
||||||
def mount(_params, session, socket) do
|
def mount(_params, session, socket) do
|
||||||
@@ -24,8 +24,8 @@ defmodule ComponentsElixirWeb.StorageLocationsLive do
|
|||||||
|> assign(:show_edit_form, false)
|
|> assign(:show_edit_form, false)
|
||||||
|> assign(:editing_location, nil)
|
|> assign(:editing_location, nil)
|
||||||
|> assign(:form, nil)
|
|> assign(:form, nil)
|
||||||
|> assign(:qr_scanner_open, false)
|
|> assign(:apriltag_scanner_open, false)
|
||||||
|> assign(:scanned_codes, [])
|
|> assign(:scanned_tags, [])
|
||||||
|> assign(:page_title, "Storage Location Management")}
|
|> assign(:page_title, "Storage Location Management")}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -38,7 +38,9 @@ defmodule ComponentsElixirWeb.StorageLocationsLive do
|
|||||||
{:noreply,
|
{:noreply,
|
||||||
socket
|
socket
|
||||||
|> assign(:show_add_form, true)
|
|> assign(:show_add_form, true)
|
||||||
|> assign(:form, form)}
|
|> assign(:form, form)
|
||||||
|
|> assign(:available_apriltag_ids, AprilTag.available_apriltag_ids())
|
||||||
|
|> assign(:apriltag_mode, "auto")}
|
||||||
end
|
end
|
||||||
|
|
||||||
def handle_event("hide_add_form", _params, socket) do
|
def handle_event("hide_add_form", _params, socket) do
|
||||||
@@ -64,7 +66,9 @@ defmodule ComponentsElixirWeb.StorageLocationsLive do
|
|||||||
socket
|
socket
|
||||||
|> assign(:show_edit_form, true)
|
|> assign(:show_edit_form, true)
|
||||||
|> assign(:editing_location, location)
|
|> assign(:editing_location, location)
|
||||||
|> assign(:form, form)}
|
|> assign(:form, form)
|
||||||
|
|> assign(:available_apriltag_ids, AprilTag.available_apriltag_ids())
|
||||||
|
|> assign(:edit_apriltag_mode, "keep")}
|
||||||
end
|
end
|
||||||
|
|
||||||
def handle_event("hide_edit_form", _params, socket) do
|
def handle_event("hide_edit_form", _params, socket) do
|
||||||
@@ -76,7 +80,32 @@ defmodule ComponentsElixirWeb.StorageLocationsLive do
|
|||||||
end
|
end
|
||||||
|
|
||||||
def handle_event("save_location", %{"storage_location" => location_params}, socket) do
|
def handle_event("save_location", %{"storage_location" => location_params}, socket) do
|
||||||
case Inventory.create_storage_location(location_params) do
|
# Process AprilTag assignment based on mode
|
||||||
|
processed_params = case socket.assigns.apriltag_mode do
|
||||||
|
"none" ->
|
||||||
|
# Remove any apriltag_id from params to ensure it's nil
|
||||||
|
Map.delete(location_params, "apriltag_id")
|
||||||
|
|
||||||
|
"auto" ->
|
||||||
|
# Auto-assign next available AprilTag ID
|
||||||
|
case AprilTag.next_available_apriltag_id() do
|
||||||
|
nil ->
|
||||||
|
# No available IDs, proceed without AprilTag
|
||||||
|
Map.delete(location_params, "apriltag_id")
|
||||||
|
apriltag_id ->
|
||||||
|
Map.put(location_params, "apriltag_id", apriltag_id)
|
||||||
|
end
|
||||||
|
|
||||||
|
"manual" ->
|
||||||
|
# Use the manually entered apriltag_id (validation will be handled by changeset)
|
||||||
|
location_params
|
||||||
|
|
||||||
|
_ ->
|
||||||
|
# Fallback: remove apriltag_id
|
||||||
|
Map.delete(location_params, "apriltag_id")
|
||||||
|
end
|
||||||
|
|
||||||
|
case Inventory.create_storage_location(processed_params) do
|
||||||
{:ok, _location} ->
|
{:ok, _location} ->
|
||||||
{:noreply,
|
{:noreply,
|
||||||
socket
|
socket
|
||||||
@@ -121,57 +150,86 @@ defmodule ComponentsElixirWeb.StorageLocationsLive do
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def handle_event("open_qr_scanner", _params, socket) do
|
def handle_event("open_apriltag_scanner", _params, socket) do
|
||||||
{:noreply, assign(socket, :qr_scanner_open, true)}
|
{:noreply, assign(socket, :apriltag_scanner_open, true)}
|
||||||
end
|
end
|
||||||
|
|
||||||
def handle_event("close_qr_scanner", _params, socket) do
|
def handle_event("close_apriltag_scanner", _params, socket) do
|
||||||
{:noreply, assign(socket, :qr_scanner_open, false)}
|
{:noreply, assign(socket, :apriltag_scanner_open, false)}
|
||||||
end
|
end
|
||||||
|
|
||||||
def handle_event("qr_scanned", %{"code" => code}, socket) do
|
def handle_event("apriltag_scanned", %{"apriltag_id" => apriltag_id_str}, socket) do
|
||||||
case QRCode.parse_qr_data(code) do
|
case Integer.parse(apriltag_id_str) do
|
||||||
{:ok, parsed} ->
|
{apriltag_id, ""} when apriltag_id >= 0 and apriltag_id <= 586 ->
|
||||||
case Inventory.get_storage_location_by_qr_code(parsed.code) do
|
case Inventory.get_storage_location_by_apriltag_id(apriltag_id) do
|
||||||
nil ->
|
nil ->
|
||||||
{:noreply, put_flash(socket, :error, "Storage location not found for QR code: #{code}")}
|
{:noreply, put_flash(socket, :error, "Storage location not found for AprilTag ID: #{apriltag_id}")}
|
||||||
|
|
||||||
location ->
|
location ->
|
||||||
scanned_codes = [%{code: code, location: location} | socket.assigns.scanned_codes]
|
scanned_tags = [%{apriltag_id: apriltag_id, location: location} | socket.assigns.scanned_tags]
|
||||||
|
|
||||||
{:noreply,
|
{:noreply,
|
||||||
socket
|
socket
|
||||||
|> assign(:scanned_codes, scanned_codes)
|
|> assign(:scanned_tags, scanned_tags)
|
||||||
|> put_flash(:info, "Scanned: #{location.path}")}
|
|> put_flash(:info, "Scanned: #{location.path}")}
|
||||||
end
|
end
|
||||||
|
|
||||||
{:error, reason} ->
|
_ ->
|
||||||
{:noreply, put_flash(socket, :error, "Invalid QR code: #{reason}")}
|
{:noreply, put_flash(socket, :error, "Invalid AprilTag ID: #{apriltag_id_str}")}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def handle_event("clear_scanned", _params, socket) do
|
def handle_event("clear_scanned", _params, socket) do
|
||||||
{:noreply, assign(socket, :scanned_codes, [])}
|
{:noreply, assign(socket, :scanned_tags, [])}
|
||||||
end
|
end
|
||||||
|
|
||||||
def handle_event("download_qr", %{"id" => id}, socket) do
|
def handle_event("set_apriltag_mode", %{"mode" => mode}, socket) do
|
||||||
|
{:noreply, assign(socket, :apriltag_mode, mode)}
|
||||||
|
end
|
||||||
|
|
||||||
|
def handle_event("set_edit_apriltag_mode", %{"mode" => mode}, socket) do
|
||||||
|
# Clear the apriltag_id field when switching modes
|
||||||
|
form = case mode do
|
||||||
|
"remove" ->
|
||||||
|
socket.assigns.form
|
||||||
|
|> Phoenix.Component.to_form()
|
||||||
|
|> Map.put(:params, Map.put(socket.assigns.form.params || %{}, "apriltag_id", nil))
|
||||||
|
"keep" ->
|
||||||
|
current_id = socket.assigns.editing_location.apriltag_id
|
||||||
|
socket.assigns.form
|
||||||
|
|> Phoenix.Component.to_form()
|
||||||
|
|> Map.put(:params, Map.put(socket.assigns.form.params || %{}, "apriltag_id", current_id))
|
||||||
|
_ ->
|
||||||
|
socket.assigns.form
|
||||||
|
end
|
||||||
|
|
||||||
|
{:noreply,
|
||||||
|
socket
|
||||||
|
|> assign(:edit_apriltag_mode, mode)
|
||||||
|
|> assign(:form, form)}
|
||||||
|
end
|
||||||
|
|
||||||
|
def handle_event("download_apriltag", %{"id" => id}, socket) do
|
||||||
case Inventory.get_storage_location!(id) do
|
case Inventory.get_storage_location!(id) do
|
||||||
|
%{apriltag_id: nil} ->
|
||||||
|
{:noreply, put_flash(socket, :error, "No AprilTag assigned to this location")}
|
||||||
|
|
||||||
location ->
|
location ->
|
||||||
case QRCode.generate_qr_image(location) do
|
case AprilTag.get_apriltag_url(location) do
|
||||||
{:ok, png_data} ->
|
nil ->
|
||||||
filename = "#{location.name |> String.replace(" ", "_")}_QR.png"
|
{:noreply, put_flash(socket, :error, "Failed to get AprilTag URL")}
|
||||||
|
|
||||||
|
apriltag_url ->
|
||||||
|
filename = "#{location.name |> String.replace(" ", "_")}_AprilTag_#{location.apriltag_id}.svg"
|
||||||
|
|
||||||
# Send file download to browser
|
# Send file download to browser
|
||||||
{:noreply,
|
{:noreply,
|
||||||
socket
|
socket
|
||||||
|> push_event("download_file", %{
|
|> push_event("download_apriltag", %{
|
||||||
filename: filename,
|
filename: filename,
|
||||||
data: Base.encode64(png_data),
|
url: apriltag_url,
|
||||||
mime_type: "image/png"
|
apriltag_id: location.apriltag_id
|
||||||
})}
|
})}
|
||||||
|
|
||||||
{:error, _reason} ->
|
|
||||||
{:noreply, put_flash(socket, :error, "Failed to generate QR code")}
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -230,8 +288,8 @@ defmodule ComponentsElixirWeb.StorageLocationsLive do
|
|||||||
Inventory.count_components_in_storage_location(location_id)
|
Inventory.count_components_in_storage_location(location_id)
|
||||||
end
|
end
|
||||||
|
|
||||||
defp get_qr_image_url(location) do
|
defp get_apriltag_url(location) do
|
||||||
QRCode.get_qr_image_url(location)
|
AprilTag.get_apriltag_url(location)
|
||||||
end
|
end
|
||||||
|
|
||||||
# Component for rendering individual storage location items with QR code support
|
# Component for rendering individual storage location items with QR code support
|
||||||
@@ -284,21 +342,21 @@ defmodule ComponentsElixirWeb.StorageLocationsLive do
|
|||||||
<p class="text-xs text-gray-400">
|
<p class="text-xs text-gray-400">
|
||||||
{count_components_in_location(@location.id)} components
|
{count_components_in_location(@location.id)} components
|
||||||
</p>
|
</p>
|
||||||
<%= if @location.qr_code do %>
|
<%= if @location.apriltag_id do %>
|
||||||
<span class="text-xs bg-gray-100 text-gray-600 px-2 py-1 rounded">
|
<span class="text-xs bg-gray-100 text-gray-600 px-2 py-1 rounded">
|
||||||
QR: {@location.qr_code}
|
AprilTag: {@location.apriltag_id}
|
||||||
</span>
|
</span>
|
||||||
<% end %>
|
<% end %>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<%= if @location.qr_code do %>
|
<%= if @location.apriltag_id do %>
|
||||||
<div class="flex items-center space-x-3">
|
<div class="flex items-center space-x-3">
|
||||||
<%= if get_qr_image_url(@location) do %>
|
<%= if get_apriltag_url(@location) do %>
|
||||||
<div class="qr-code-container flex-shrink-0">
|
<div class="apriltag-container flex-shrink-0">
|
||||||
<img
|
<img
|
||||||
src={get_qr_image_url(@location)}
|
src={get_apriltag_url(@location)}
|
||||||
alt={"QR Code for #{@location.name}"}
|
alt={"AprilTag for #{@location.name}"}
|
||||||
class="w-16 h-16 border border-gray-200 rounded bg-white"
|
class="w-16 h-auto border border-gray-200 rounded bg-white"
|
||||||
onerror="this.style.display='none'"
|
onerror="this.style.display='none'"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
@@ -308,10 +366,10 @@ defmodule ComponentsElixirWeb.StorageLocationsLive do
|
|||||||
</div>
|
</div>
|
||||||
<% end %>
|
<% end %>
|
||||||
<button
|
<button
|
||||||
phx-click="download_qr"
|
phx-click="download_apriltag"
|
||||||
phx-value-id={@location.id}
|
phx-value-id={@location.id}
|
||||||
class="inline-flex items-center px-3 py-1.5 border border-gray-300 rounded-md shadow-sm text-sm font-medium text-gray-700 bg-white hover:bg-gray-50 flex-shrink-0"
|
class="inline-flex items-center px-3 py-1.5 border border-gray-300 rounded-md shadow-sm text-sm font-medium text-gray-700 bg-white hover:bg-gray-50 flex-shrink-0"
|
||||||
title="Download QR Code"
|
title="Download AprilTag"
|
||||||
>
|
>
|
||||||
<.icon name="hero-arrow-down-tray" class="w-4 h-4 mr-1.5" />
|
<.icon name="hero-arrow-down-tray" class="w-4 h-4 mr-1.5" />
|
||||||
Download
|
Download
|
||||||
@@ -427,6 +485,76 @@ defmodule ComponentsElixirWeb.StorageLocationsLive do
|
|||||||
<.input field={@form[:description]} type="textarea" />
|
<.input field={@form[:description]} type="textarea" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<label class="block text-sm font-medium text-gray-700">AprilTag ID (Optional)</label>
|
||||||
|
<div class="space-y-2">
|
||||||
|
<div class="flex items-center space-x-2">
|
||||||
|
<input
|
||||||
|
type="radio"
|
||||||
|
name="apriltag_assignment"
|
||||||
|
value="none"
|
||||||
|
id="apriltag_none"
|
||||||
|
checked={@apriltag_mode == "none"}
|
||||||
|
class="h-4 w-4 text-indigo-600 focus:ring-indigo-500 border-gray-300"
|
||||||
|
phx-click="set_apriltag_mode"
|
||||||
|
phx-value-mode="none"
|
||||||
|
/>
|
||||||
|
<label for="apriltag_none" class="text-sm text-gray-700">
|
||||||
|
No AprilTag assignment
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<div class="flex items-center space-x-2">
|
||||||
|
<input
|
||||||
|
type="radio"
|
||||||
|
name="apriltag_assignment"
|
||||||
|
value="auto"
|
||||||
|
id="apriltag_auto"
|
||||||
|
checked={@apriltag_mode == "auto"}
|
||||||
|
class="h-4 w-4 text-indigo-600 focus:ring-indigo-500 border-gray-300"
|
||||||
|
phx-click="set_apriltag_mode"
|
||||||
|
phx-value-mode="auto"
|
||||||
|
/>
|
||||||
|
<label for="apriltag_auto" class="text-sm text-gray-700">
|
||||||
|
Auto-assign next available ID
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<div class="flex items-center space-x-2">
|
||||||
|
<input
|
||||||
|
type="radio"
|
||||||
|
name="apriltag_assignment"
|
||||||
|
value="manual"
|
||||||
|
id="apriltag_manual"
|
||||||
|
checked={@apriltag_mode == "manual"}
|
||||||
|
class="h-4 w-4 text-indigo-600 focus:ring-indigo-500 border-gray-300"
|
||||||
|
phx-click="set_apriltag_mode"
|
||||||
|
phx-value-mode="manual"
|
||||||
|
/>
|
||||||
|
<label for="apriltag_manual" class="text-sm text-gray-700">
|
||||||
|
Choose specific ID
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<%= if @apriltag_mode == "manual" do %>
|
||||||
|
<div class="ml-6 space-y-2">
|
||||||
|
<.input
|
||||||
|
field={@form[:apriltag_id]}
|
||||||
|
type="number"
|
||||||
|
min="0"
|
||||||
|
max="586"
|
||||||
|
placeholder="Enter ID (0-586)"
|
||||||
|
class="w-32"
|
||||||
|
/>
|
||||||
|
<div class="text-xs text-gray-500">
|
||||||
|
Available IDs: <%= length(@available_apriltag_ids) %> of 587
|
||||||
|
<%= if length(@available_apriltag_ids) < 20 do %>
|
||||||
|
<br/>Next available: <%= @available_apriltag_ids |> Enum.take(10) |> Enum.join(", ") %>
|
||||||
|
<%= if length(@available_apriltag_ids) > 10, do: "..." %>
|
||||||
|
<% end %>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<% end %>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="flex justify-end space-x-3 pt-4">
|
<div class="flex justify-end space-x-3 pt-4">
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
@@ -483,6 +611,75 @@ defmodule ComponentsElixirWeb.StorageLocationsLive do
|
|||||||
<.input field={@form[:description]} type="textarea" />
|
<.input field={@form[:description]} type="textarea" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<label class="block text-sm font-medium text-gray-700">AprilTag ID</label>
|
||||||
|
<div class="space-y-2">
|
||||||
|
<div class="flex items-center space-x-2">
|
||||||
|
<input
|
||||||
|
type="radio"
|
||||||
|
name="edit_apriltag_assignment"
|
||||||
|
value="keep"
|
||||||
|
id="edit_apriltag_keep"
|
||||||
|
checked={@edit_apriltag_mode == "keep"}
|
||||||
|
class="h-4 w-4 text-indigo-600 focus:ring-indigo-500 border-gray-300"
|
||||||
|
phx-click="set_edit_apriltag_mode"
|
||||||
|
phx-value-mode="keep"
|
||||||
|
/>
|
||||||
|
<label for="edit_apriltag_keep" class="text-sm text-gray-700">
|
||||||
|
Keep current assignment
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<div class="flex items-center space-x-2">
|
||||||
|
<input
|
||||||
|
type="radio"
|
||||||
|
name="edit_apriltag_assignment"
|
||||||
|
value="change"
|
||||||
|
id="edit_apriltag_change"
|
||||||
|
checked={@edit_apriltag_mode == "change"}
|
||||||
|
class="h-4 w-4 text-indigo-600 focus:ring-indigo-500 border-gray-300"
|
||||||
|
phx-click="set_edit_apriltag_mode"
|
||||||
|
phx-value-mode="change"
|
||||||
|
/>
|
||||||
|
<label for="edit_apriltag_change" class="text-sm text-gray-700">
|
||||||
|
Change to different ID
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<div class="flex items-center space-x-2">
|
||||||
|
<input
|
||||||
|
type="radio"
|
||||||
|
name="edit_apriltag_assignment"
|
||||||
|
value="remove"
|
||||||
|
id="edit_apriltag_remove"
|
||||||
|
checked={@edit_apriltag_mode == "remove"}
|
||||||
|
class="h-4 w-4 text-indigo-600 focus:ring-indigo-500 border-gray-300"
|
||||||
|
phx-click="set_edit_apriltag_mode"
|
||||||
|
phx-value-mode="remove"
|
||||||
|
/>
|
||||||
|
<label for="edit_apriltag_remove" class="text-sm text-gray-700">
|
||||||
|
Remove AprilTag assignment
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<%= if @edit_apriltag_mode == "change" do %>
|
||||||
|
<div class="ml-6 space-y-2">
|
||||||
|
<.input
|
||||||
|
field={@form[:apriltag_id]}
|
||||||
|
type="number"
|
||||||
|
min="0"
|
||||||
|
max="586"
|
||||||
|
placeholder="Enter new ID (0-586)"
|
||||||
|
class="w-32"
|
||||||
|
/>
|
||||||
|
<div class="text-xs text-gray-500">
|
||||||
|
Available IDs: <%= length(@available_apriltag_ids) %> of 587
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<% end %>
|
||||||
|
<p class="text-xs text-gray-500 mt-1">
|
||||||
|
Current: <%= if @editing_location.apriltag_id, do: "ID #{@editing_location.apriltag_id}", else: "None" %>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="flex justify-end space-x-3 pt-4">
|
<div class="flex justify-end space-x-3 pt-4">
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
@@ -504,43 +701,43 @@ defmodule ComponentsElixirWeb.StorageLocationsLive do
|
|||||||
</div>
|
</div>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|
||||||
<!-- QR Scanner Modal -->
|
<!-- AprilTag Scanner Modal -->
|
||||||
<%= if @qr_scanner_open do %>
|
<%= if @apriltag_scanner_open do %>
|
||||||
<div class="fixed inset-0 bg-gray-600 bg-opacity-50 overflow-y-auto h-full w-full z-50">
|
<div class="fixed inset-0 bg-gray-600 bg-opacity-50 overflow-y-auto h-full w-full z-50">
|
||||||
<div class="relative top-10 mx-auto p-5 border w-11/12 md:w-1/2 shadow-lg rounded-md bg-white">
|
<div class="relative top-10 mx-auto p-5 border w-11/12 md:w-1/2 shadow-lg rounded-md bg-white">
|
||||||
<div class="mt-3">
|
<div class="mt-3">
|
||||||
<div class="flex justify-between items-center mb-4">
|
<div class="flex justify-between items-center mb-4">
|
||||||
<h3 class="text-lg font-medium text-gray-900">QR Code Scanner</h3>
|
<h3 class="text-lg font-medium text-gray-900">AprilTag Scanner</h3>
|
||||||
<button
|
<button
|
||||||
phx-click="close_qr_scanner"
|
phx-click="close_apriltag_scanner"
|
||||||
class="text-gray-400 hover:text-gray-600"
|
class="text-gray-400 hover:text-gray-600"
|
||||||
>
|
>
|
||||||
<.icon name="hero-x-mark" class="w-6 h-6" />
|
<.icon name="hero-x-mark" class="w-6 h-6" />
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- QR Scanner Interface -->
|
<!-- AprilTag Scanner Interface -->
|
||||||
<div class="border-2 border-dashed border-gray-300 rounded-lg p-6 text-center">
|
<div class="border-2 border-dashed border-gray-300 rounded-lg p-6 text-center">
|
||||||
<.icon name="hero-qr-code" class="mx-auto h-12 w-12 text-gray-400" />
|
<.icon name="hero-qr-code" class="mx-auto h-12 w-12 text-gray-400" />
|
||||||
<p class="mt-2 text-sm text-gray-600">Camera QR scanner would go here</p>
|
<p class="mt-2 text-sm text-gray-600">Camera AprilTag scanner would go here</p>
|
||||||
<p class="text-xs text-gray-500 mt-1">In a real implementation, this would use JavaScript QR scanning</p>
|
<p class="text-xs text-gray-500 mt-1">In a real implementation, this would use JavaScript AprilTag detection</p>
|
||||||
|
|
||||||
<!-- Test buttons for demo -->
|
<!-- Test buttons for demo -->
|
||||||
<div class="mt-4 space-y-2">
|
<div class="mt-4 space-y-2">
|
||||||
<p class="text-sm font-medium text-gray-700">Test with sample codes:</p>
|
<p class="text-sm font-medium text-gray-700">Test with sample AprilTag IDs:</p>
|
||||||
<button
|
<button
|
||||||
phx-click="qr_scanned"
|
phx-click="apriltag_scanned"
|
||||||
phx-value-code="SL:0:1MTKDM:ROOT"
|
phx-value-apriltag_id="0"
|
||||||
class="block w-full px-3 py-2 text-sm bg-gray-100 hover:bg-gray-200 rounded"
|
class="block w-full px-3 py-2 text-sm bg-gray-100 hover:bg-gray-200 rounded"
|
||||||
>
|
>
|
||||||
Scan "Shelf A"
|
Scan AprilTag ID 0
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
phx-click="qr_scanned"
|
phx-click="apriltag_scanned"
|
||||||
phx-value-code="SL:1:VDI701:1MTKDM"
|
phx-value-apriltag_id="1"
|
||||||
class="block w-full px-3 py-2 text-sm bg-gray-100 hover:bg-gray-200 rounded"
|
class="block w-full px-3 py-2 text-sm bg-gray-100 hover:bg-gray-200 rounded"
|
||||||
>
|
>
|
||||||
Scan "Drawer 1"
|
Scan AprilTag ID 1
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -549,8 +746,8 @@ defmodule ComponentsElixirWeb.StorageLocationsLive do
|
|||||||
</div>
|
</div>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|
||||||
<!-- Scanned Codes Display -->
|
<!-- Scanned Tags Display -->
|
||||||
<%= if length(@scanned_codes) > 0 do %>
|
<%= if length(@scanned_tags) > 0 do %>
|
||||||
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-4">
|
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-4">
|
||||||
<div class="bg-green-50 border border-green-200 rounded-lg p-4">
|
<div class="bg-green-50 border border-green-200 rounded-lg p-4">
|
||||||
<div class="flex justify-between items-center mb-2">
|
<div class="flex justify-between items-center mb-2">
|
||||||
@@ -563,10 +760,10 @@ defmodule ComponentsElixirWeb.StorageLocationsLive do
|
|||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="space-y-2">
|
<div class="space-y-2">
|
||||||
<div :for={scan <- @scanned_codes} class="flex items-center justify-between bg-white p-2 rounded border">
|
<div :for={scan <- @scanned_tags} class="flex items-center justify-between bg-white p-2 rounded border">
|
||||||
<div>
|
<div>
|
||||||
<span class="font-medium text-gray-900">{location_display_name(scan.location)}</span>
|
<span class="font-medium text-gray-900">{location_display_name(scan.location)}</span>
|
||||||
<span class="text-sm text-gray-600 ml-2">({scan.code})</span>
|
<span class="text-sm text-gray-600 ml-2">(AprilTag ID {scan.apriltag_id})</span>
|
||||||
</div>
|
</div>
|
||||||
<span class="text-xs text-green-600 bg-green-100 px-2 py-1 rounded">
|
<span class="text-xs text-green-600 bg-green-100 px-2 py-1 rounded">
|
||||||
Level {scan.location.level}
|
Level {scan.location.level}
|
||||||
@@ -582,7 +779,7 @@ defmodule ComponentsElixirWeb.StorageLocationsLive do
|
|||||||
<div class="bg-white shadow overflow-hidden sm:rounded-md">
|
<div class="bg-white shadow overflow-hidden sm:rounded-md">
|
||||||
<div class="px-6 py-4 border-b border-gray-200">
|
<div class="px-6 py-4 border-b border-gray-200">
|
||||||
<h2 class="text-lg font-medium text-gray-900">Storage Location Hierarchy</h2>
|
<h2 class="text-lg font-medium text-gray-900">Storage Location Hierarchy</h2>
|
||||||
<p class="text-sm text-gray-500 mt-1">Manage your physical storage locations and QR codes</p>
|
<p class="text-sm text-gray-500 mt-1">Manage your physical storage locations and AprilTags</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<%= if Enum.empty?(@storage_locations) do %>
|
<%= if Enum.empty?(@storage_locations) do %>
|
||||||
|
|||||||
57
lib/mix/tasks/apriltag.generate_all.ex
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
defmodule Mix.Tasks.Apriltag.GenerateAll do
|
||||||
|
@moduledoc """
|
||||||
|
Generates all 587 AprilTag tag36h11 SVG files for the storage system.
|
||||||
|
|
||||||
|
## Examples
|
||||||
|
|
||||||
|
mix apriltag.generate_all
|
||||||
|
mix apriltag.generate_all --force
|
||||||
|
|
||||||
|
Options:
|
||||||
|
* `--force` - Regenerate all files even if they already exist
|
||||||
|
"""
|
||||||
|
use Mix.Task
|
||||||
|
|
||||||
|
@shortdoc "Generate all AprilTag SVG files"
|
||||||
|
|
||||||
|
def run(args) do
|
||||||
|
{opts, [], []} = OptionParser.parse(args, strict: [force: :boolean])
|
||||||
|
force_regenerate = Keyword.get(opts, :force, false)
|
||||||
|
|
||||||
|
Mix.Task.run("app.start")
|
||||||
|
|
||||||
|
IO.puts("Generating AprilTag SVG files...")
|
||||||
|
IO.puts("Force regenerate: #{force_regenerate}")
|
||||||
|
|
||||||
|
start_time = System.monotonic_time(:millisecond)
|
||||||
|
|
||||||
|
result = ComponentsElixir.AprilTag.generate_all_apriltag_svgs(
|
||||||
|
force_regenerate: force_regenerate
|
||||||
|
)
|
||||||
|
|
||||||
|
end_time = System.monotonic_time(:millisecond)
|
||||||
|
duration = end_time - start_time
|
||||||
|
|
||||||
|
IO.puts("Generation completed in #{duration}ms")
|
||||||
|
IO.puts("Total: #{result.total}")
|
||||||
|
IO.puts("Success: #{result.success}")
|
||||||
|
IO.puts("Errors: #{result.errors}")
|
||||||
|
|
||||||
|
if result.errors > 0 do
|
||||||
|
IO.puts("\nErrors encountered:")
|
||||||
|
result.results
|
||||||
|
|> Enum.filter(&match?({:error, _, _}, &1))
|
||||||
|
|> Enum.each(fn {:error, id, reason} ->
|
||||||
|
IO.puts(" AprilTag ID #{id}: #{inspect(reason)}")
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
|
||||||
|
if result.success == result.total do
|
||||||
|
IO.puts("\n✅ All AprilTag SVG files generated successfully!")
|
||||||
|
IO.puts("Files are available in: priv/static/apriltags/")
|
||||||
|
else
|
||||||
|
IO.puts("\n⚠️ Some files failed to generate. Check the errors above.")
|
||||||
|
System.halt(1)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
defmodule ComponentsElixir.Repo.Migrations.MigrateQrToApriltag do
|
||||||
|
use Ecto.Migration
|
||||||
|
|
||||||
|
def up do
|
||||||
|
# Rename qr_code column to qr_code_old for backup
|
||||||
|
rename table(:storage_locations), :qr_code, to: :qr_code_old
|
||||||
|
|
||||||
|
# Add new apriltag_id column as integer
|
||||||
|
alter table(:storage_locations) do
|
||||||
|
add :apriltag_id, :integer
|
||||||
|
end
|
||||||
|
|
||||||
|
# Create unique index for apriltag_id
|
||||||
|
create unique_index(:storage_locations, [:apriltag_id])
|
||||||
|
|
||||||
|
# Add constraint to ensure apriltag_id is in valid range (0-586 for tag36h11)
|
||||||
|
create constraint(:storage_locations, :apriltag_id_range, check: "apriltag_id >= 0 AND apriltag_id <= 586")
|
||||||
|
|
||||||
|
# Note: We keep qr_code_old for now in case we need to rollback
|
||||||
|
# It can be removed in a future migration after confirming everything works
|
||||||
|
end
|
||||||
|
|
||||||
|
def down do
|
||||||
|
# Remove apriltag_id column and constraints
|
||||||
|
drop constraint(:storage_locations, :apriltag_id_range)
|
||||||
|
drop unique_index(:storage_locations, [:apriltag_id])
|
||||||
|
|
||||||
|
alter table(:storage_locations) do
|
||||||
|
remove :apriltag_id
|
||||||
|
end
|
||||||
|
|
||||||
|
# Rename back to qr_code
|
||||||
|
rename table(:storage_locations), :qr_code_old, to: :qr_code
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
defmodule ComponentsElixir.Repo.Migrations.DropQrCodeOldColumn do
|
||||||
|
use Ecto.Migration
|
||||||
|
|
||||||
|
def up do
|
||||||
|
# Drop the qr_code_old column since we've fully migrated to AprilTags
|
||||||
|
alter table(:storage_locations) do
|
||||||
|
remove :qr_code_old
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def down do
|
||||||
|
# If we need to rollback, re-add the qr_code_old column
|
||||||
|
# Note: This will not restore the original data
|
||||||
|
alter table(:storage_locations) do
|
||||||
|
add :qr_code_old, :string, null: false, default: ""
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
20
priv/static/apriltags/tag36h11_id_000.svg
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
<svg width="200" height="230" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<!-- White background -->
|
||||||
|
<rect width="200" height="230" fill="white"/>
|
||||||
|
|
||||||
|
<!-- AprilTag placeholder (simplified) -->
|
||||||
|
<rect x="20" y="20" width="160" height="160"
|
||||||
|
fill="white" stroke="black" stroke-width="2"/>
|
||||||
|
|
||||||
|
<!-- Simplified tag pattern - in reality this would be the actual AprilTag -->
|
||||||
|
<rect x="30" y="30" width="140" height="140"
|
||||||
|
fill="black"/>
|
||||||
|
<rect x="40" y="40" width="120" height="120"
|
||||||
|
fill="white"/>
|
||||||
|
|
||||||
|
<!-- ID text below -->
|
||||||
|
<text x="100.0" y="220" text-anchor="middle"
|
||||||
|
font-family="Arial" font-size="14" font-weight="bold">
|
||||||
|
ID: 000
|
||||||
|
</text>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 687 B |
20
priv/static/apriltags/tag36h11_id_001.svg
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
<svg width="200" height="230" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<!-- White background -->
|
||||||
|
<rect width="200" height="230" fill="white"/>
|
||||||
|
|
||||||
|
<!-- AprilTag placeholder (simplified) -->
|
||||||
|
<rect x="20" y="20" width="160" height="160"
|
||||||
|
fill="white" stroke="black" stroke-width="2"/>
|
||||||
|
|
||||||
|
<!-- Simplified tag pattern - in reality this would be the actual AprilTag -->
|
||||||
|
<rect x="30" y="30" width="140" height="140"
|
||||||
|
fill="black"/>
|
||||||
|
<rect x="40" y="40" width="120" height="120"
|
||||||
|
fill="white"/>
|
||||||
|
|
||||||
|
<!-- ID text below -->
|
||||||
|
<text x="100.0" y="220" text-anchor="middle"
|
||||||
|
font-family="Arial" font-size="14" font-weight="bold">
|
||||||
|
ID: 001
|
||||||
|
</text>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 687 B |
20
priv/static/apriltags/tag36h11_id_002.svg
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
<svg width="200" height="230" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<!-- White background -->
|
||||||
|
<rect width="200" height="230" fill="white"/>
|
||||||
|
|
||||||
|
<!-- AprilTag placeholder (simplified) -->
|
||||||
|
<rect x="20" y="20" width="160" height="160"
|
||||||
|
fill="white" stroke="black" stroke-width="2"/>
|
||||||
|
|
||||||
|
<!-- Simplified tag pattern - in reality this would be the actual AprilTag -->
|
||||||
|
<rect x="30" y="30" width="140" height="140"
|
||||||
|
fill="black"/>
|
||||||
|
<rect x="40" y="40" width="120" height="120"
|
||||||
|
fill="white"/>
|
||||||
|
|
||||||
|
<!-- ID text below -->
|
||||||
|
<text x="100.0" y="220" text-anchor="middle"
|
||||||
|
font-family="Arial" font-size="14" font-weight="bold">
|
||||||
|
ID: 002
|
||||||
|
</text>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 687 B |
20
priv/static/apriltags/tag36h11_id_003.svg
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
<svg width="200" height="230" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<!-- White background -->
|
||||||
|
<rect width="200" height="230" fill="white"/>
|
||||||
|
|
||||||
|
<!-- AprilTag placeholder (simplified) -->
|
||||||
|
<rect x="20" y="20" width="160" height="160"
|
||||||
|
fill="white" stroke="black" stroke-width="2"/>
|
||||||
|
|
||||||
|
<!-- Simplified tag pattern - in reality this would be the actual AprilTag -->
|
||||||
|
<rect x="30" y="30" width="140" height="140"
|
||||||
|
fill="black"/>
|
||||||
|
<rect x="40" y="40" width="120" height="120"
|
||||||
|
fill="white"/>
|
||||||
|
|
||||||
|
<!-- ID text below -->
|
||||||
|
<text x="100.0" y="220" text-anchor="middle"
|
||||||
|
font-family="Arial" font-size="14" font-weight="bold">
|
||||||
|
ID: 003
|
||||||
|
</text>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 687 B |
20
priv/static/apriltags/tag36h11_id_004.svg
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
<svg width="200" height="230" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<!-- White background -->
|
||||||
|
<rect width="200" height="230" fill="white"/>
|
||||||
|
|
||||||
|
<!-- AprilTag placeholder (simplified) -->
|
||||||
|
<rect x="20" y="20" width="160" height="160"
|
||||||
|
fill="white" stroke="black" stroke-width="2"/>
|
||||||
|
|
||||||
|
<!-- Simplified tag pattern - in reality this would be the actual AprilTag -->
|
||||||
|
<rect x="30" y="30" width="140" height="140"
|
||||||
|
fill="black"/>
|
||||||
|
<rect x="40" y="40" width="120" height="120"
|
||||||
|
fill="white"/>
|
||||||
|
|
||||||
|
<!-- ID text below -->
|
||||||
|
<text x="100.0" y="220" text-anchor="middle"
|
||||||
|
font-family="Arial" font-size="14" font-weight="bold">
|
||||||
|
ID: 004
|
||||||
|
</text>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 687 B |
20
priv/static/apriltags/tag36h11_id_005.svg
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
<svg width="200" height="230" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<!-- White background -->
|
||||||
|
<rect width="200" height="230" fill="white"/>
|
||||||
|
|
||||||
|
<!-- AprilTag placeholder (simplified) -->
|
||||||
|
<rect x="20" y="20" width="160" height="160"
|
||||||
|
fill="white" stroke="black" stroke-width="2"/>
|
||||||
|
|
||||||
|
<!-- Simplified tag pattern - in reality this would be the actual AprilTag -->
|
||||||
|
<rect x="30" y="30" width="140" height="140"
|
||||||
|
fill="black"/>
|
||||||
|
<rect x="40" y="40" width="120" height="120"
|
||||||
|
fill="white"/>
|
||||||
|
|
||||||
|
<!-- ID text below -->
|
||||||
|
<text x="100.0" y="220" text-anchor="middle"
|
||||||
|
font-family="Arial" font-size="14" font-weight="bold">
|
||||||
|
ID: 005
|
||||||
|
</text>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 687 B |
20
priv/static/apriltags/tag36h11_id_006.svg
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
<svg width="200" height="230" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<!-- White background -->
|
||||||
|
<rect width="200" height="230" fill="white"/>
|
||||||
|
|
||||||
|
<!-- AprilTag placeholder (simplified) -->
|
||||||
|
<rect x="20" y="20" width="160" height="160"
|
||||||
|
fill="white" stroke="black" stroke-width="2"/>
|
||||||
|
|
||||||
|
<!-- Simplified tag pattern - in reality this would be the actual AprilTag -->
|
||||||
|
<rect x="30" y="30" width="140" height="140"
|
||||||
|
fill="black"/>
|
||||||
|
<rect x="40" y="40" width="120" height="120"
|
||||||
|
fill="white"/>
|
||||||
|
|
||||||
|
<!-- ID text below -->
|
||||||
|
<text x="100.0" y="220" text-anchor="middle"
|
||||||
|
font-family="Arial" font-size="14" font-weight="bold">
|
||||||
|
ID: 006
|
||||||
|
</text>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 687 B |
20
priv/static/apriltags/tag36h11_id_007.svg
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
<svg width="200" height="230" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<!-- White background -->
|
||||||
|
<rect width="200" height="230" fill="white"/>
|
||||||
|
|
||||||
|
<!-- AprilTag placeholder (simplified) -->
|
||||||
|
<rect x="20" y="20" width="160" height="160"
|
||||||
|
fill="white" stroke="black" stroke-width="2"/>
|
||||||
|
|
||||||
|
<!-- Simplified tag pattern - in reality this would be the actual AprilTag -->
|
||||||
|
<rect x="30" y="30" width="140" height="140"
|
||||||
|
fill="black"/>
|
||||||
|
<rect x="40" y="40" width="120" height="120"
|
||||||
|
fill="white"/>
|
||||||
|
|
||||||
|
<!-- ID text below -->
|
||||||
|
<text x="100.0" y="220" text-anchor="middle"
|
||||||
|
font-family="Arial" font-size="14" font-weight="bold">
|
||||||
|
ID: 007
|
||||||
|
</text>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 687 B |
20
priv/static/apriltags/tag36h11_id_008.svg
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
<svg width="200" height="230" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<!-- White background -->
|
||||||
|
<rect width="200" height="230" fill="white"/>
|
||||||
|
|
||||||
|
<!-- AprilTag placeholder (simplified) -->
|
||||||
|
<rect x="20" y="20" width="160" height="160"
|
||||||
|
fill="white" stroke="black" stroke-width="2"/>
|
||||||
|
|
||||||
|
<!-- Simplified tag pattern - in reality this would be the actual AprilTag -->
|
||||||
|
<rect x="30" y="30" width="140" height="140"
|
||||||
|
fill="black"/>
|
||||||
|
<rect x="40" y="40" width="120" height="120"
|
||||||
|
fill="white"/>
|
||||||
|
|
||||||
|
<!-- ID text below -->
|
||||||
|
<text x="100.0" y="220" text-anchor="middle"
|
||||||
|
font-family="Arial" font-size="14" font-weight="bold">
|
||||||
|
ID: 008
|
||||||
|
</text>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 687 B |
20
priv/static/apriltags/tag36h11_id_009.svg
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
<svg width="200" height="230" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<!-- White background -->
|
||||||
|
<rect width="200" height="230" fill="white"/>
|
||||||
|
|
||||||
|
<!-- AprilTag placeholder (simplified) -->
|
||||||
|
<rect x="20" y="20" width="160" height="160"
|
||||||
|
fill="white" stroke="black" stroke-width="2"/>
|
||||||
|
|
||||||
|
<!-- Simplified tag pattern - in reality this would be the actual AprilTag -->
|
||||||
|
<rect x="30" y="30" width="140" height="140"
|
||||||
|
fill="black"/>
|
||||||
|
<rect x="40" y="40" width="120" height="120"
|
||||||
|
fill="white"/>
|
||||||
|
|
||||||
|
<!-- ID text below -->
|
||||||
|
<text x="100.0" y="220" text-anchor="middle"
|
||||||
|
font-family="Arial" font-size="14" font-weight="bold">
|
||||||
|
ID: 009
|
||||||
|
</text>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 687 B |
20
priv/static/apriltags/tag36h11_id_010.svg
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
<svg width="200" height="230" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<!-- White background -->
|
||||||
|
<rect width="200" height="230" fill="white"/>
|
||||||
|
|
||||||
|
<!-- AprilTag placeholder (simplified) -->
|
||||||
|
<rect x="20" y="20" width="160" height="160"
|
||||||
|
fill="white" stroke="black" stroke-width="2"/>
|
||||||
|
|
||||||
|
<!-- Simplified tag pattern - in reality this would be the actual AprilTag -->
|
||||||
|
<rect x="30" y="30" width="140" height="140"
|
||||||
|
fill="black"/>
|
||||||
|
<rect x="40" y="40" width="120" height="120"
|
||||||
|
fill="white"/>
|
||||||
|
|
||||||
|
<!-- ID text below -->
|
||||||
|
<text x="100.0" y="220" text-anchor="middle"
|
||||||
|
font-family="Arial" font-size="14" font-weight="bold">
|
||||||
|
ID: 010
|
||||||
|
</text>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 687 B |
20
priv/static/apriltags/tag36h11_id_011.svg
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
<svg width="200" height="230" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<!-- White background -->
|
||||||
|
<rect width="200" height="230" fill="white"/>
|
||||||
|
|
||||||
|
<!-- AprilTag placeholder (simplified) -->
|
||||||
|
<rect x="20" y="20" width="160" height="160"
|
||||||
|
fill="white" stroke="black" stroke-width="2"/>
|
||||||
|
|
||||||
|
<!-- Simplified tag pattern - in reality this would be the actual AprilTag -->
|
||||||
|
<rect x="30" y="30" width="140" height="140"
|
||||||
|
fill="black"/>
|
||||||
|
<rect x="40" y="40" width="120" height="120"
|
||||||
|
fill="white"/>
|
||||||
|
|
||||||
|
<!-- ID text below -->
|
||||||
|
<text x="100.0" y="220" text-anchor="middle"
|
||||||
|
font-family="Arial" font-size="14" font-weight="bold">
|
||||||
|
ID: 011
|
||||||
|
</text>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 687 B |
20
priv/static/apriltags/tag36h11_id_012.svg
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
<svg width="200" height="230" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<!-- White background -->
|
||||||
|
<rect width="200" height="230" fill="white"/>
|
||||||
|
|
||||||
|
<!-- AprilTag placeholder (simplified) -->
|
||||||
|
<rect x="20" y="20" width="160" height="160"
|
||||||
|
fill="white" stroke="black" stroke-width="2"/>
|
||||||
|
|
||||||
|
<!-- Simplified tag pattern - in reality this would be the actual AprilTag -->
|
||||||
|
<rect x="30" y="30" width="140" height="140"
|
||||||
|
fill="black"/>
|
||||||
|
<rect x="40" y="40" width="120" height="120"
|
||||||
|
fill="white"/>
|
||||||
|
|
||||||
|
<!-- ID text below -->
|
||||||
|
<text x="100.0" y="220" text-anchor="middle"
|
||||||
|
font-family="Arial" font-size="14" font-weight="bold">
|
||||||
|
ID: 012
|
||||||
|
</text>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 687 B |
20
priv/static/apriltags/tag36h11_id_013.svg
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
<svg width="200" height="230" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<!-- White background -->
|
||||||
|
<rect width="200" height="230" fill="white"/>
|
||||||
|
|
||||||
|
<!-- AprilTag placeholder (simplified) -->
|
||||||
|
<rect x="20" y="20" width="160" height="160"
|
||||||
|
fill="white" stroke="black" stroke-width="2"/>
|
||||||
|
|
||||||
|
<!-- Simplified tag pattern - in reality this would be the actual AprilTag -->
|
||||||
|
<rect x="30" y="30" width="140" height="140"
|
||||||
|
fill="black"/>
|
||||||
|
<rect x="40" y="40" width="120" height="120"
|
||||||
|
fill="white"/>
|
||||||
|
|
||||||
|
<!-- ID text below -->
|
||||||
|
<text x="100.0" y="220" text-anchor="middle"
|
||||||
|
font-family="Arial" font-size="14" font-weight="bold">
|
||||||
|
ID: 013
|
||||||
|
</text>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 687 B |
20
priv/static/apriltags/tag36h11_id_014.svg
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
<svg width="200" height="230" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<!-- White background -->
|
||||||
|
<rect width="200" height="230" fill="white"/>
|
||||||
|
|
||||||
|
<!-- AprilTag placeholder (simplified) -->
|
||||||
|
<rect x="20" y="20" width="160" height="160"
|
||||||
|
fill="white" stroke="black" stroke-width="2"/>
|
||||||
|
|
||||||
|
<!-- Simplified tag pattern - in reality this would be the actual AprilTag -->
|
||||||
|
<rect x="30" y="30" width="140" height="140"
|
||||||
|
fill="black"/>
|
||||||
|
<rect x="40" y="40" width="120" height="120"
|
||||||
|
fill="white"/>
|
||||||
|
|
||||||
|
<!-- ID text below -->
|
||||||
|
<text x="100.0" y="220" text-anchor="middle"
|
||||||
|
font-family="Arial" font-size="14" font-weight="bold">
|
||||||
|
ID: 014
|
||||||
|
</text>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 687 B |
20
priv/static/apriltags/tag36h11_id_015.svg
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
<svg width="200" height="230" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<!-- White background -->
|
||||||
|
<rect width="200" height="230" fill="white"/>
|
||||||
|
|
||||||
|
<!-- AprilTag placeholder (simplified) -->
|
||||||
|
<rect x="20" y="20" width="160" height="160"
|
||||||
|
fill="white" stroke="black" stroke-width="2"/>
|
||||||
|
|
||||||
|
<!-- Simplified tag pattern - in reality this would be the actual AprilTag -->
|
||||||
|
<rect x="30" y="30" width="140" height="140"
|
||||||
|
fill="black"/>
|
||||||
|
<rect x="40" y="40" width="120" height="120"
|
||||||
|
fill="white"/>
|
||||||
|
|
||||||
|
<!-- ID text below -->
|
||||||
|
<text x="100.0" y="220" text-anchor="middle"
|
||||||
|
font-family="Arial" font-size="14" font-weight="bold">
|
||||||
|
ID: 015
|
||||||
|
</text>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 687 B |
20
priv/static/apriltags/tag36h11_id_016.svg
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
<svg width="200" height="230" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<!-- White background -->
|
||||||
|
<rect width="200" height="230" fill="white"/>
|
||||||
|
|
||||||
|
<!-- AprilTag placeholder (simplified) -->
|
||||||
|
<rect x="20" y="20" width="160" height="160"
|
||||||
|
fill="white" stroke="black" stroke-width="2"/>
|
||||||
|
|
||||||
|
<!-- Simplified tag pattern - in reality this would be the actual AprilTag -->
|
||||||
|
<rect x="30" y="30" width="140" height="140"
|
||||||
|
fill="black"/>
|
||||||
|
<rect x="40" y="40" width="120" height="120"
|
||||||
|
fill="white"/>
|
||||||
|
|
||||||
|
<!-- ID text below -->
|
||||||
|
<text x="100.0" y="220" text-anchor="middle"
|
||||||
|
font-family="Arial" font-size="14" font-weight="bold">
|
||||||
|
ID: 016
|
||||||
|
</text>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 687 B |
20
priv/static/apriltags/tag36h11_id_017.svg
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
<svg width="200" height="230" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<!-- White background -->
|
||||||
|
<rect width="200" height="230" fill="white"/>
|
||||||
|
|
||||||
|
<!-- AprilTag placeholder (simplified) -->
|
||||||
|
<rect x="20" y="20" width="160" height="160"
|
||||||
|
fill="white" stroke="black" stroke-width="2"/>
|
||||||
|
|
||||||
|
<!-- Simplified tag pattern - in reality this would be the actual AprilTag -->
|
||||||
|
<rect x="30" y="30" width="140" height="140"
|
||||||
|
fill="black"/>
|
||||||
|
<rect x="40" y="40" width="120" height="120"
|
||||||
|
fill="white"/>
|
||||||
|
|
||||||
|
<!-- ID text below -->
|
||||||
|
<text x="100.0" y="220" text-anchor="middle"
|
||||||
|
font-family="Arial" font-size="14" font-weight="bold">
|
||||||
|
ID: 017
|
||||||
|
</text>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 687 B |
20
priv/static/apriltags/tag36h11_id_018.svg
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
<svg width="200" height="230" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<!-- White background -->
|
||||||
|
<rect width="200" height="230" fill="white"/>
|
||||||
|
|
||||||
|
<!-- AprilTag placeholder (simplified) -->
|
||||||
|
<rect x="20" y="20" width="160" height="160"
|
||||||
|
fill="white" stroke="black" stroke-width="2"/>
|
||||||
|
|
||||||
|
<!-- Simplified tag pattern - in reality this would be the actual AprilTag -->
|
||||||
|
<rect x="30" y="30" width="140" height="140"
|
||||||
|
fill="black"/>
|
||||||
|
<rect x="40" y="40" width="120" height="120"
|
||||||
|
fill="white"/>
|
||||||
|
|
||||||
|
<!-- ID text below -->
|
||||||
|
<text x="100.0" y="220" text-anchor="middle"
|
||||||
|
font-family="Arial" font-size="14" font-weight="bold">
|
||||||
|
ID: 018
|
||||||
|
</text>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 687 B |
20
priv/static/apriltags/tag36h11_id_019.svg
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
<svg width="200" height="230" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<!-- White background -->
|
||||||
|
<rect width="200" height="230" fill="white"/>
|
||||||
|
|
||||||
|
<!-- AprilTag placeholder (simplified) -->
|
||||||
|
<rect x="20" y="20" width="160" height="160"
|
||||||
|
fill="white" stroke="black" stroke-width="2"/>
|
||||||
|
|
||||||
|
<!-- Simplified tag pattern - in reality this would be the actual AprilTag -->
|
||||||
|
<rect x="30" y="30" width="140" height="140"
|
||||||
|
fill="black"/>
|
||||||
|
<rect x="40" y="40" width="120" height="120"
|
||||||
|
fill="white"/>
|
||||||
|
|
||||||
|
<!-- ID text below -->
|
||||||
|
<text x="100.0" y="220" text-anchor="middle"
|
||||||
|
font-family="Arial" font-size="14" font-weight="bold">
|
||||||
|
ID: 019
|
||||||
|
</text>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 687 B |
20
priv/static/apriltags/tag36h11_id_020.svg
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
<svg width="200" height="230" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<!-- White background -->
|
||||||
|
<rect width="200" height="230" fill="white"/>
|
||||||
|
|
||||||
|
<!-- AprilTag placeholder (simplified) -->
|
||||||
|
<rect x="20" y="20" width="160" height="160"
|
||||||
|
fill="white" stroke="black" stroke-width="2"/>
|
||||||
|
|
||||||
|
<!-- Simplified tag pattern - in reality this would be the actual AprilTag -->
|
||||||
|
<rect x="30" y="30" width="140" height="140"
|
||||||
|
fill="black"/>
|
||||||
|
<rect x="40" y="40" width="120" height="120"
|
||||||
|
fill="white"/>
|
||||||
|
|
||||||
|
<!-- ID text below -->
|
||||||
|
<text x="100.0" y="220" text-anchor="middle"
|
||||||
|
font-family="Arial" font-size="14" font-weight="bold">
|
||||||
|
ID: 020
|
||||||
|
</text>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 687 B |
20
priv/static/apriltags/tag36h11_id_021.svg
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
<svg width="200" height="230" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<!-- White background -->
|
||||||
|
<rect width="200" height="230" fill="white"/>
|
||||||
|
|
||||||
|
<!-- AprilTag placeholder (simplified) -->
|
||||||
|
<rect x="20" y="20" width="160" height="160"
|
||||||
|
fill="white" stroke="black" stroke-width="2"/>
|
||||||
|
|
||||||
|
<!-- Simplified tag pattern - in reality this would be the actual AprilTag -->
|
||||||
|
<rect x="30" y="30" width="140" height="140"
|
||||||
|
fill="black"/>
|
||||||
|
<rect x="40" y="40" width="120" height="120"
|
||||||
|
fill="white"/>
|
||||||
|
|
||||||
|
<!-- ID text below -->
|
||||||
|
<text x="100.0" y="220" text-anchor="middle"
|
||||||
|
font-family="Arial" font-size="14" font-weight="bold">
|
||||||
|
ID: 021
|
||||||
|
</text>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 687 B |
20
priv/static/apriltags/tag36h11_id_022.svg
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
<svg width="200" height="230" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<!-- White background -->
|
||||||
|
<rect width="200" height="230" fill="white"/>
|
||||||
|
|
||||||
|
<!-- AprilTag placeholder (simplified) -->
|
||||||
|
<rect x="20" y="20" width="160" height="160"
|
||||||
|
fill="white" stroke="black" stroke-width="2"/>
|
||||||
|
|
||||||
|
<!-- Simplified tag pattern - in reality this would be the actual AprilTag -->
|
||||||
|
<rect x="30" y="30" width="140" height="140"
|
||||||
|
fill="black"/>
|
||||||
|
<rect x="40" y="40" width="120" height="120"
|
||||||
|
fill="white"/>
|
||||||
|
|
||||||
|
<!-- ID text below -->
|
||||||
|
<text x="100.0" y="220" text-anchor="middle"
|
||||||
|
font-family="Arial" font-size="14" font-weight="bold">
|
||||||
|
ID: 022
|
||||||
|
</text>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 687 B |
20
priv/static/apriltags/tag36h11_id_023.svg
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
<svg width="200" height="230" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<!-- White background -->
|
||||||
|
<rect width="200" height="230" fill="white"/>
|
||||||
|
|
||||||
|
<!-- AprilTag placeholder (simplified) -->
|
||||||
|
<rect x="20" y="20" width="160" height="160"
|
||||||
|
fill="white" stroke="black" stroke-width="2"/>
|
||||||
|
|
||||||
|
<!-- Simplified tag pattern - in reality this would be the actual AprilTag -->
|
||||||
|
<rect x="30" y="30" width="140" height="140"
|
||||||
|
fill="black"/>
|
||||||
|
<rect x="40" y="40" width="120" height="120"
|
||||||
|
fill="white"/>
|
||||||
|
|
||||||
|
<!-- ID text below -->
|
||||||
|
<text x="100.0" y="220" text-anchor="middle"
|
||||||
|
font-family="Arial" font-size="14" font-weight="bold">
|
||||||
|
ID: 023
|
||||||
|
</text>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 687 B |
20
priv/static/apriltags/tag36h11_id_024.svg
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
<svg width="200" height="230" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<!-- White background -->
|
||||||
|
<rect width="200" height="230" fill="white"/>
|
||||||
|
|
||||||
|
<!-- AprilTag placeholder (simplified) -->
|
||||||
|
<rect x="20" y="20" width="160" height="160"
|
||||||
|
fill="white" stroke="black" stroke-width="2"/>
|
||||||
|
|
||||||
|
<!-- Simplified tag pattern - in reality this would be the actual AprilTag -->
|
||||||
|
<rect x="30" y="30" width="140" height="140"
|
||||||
|
fill="black"/>
|
||||||
|
<rect x="40" y="40" width="120" height="120"
|
||||||
|
fill="white"/>
|
||||||
|
|
||||||
|
<!-- ID text below -->
|
||||||
|
<text x="100.0" y="220" text-anchor="middle"
|
||||||
|
font-family="Arial" font-size="14" font-weight="bold">
|
||||||
|
ID: 024
|
||||||
|
</text>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 687 B |
20
priv/static/apriltags/tag36h11_id_025.svg
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
<svg width="200" height="230" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<!-- White background -->
|
||||||
|
<rect width="200" height="230" fill="white"/>
|
||||||
|
|
||||||
|
<!-- AprilTag placeholder (simplified) -->
|
||||||
|
<rect x="20" y="20" width="160" height="160"
|
||||||
|
fill="white" stroke="black" stroke-width="2"/>
|
||||||
|
|
||||||
|
<!-- Simplified tag pattern - in reality this would be the actual AprilTag -->
|
||||||
|
<rect x="30" y="30" width="140" height="140"
|
||||||
|
fill="black"/>
|
||||||
|
<rect x="40" y="40" width="120" height="120"
|
||||||
|
fill="white"/>
|
||||||
|
|
||||||
|
<!-- ID text below -->
|
||||||
|
<text x="100.0" y="220" text-anchor="middle"
|
||||||
|
font-family="Arial" font-size="14" font-weight="bold">
|
||||||
|
ID: 025
|
||||||
|
</text>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 687 B |
20
priv/static/apriltags/tag36h11_id_026.svg
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
<svg width="200" height="230" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<!-- White background -->
|
||||||
|
<rect width="200" height="230" fill="white"/>
|
||||||
|
|
||||||
|
<!-- AprilTag placeholder (simplified) -->
|
||||||
|
<rect x="20" y="20" width="160" height="160"
|
||||||
|
fill="white" stroke="black" stroke-width="2"/>
|
||||||
|
|
||||||
|
<!-- Simplified tag pattern - in reality this would be the actual AprilTag -->
|
||||||
|
<rect x="30" y="30" width="140" height="140"
|
||||||
|
fill="black"/>
|
||||||
|
<rect x="40" y="40" width="120" height="120"
|
||||||
|
fill="white"/>
|
||||||
|
|
||||||
|
<!-- ID text below -->
|
||||||
|
<text x="100.0" y="220" text-anchor="middle"
|
||||||
|
font-family="Arial" font-size="14" font-weight="bold">
|
||||||
|
ID: 026
|
||||||
|
</text>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 687 B |
20
priv/static/apriltags/tag36h11_id_027.svg
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
<svg width="200" height="230" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<!-- White background -->
|
||||||
|
<rect width="200" height="230" fill="white"/>
|
||||||
|
|
||||||
|
<!-- AprilTag placeholder (simplified) -->
|
||||||
|
<rect x="20" y="20" width="160" height="160"
|
||||||
|
fill="white" stroke="black" stroke-width="2"/>
|
||||||
|
|
||||||
|
<!-- Simplified tag pattern - in reality this would be the actual AprilTag -->
|
||||||
|
<rect x="30" y="30" width="140" height="140"
|
||||||
|
fill="black"/>
|
||||||
|
<rect x="40" y="40" width="120" height="120"
|
||||||
|
fill="white"/>
|
||||||
|
|
||||||
|
<!-- ID text below -->
|
||||||
|
<text x="100.0" y="220" text-anchor="middle"
|
||||||
|
font-family="Arial" font-size="14" font-weight="bold">
|
||||||
|
ID: 027
|
||||||
|
</text>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 687 B |
20
priv/static/apriltags/tag36h11_id_028.svg
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
<svg width="200" height="230" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<!-- White background -->
|
||||||
|
<rect width="200" height="230" fill="white"/>
|
||||||
|
|
||||||
|
<!-- AprilTag placeholder (simplified) -->
|
||||||
|
<rect x="20" y="20" width="160" height="160"
|
||||||
|
fill="white" stroke="black" stroke-width="2"/>
|
||||||
|
|
||||||
|
<!-- Simplified tag pattern - in reality this would be the actual AprilTag -->
|
||||||
|
<rect x="30" y="30" width="140" height="140"
|
||||||
|
fill="black"/>
|
||||||
|
<rect x="40" y="40" width="120" height="120"
|
||||||
|
fill="white"/>
|
||||||
|
|
||||||
|
<!-- ID text below -->
|
||||||
|
<text x="100.0" y="220" text-anchor="middle"
|
||||||
|
font-family="Arial" font-size="14" font-weight="bold">
|
||||||
|
ID: 028
|
||||||
|
</text>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 687 B |
20
priv/static/apriltags/tag36h11_id_029.svg
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
<svg width="200" height="230" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<!-- White background -->
|
||||||
|
<rect width="200" height="230" fill="white"/>
|
||||||
|
|
||||||
|
<!-- AprilTag placeholder (simplified) -->
|
||||||
|
<rect x="20" y="20" width="160" height="160"
|
||||||
|
fill="white" stroke="black" stroke-width="2"/>
|
||||||
|
|
||||||
|
<!-- Simplified tag pattern - in reality this would be the actual AprilTag -->
|
||||||
|
<rect x="30" y="30" width="140" height="140"
|
||||||
|
fill="black"/>
|
||||||
|
<rect x="40" y="40" width="120" height="120"
|
||||||
|
fill="white"/>
|
||||||
|
|
||||||
|
<!-- ID text below -->
|
||||||
|
<text x="100.0" y="220" text-anchor="middle"
|
||||||
|
font-family="Arial" font-size="14" font-weight="bold">
|
||||||
|
ID: 029
|
||||||
|
</text>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 687 B |
20
priv/static/apriltags/tag36h11_id_030.svg
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
<svg width="200" height="230" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<!-- White background -->
|
||||||
|
<rect width="200" height="230" fill="white"/>
|
||||||
|
|
||||||
|
<!-- AprilTag placeholder (simplified) -->
|
||||||
|
<rect x="20" y="20" width="160" height="160"
|
||||||
|
fill="white" stroke="black" stroke-width="2"/>
|
||||||
|
|
||||||
|
<!-- Simplified tag pattern - in reality this would be the actual AprilTag -->
|
||||||
|
<rect x="30" y="30" width="140" height="140"
|
||||||
|
fill="black"/>
|
||||||
|
<rect x="40" y="40" width="120" height="120"
|
||||||
|
fill="white"/>
|
||||||
|
|
||||||
|
<!-- ID text below -->
|
||||||
|
<text x="100.0" y="220" text-anchor="middle"
|
||||||
|
font-family="Arial" font-size="14" font-weight="bold">
|
||||||
|
ID: 030
|
||||||
|
</text>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 687 B |
20
priv/static/apriltags/tag36h11_id_031.svg
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
<svg width="200" height="230" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<!-- White background -->
|
||||||
|
<rect width="200" height="230" fill="white"/>
|
||||||
|
|
||||||
|
<!-- AprilTag placeholder (simplified) -->
|
||||||
|
<rect x="20" y="20" width="160" height="160"
|
||||||
|
fill="white" stroke="black" stroke-width="2"/>
|
||||||
|
|
||||||
|
<!-- Simplified tag pattern - in reality this would be the actual AprilTag -->
|
||||||
|
<rect x="30" y="30" width="140" height="140"
|
||||||
|
fill="black"/>
|
||||||
|
<rect x="40" y="40" width="120" height="120"
|
||||||
|
fill="white"/>
|
||||||
|
|
||||||
|
<!-- ID text below -->
|
||||||
|
<text x="100.0" y="220" text-anchor="middle"
|
||||||
|
font-family="Arial" font-size="14" font-weight="bold">
|
||||||
|
ID: 031
|
||||||
|
</text>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 687 B |
20
priv/static/apriltags/tag36h11_id_032.svg
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
<svg width="200" height="230" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<!-- White background -->
|
||||||
|
<rect width="200" height="230" fill="white"/>
|
||||||
|
|
||||||
|
<!-- AprilTag placeholder (simplified) -->
|
||||||
|
<rect x="20" y="20" width="160" height="160"
|
||||||
|
fill="white" stroke="black" stroke-width="2"/>
|
||||||
|
|
||||||
|
<!-- Simplified tag pattern - in reality this would be the actual AprilTag -->
|
||||||
|
<rect x="30" y="30" width="140" height="140"
|
||||||
|
fill="black"/>
|
||||||
|
<rect x="40" y="40" width="120" height="120"
|
||||||
|
fill="white"/>
|
||||||
|
|
||||||
|
<!-- ID text below -->
|
||||||
|
<text x="100.0" y="220" text-anchor="middle"
|
||||||
|
font-family="Arial" font-size="14" font-weight="bold">
|
||||||
|
ID: 032
|
||||||
|
</text>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 687 B |
20
priv/static/apriltags/tag36h11_id_033.svg
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
<svg width="200" height="230" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<!-- White background -->
|
||||||
|
<rect width="200" height="230" fill="white"/>
|
||||||
|
|
||||||
|
<!-- AprilTag placeholder (simplified) -->
|
||||||
|
<rect x="20" y="20" width="160" height="160"
|
||||||
|
fill="white" stroke="black" stroke-width="2"/>
|
||||||
|
|
||||||
|
<!-- Simplified tag pattern - in reality this would be the actual AprilTag -->
|
||||||
|
<rect x="30" y="30" width="140" height="140"
|
||||||
|
fill="black"/>
|
||||||
|
<rect x="40" y="40" width="120" height="120"
|
||||||
|
fill="white"/>
|
||||||
|
|
||||||
|
<!-- ID text below -->
|
||||||
|
<text x="100.0" y="220" text-anchor="middle"
|
||||||
|
font-family="Arial" font-size="14" font-weight="bold">
|
||||||
|
ID: 033
|
||||||
|
</text>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 687 B |
20
priv/static/apriltags/tag36h11_id_034.svg
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
<svg width="200" height="230" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<!-- White background -->
|
||||||
|
<rect width="200" height="230" fill="white"/>
|
||||||
|
|
||||||
|
<!-- AprilTag placeholder (simplified) -->
|
||||||
|
<rect x="20" y="20" width="160" height="160"
|
||||||
|
fill="white" stroke="black" stroke-width="2"/>
|
||||||
|
|
||||||
|
<!-- Simplified tag pattern - in reality this would be the actual AprilTag -->
|
||||||
|
<rect x="30" y="30" width="140" height="140"
|
||||||
|
fill="black"/>
|
||||||
|
<rect x="40" y="40" width="120" height="120"
|
||||||
|
fill="white"/>
|
||||||
|
|
||||||
|
<!-- ID text below -->
|
||||||
|
<text x="100.0" y="220" text-anchor="middle"
|
||||||
|
font-family="Arial" font-size="14" font-weight="bold">
|
||||||
|
ID: 034
|
||||||
|
</text>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 687 B |
20
priv/static/apriltags/tag36h11_id_035.svg
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
<svg width="200" height="230" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<!-- White background -->
|
||||||
|
<rect width="200" height="230" fill="white"/>
|
||||||
|
|
||||||
|
<!-- AprilTag placeholder (simplified) -->
|
||||||
|
<rect x="20" y="20" width="160" height="160"
|
||||||
|
fill="white" stroke="black" stroke-width="2"/>
|
||||||
|
|
||||||
|
<!-- Simplified tag pattern - in reality this would be the actual AprilTag -->
|
||||||
|
<rect x="30" y="30" width="140" height="140"
|
||||||
|
fill="black"/>
|
||||||
|
<rect x="40" y="40" width="120" height="120"
|
||||||
|
fill="white"/>
|
||||||
|
|
||||||
|
<!-- ID text below -->
|
||||||
|
<text x="100.0" y="220" text-anchor="middle"
|
||||||
|
font-family="Arial" font-size="14" font-weight="bold">
|
||||||
|
ID: 035
|
||||||
|
</text>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 687 B |
20
priv/static/apriltags/tag36h11_id_036.svg
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
<svg width="200" height="230" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<!-- White background -->
|
||||||
|
<rect width="200" height="230" fill="white"/>
|
||||||
|
|
||||||
|
<!-- AprilTag placeholder (simplified) -->
|
||||||
|
<rect x="20" y="20" width="160" height="160"
|
||||||
|
fill="white" stroke="black" stroke-width="2"/>
|
||||||
|
|
||||||
|
<!-- Simplified tag pattern - in reality this would be the actual AprilTag -->
|
||||||
|
<rect x="30" y="30" width="140" height="140"
|
||||||
|
fill="black"/>
|
||||||
|
<rect x="40" y="40" width="120" height="120"
|
||||||
|
fill="white"/>
|
||||||
|
|
||||||
|
<!-- ID text below -->
|
||||||
|
<text x="100.0" y="220" text-anchor="middle"
|
||||||
|
font-family="Arial" font-size="14" font-weight="bold">
|
||||||
|
ID: 036
|
||||||
|
</text>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 687 B |
20
priv/static/apriltags/tag36h11_id_037.svg
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
<svg width="200" height="230" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<!-- White background -->
|
||||||
|
<rect width="200" height="230" fill="white"/>
|
||||||
|
|
||||||
|
<!-- AprilTag placeholder (simplified) -->
|
||||||
|
<rect x="20" y="20" width="160" height="160"
|
||||||
|
fill="white" stroke="black" stroke-width="2"/>
|
||||||
|
|
||||||
|
<!-- Simplified tag pattern - in reality this would be the actual AprilTag -->
|
||||||
|
<rect x="30" y="30" width="140" height="140"
|
||||||
|
fill="black"/>
|
||||||
|
<rect x="40" y="40" width="120" height="120"
|
||||||
|
fill="white"/>
|
||||||
|
|
||||||
|
<!-- ID text below -->
|
||||||
|
<text x="100.0" y="220" text-anchor="middle"
|
||||||
|
font-family="Arial" font-size="14" font-weight="bold">
|
||||||
|
ID: 037
|
||||||
|
</text>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 687 B |
20
priv/static/apriltags/tag36h11_id_038.svg
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
<svg width="200" height="230" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<!-- White background -->
|
||||||
|
<rect width="200" height="230" fill="white"/>
|
||||||
|
|
||||||
|
<!-- AprilTag placeholder (simplified) -->
|
||||||
|
<rect x="20" y="20" width="160" height="160"
|
||||||
|
fill="white" stroke="black" stroke-width="2"/>
|
||||||
|
|
||||||
|
<!-- Simplified tag pattern - in reality this would be the actual AprilTag -->
|
||||||
|
<rect x="30" y="30" width="140" height="140"
|
||||||
|
fill="black"/>
|
||||||
|
<rect x="40" y="40" width="120" height="120"
|
||||||
|
fill="white"/>
|
||||||
|
|
||||||
|
<!-- ID text below -->
|
||||||
|
<text x="100.0" y="220" text-anchor="middle"
|
||||||
|
font-family="Arial" font-size="14" font-weight="bold">
|
||||||
|
ID: 038
|
||||||
|
</text>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 687 B |
20
priv/static/apriltags/tag36h11_id_039.svg
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
<svg width="200" height="230" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<!-- White background -->
|
||||||
|
<rect width="200" height="230" fill="white"/>
|
||||||
|
|
||||||
|
<!-- AprilTag placeholder (simplified) -->
|
||||||
|
<rect x="20" y="20" width="160" height="160"
|
||||||
|
fill="white" stroke="black" stroke-width="2"/>
|
||||||
|
|
||||||
|
<!-- Simplified tag pattern - in reality this would be the actual AprilTag -->
|
||||||
|
<rect x="30" y="30" width="140" height="140"
|
||||||
|
fill="black"/>
|
||||||
|
<rect x="40" y="40" width="120" height="120"
|
||||||
|
fill="white"/>
|
||||||
|
|
||||||
|
<!-- ID text below -->
|
||||||
|
<text x="100.0" y="220" text-anchor="middle"
|
||||||
|
font-family="Arial" font-size="14" font-weight="bold">
|
||||||
|
ID: 039
|
||||||
|
</text>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 687 B |
20
priv/static/apriltags/tag36h11_id_040.svg
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
<svg width="200" height="230" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<!-- White background -->
|
||||||
|
<rect width="200" height="230" fill="white"/>
|
||||||
|
|
||||||
|
<!-- AprilTag placeholder (simplified) -->
|
||||||
|
<rect x="20" y="20" width="160" height="160"
|
||||||
|
fill="white" stroke="black" stroke-width="2"/>
|
||||||
|
|
||||||
|
<!-- Simplified tag pattern - in reality this would be the actual AprilTag -->
|
||||||
|
<rect x="30" y="30" width="140" height="140"
|
||||||
|
fill="black"/>
|
||||||
|
<rect x="40" y="40" width="120" height="120"
|
||||||
|
fill="white"/>
|
||||||
|
|
||||||
|
<!-- ID text below -->
|
||||||
|
<text x="100.0" y="220" text-anchor="middle"
|
||||||
|
font-family="Arial" font-size="14" font-weight="bold">
|
||||||
|
ID: 040
|
||||||
|
</text>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 687 B |
20
priv/static/apriltags/tag36h11_id_041.svg
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
<svg width="200" height="230" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<!-- White background -->
|
||||||
|
<rect width="200" height="230" fill="white"/>
|
||||||
|
|
||||||
|
<!-- AprilTag placeholder (simplified) -->
|
||||||
|
<rect x="20" y="20" width="160" height="160"
|
||||||
|
fill="white" stroke="black" stroke-width="2"/>
|
||||||
|
|
||||||
|
<!-- Simplified tag pattern - in reality this would be the actual AprilTag -->
|
||||||
|
<rect x="30" y="30" width="140" height="140"
|
||||||
|
fill="black"/>
|
||||||
|
<rect x="40" y="40" width="120" height="120"
|
||||||
|
fill="white"/>
|
||||||
|
|
||||||
|
<!-- ID text below -->
|
||||||
|
<text x="100.0" y="220" text-anchor="middle"
|
||||||
|
font-family="Arial" font-size="14" font-weight="bold">
|
||||||
|
ID: 041
|
||||||
|
</text>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 687 B |
20
priv/static/apriltags/tag36h11_id_042.svg
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
<svg width="200" height="230" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<!-- White background -->
|
||||||
|
<rect width="200" height="230" fill="white"/>
|
||||||
|
|
||||||
|
<!-- AprilTag placeholder (simplified) -->
|
||||||
|
<rect x="20" y="20" width="160" height="160"
|
||||||
|
fill="white" stroke="black" stroke-width="2"/>
|
||||||
|
|
||||||
|
<!-- Simplified tag pattern - in reality this would be the actual AprilTag -->
|
||||||
|
<rect x="30" y="30" width="140" height="140"
|
||||||
|
fill="black"/>
|
||||||
|
<rect x="40" y="40" width="120" height="120"
|
||||||
|
fill="white"/>
|
||||||
|
|
||||||
|
<!-- ID text below -->
|
||||||
|
<text x="100.0" y="220" text-anchor="middle"
|
||||||
|
font-family="Arial" font-size="14" font-weight="bold">
|
||||||
|
ID: 042
|
||||||
|
</text>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 687 B |
20
priv/static/apriltags/tag36h11_id_043.svg
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
<svg width="200" height="230" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<!-- White background -->
|
||||||
|
<rect width="200" height="230" fill="white"/>
|
||||||
|
|
||||||
|
<!-- AprilTag placeholder (simplified) -->
|
||||||
|
<rect x="20" y="20" width="160" height="160"
|
||||||
|
fill="white" stroke="black" stroke-width="2"/>
|
||||||
|
|
||||||
|
<!-- Simplified tag pattern - in reality this would be the actual AprilTag -->
|
||||||
|
<rect x="30" y="30" width="140" height="140"
|
||||||
|
fill="black"/>
|
||||||
|
<rect x="40" y="40" width="120" height="120"
|
||||||
|
fill="white"/>
|
||||||
|
|
||||||
|
<!-- ID text below -->
|
||||||
|
<text x="100.0" y="220" text-anchor="middle"
|
||||||
|
font-family="Arial" font-size="14" font-weight="bold">
|
||||||
|
ID: 043
|
||||||
|
</text>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 687 B |
20
priv/static/apriltags/tag36h11_id_044.svg
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
<svg width="200" height="230" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<!-- White background -->
|
||||||
|
<rect width="200" height="230" fill="white"/>
|
||||||
|
|
||||||
|
<!-- AprilTag placeholder (simplified) -->
|
||||||
|
<rect x="20" y="20" width="160" height="160"
|
||||||
|
fill="white" stroke="black" stroke-width="2"/>
|
||||||
|
|
||||||
|
<!-- Simplified tag pattern - in reality this would be the actual AprilTag -->
|
||||||
|
<rect x="30" y="30" width="140" height="140"
|
||||||
|
fill="black"/>
|
||||||
|
<rect x="40" y="40" width="120" height="120"
|
||||||
|
fill="white"/>
|
||||||
|
|
||||||
|
<!-- ID text below -->
|
||||||
|
<text x="100.0" y="220" text-anchor="middle"
|
||||||
|
font-family="Arial" font-size="14" font-weight="bold">
|
||||||
|
ID: 044
|
||||||
|
</text>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 687 B |
20
priv/static/apriltags/tag36h11_id_045.svg
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
<svg width="200" height="230" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<!-- White background -->
|
||||||
|
<rect width="200" height="230" fill="white"/>
|
||||||
|
|
||||||
|
<!-- AprilTag placeholder (simplified) -->
|
||||||
|
<rect x="20" y="20" width="160" height="160"
|
||||||
|
fill="white" stroke="black" stroke-width="2"/>
|
||||||
|
|
||||||
|
<!-- Simplified tag pattern - in reality this would be the actual AprilTag -->
|
||||||
|
<rect x="30" y="30" width="140" height="140"
|
||||||
|
fill="black"/>
|
||||||
|
<rect x="40" y="40" width="120" height="120"
|
||||||
|
fill="white"/>
|
||||||
|
|
||||||
|
<!-- ID text below -->
|
||||||
|
<text x="100.0" y="220" text-anchor="middle"
|
||||||
|
font-family="Arial" font-size="14" font-weight="bold">
|
||||||
|
ID: 045
|
||||||
|
</text>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 687 B |
20
priv/static/apriltags/tag36h11_id_046.svg
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
<svg width="200" height="230" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<!-- White background -->
|
||||||
|
<rect width="200" height="230" fill="white"/>
|
||||||
|
|
||||||
|
<!-- AprilTag placeholder (simplified) -->
|
||||||
|
<rect x="20" y="20" width="160" height="160"
|
||||||
|
fill="white" stroke="black" stroke-width="2"/>
|
||||||
|
|
||||||
|
<!-- Simplified tag pattern - in reality this would be the actual AprilTag -->
|
||||||
|
<rect x="30" y="30" width="140" height="140"
|
||||||
|
fill="black"/>
|
||||||
|
<rect x="40" y="40" width="120" height="120"
|
||||||
|
fill="white"/>
|
||||||
|
|
||||||
|
<!-- ID text below -->
|
||||||
|
<text x="100.0" y="220" text-anchor="middle"
|
||||||
|
font-family="Arial" font-size="14" font-weight="bold">
|
||||||
|
ID: 046
|
||||||
|
</text>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 687 B |
20
priv/static/apriltags/tag36h11_id_047.svg
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
<svg width="200" height="230" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<!-- White background -->
|
||||||
|
<rect width="200" height="230" fill="white"/>
|
||||||
|
|
||||||
|
<!-- AprilTag placeholder (simplified) -->
|
||||||
|
<rect x="20" y="20" width="160" height="160"
|
||||||
|
fill="white" stroke="black" stroke-width="2"/>
|
||||||
|
|
||||||
|
<!-- Simplified tag pattern - in reality this would be the actual AprilTag -->
|
||||||
|
<rect x="30" y="30" width="140" height="140"
|
||||||
|
fill="black"/>
|
||||||
|
<rect x="40" y="40" width="120" height="120"
|
||||||
|
fill="white"/>
|
||||||
|
|
||||||
|
<!-- ID text below -->
|
||||||
|
<text x="100.0" y="220" text-anchor="middle"
|
||||||
|
font-family="Arial" font-size="14" font-weight="bold">
|
||||||
|
ID: 047
|
||||||
|
</text>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 687 B |
20
priv/static/apriltags/tag36h11_id_048.svg
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
<svg width="200" height="230" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<!-- White background -->
|
||||||
|
<rect width="200" height="230" fill="white"/>
|
||||||
|
|
||||||
|
<!-- AprilTag placeholder (simplified) -->
|
||||||
|
<rect x="20" y="20" width="160" height="160"
|
||||||
|
fill="white" stroke="black" stroke-width="2"/>
|
||||||
|
|
||||||
|
<!-- Simplified tag pattern - in reality this would be the actual AprilTag -->
|
||||||
|
<rect x="30" y="30" width="140" height="140"
|
||||||
|
fill="black"/>
|
||||||
|
<rect x="40" y="40" width="120" height="120"
|
||||||
|
fill="white"/>
|
||||||
|
|
||||||
|
<!-- ID text below -->
|
||||||
|
<text x="100.0" y="220" text-anchor="middle"
|
||||||
|
font-family="Arial" font-size="14" font-weight="bold">
|
||||||
|
ID: 048
|
||||||
|
</text>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 687 B |
20
priv/static/apriltags/tag36h11_id_049.svg
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
<svg width="200" height="230" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<!-- White background -->
|
||||||
|
<rect width="200" height="230" fill="white"/>
|
||||||
|
|
||||||
|
<!-- AprilTag placeholder (simplified) -->
|
||||||
|
<rect x="20" y="20" width="160" height="160"
|
||||||
|
fill="white" stroke="black" stroke-width="2"/>
|
||||||
|
|
||||||
|
<!-- Simplified tag pattern - in reality this would be the actual AprilTag -->
|
||||||
|
<rect x="30" y="30" width="140" height="140"
|
||||||
|
fill="black"/>
|
||||||
|
<rect x="40" y="40" width="120" height="120"
|
||||||
|
fill="white"/>
|
||||||
|
|
||||||
|
<!-- ID text below -->
|
||||||
|
<text x="100.0" y="220" text-anchor="middle"
|
||||||
|
font-family="Arial" font-size="14" font-weight="bold">
|
||||||
|
ID: 049
|
||||||
|
</text>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 687 B |
20
priv/static/apriltags/tag36h11_id_050.svg
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
<svg width="200" height="230" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<!-- White background -->
|
||||||
|
<rect width="200" height="230" fill="white"/>
|
||||||
|
|
||||||
|
<!-- AprilTag placeholder (simplified) -->
|
||||||
|
<rect x="20" y="20" width="160" height="160"
|
||||||
|
fill="white" stroke="black" stroke-width="2"/>
|
||||||
|
|
||||||
|
<!-- Simplified tag pattern - in reality this would be the actual AprilTag -->
|
||||||
|
<rect x="30" y="30" width="140" height="140"
|
||||||
|
fill="black"/>
|
||||||
|
<rect x="40" y="40" width="120" height="120"
|
||||||
|
fill="white"/>
|
||||||
|
|
||||||
|
<!-- ID text below -->
|
||||||
|
<text x="100.0" y="220" text-anchor="middle"
|
||||||
|
font-family="Arial" font-size="14" font-weight="bold">
|
||||||
|
ID: 050
|
||||||
|
</text>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 687 B |
20
priv/static/apriltags/tag36h11_id_051.svg
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
<svg width="200" height="230" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<!-- White background -->
|
||||||
|
<rect width="200" height="230" fill="white"/>
|
||||||
|
|
||||||
|
<!-- AprilTag placeholder (simplified) -->
|
||||||
|
<rect x="20" y="20" width="160" height="160"
|
||||||
|
fill="white" stroke="black" stroke-width="2"/>
|
||||||
|
|
||||||
|
<!-- Simplified tag pattern - in reality this would be the actual AprilTag -->
|
||||||
|
<rect x="30" y="30" width="140" height="140"
|
||||||
|
fill="black"/>
|
||||||
|
<rect x="40" y="40" width="120" height="120"
|
||||||
|
fill="white"/>
|
||||||
|
|
||||||
|
<!-- ID text below -->
|
||||||
|
<text x="100.0" y="220" text-anchor="middle"
|
||||||
|
font-family="Arial" font-size="14" font-weight="bold">
|
||||||
|
ID: 051
|
||||||
|
</text>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 687 B |
20
priv/static/apriltags/tag36h11_id_052.svg
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
<svg width="200" height="230" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<!-- White background -->
|
||||||
|
<rect width="200" height="230" fill="white"/>
|
||||||
|
|
||||||
|
<!-- AprilTag placeholder (simplified) -->
|
||||||
|
<rect x="20" y="20" width="160" height="160"
|
||||||
|
fill="white" stroke="black" stroke-width="2"/>
|
||||||
|
|
||||||
|
<!-- Simplified tag pattern - in reality this would be the actual AprilTag -->
|
||||||
|
<rect x="30" y="30" width="140" height="140"
|
||||||
|
fill="black"/>
|
||||||
|
<rect x="40" y="40" width="120" height="120"
|
||||||
|
fill="white"/>
|
||||||
|
|
||||||
|
<!-- ID text below -->
|
||||||
|
<text x="100.0" y="220" text-anchor="middle"
|
||||||
|
font-family="Arial" font-size="14" font-weight="bold">
|
||||||
|
ID: 052
|
||||||
|
</text>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 687 B |
20
priv/static/apriltags/tag36h11_id_053.svg
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
<svg width="200" height="230" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<!-- White background -->
|
||||||
|
<rect width="200" height="230" fill="white"/>
|
||||||
|
|
||||||
|
<!-- AprilTag placeholder (simplified) -->
|
||||||
|
<rect x="20" y="20" width="160" height="160"
|
||||||
|
fill="white" stroke="black" stroke-width="2"/>
|
||||||
|
|
||||||
|
<!-- Simplified tag pattern - in reality this would be the actual AprilTag -->
|
||||||
|
<rect x="30" y="30" width="140" height="140"
|
||||||
|
fill="black"/>
|
||||||
|
<rect x="40" y="40" width="120" height="120"
|
||||||
|
fill="white"/>
|
||||||
|
|
||||||
|
<!-- ID text below -->
|
||||||
|
<text x="100.0" y="220" text-anchor="middle"
|
||||||
|
font-family="Arial" font-size="14" font-weight="bold">
|
||||||
|
ID: 053
|
||||||
|
</text>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 687 B |
20
priv/static/apriltags/tag36h11_id_054.svg
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
<svg width="200" height="230" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<!-- White background -->
|
||||||
|
<rect width="200" height="230" fill="white"/>
|
||||||
|
|
||||||
|
<!-- AprilTag placeholder (simplified) -->
|
||||||
|
<rect x="20" y="20" width="160" height="160"
|
||||||
|
fill="white" stroke="black" stroke-width="2"/>
|
||||||
|
|
||||||
|
<!-- Simplified tag pattern - in reality this would be the actual AprilTag -->
|
||||||
|
<rect x="30" y="30" width="140" height="140"
|
||||||
|
fill="black"/>
|
||||||
|
<rect x="40" y="40" width="120" height="120"
|
||||||
|
fill="white"/>
|
||||||
|
|
||||||
|
<!-- ID text below -->
|
||||||
|
<text x="100.0" y="220" text-anchor="middle"
|
||||||
|
font-family="Arial" font-size="14" font-weight="bold">
|
||||||
|
ID: 054
|
||||||
|
</text>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 687 B |
20
priv/static/apriltags/tag36h11_id_055.svg
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
<svg width="200" height="230" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<!-- White background -->
|
||||||
|
<rect width="200" height="230" fill="white"/>
|
||||||
|
|
||||||
|
<!-- AprilTag placeholder (simplified) -->
|
||||||
|
<rect x="20" y="20" width="160" height="160"
|
||||||
|
fill="white" stroke="black" stroke-width="2"/>
|
||||||
|
|
||||||
|
<!-- Simplified tag pattern - in reality this would be the actual AprilTag -->
|
||||||
|
<rect x="30" y="30" width="140" height="140"
|
||||||
|
fill="black"/>
|
||||||
|
<rect x="40" y="40" width="120" height="120"
|
||||||
|
fill="white"/>
|
||||||
|
|
||||||
|
<!-- ID text below -->
|
||||||
|
<text x="100.0" y="220" text-anchor="middle"
|
||||||
|
font-family="Arial" font-size="14" font-weight="bold">
|
||||||
|
ID: 055
|
||||||
|
</text>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 687 B |
20
priv/static/apriltags/tag36h11_id_056.svg
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
<svg width="200" height="230" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<!-- White background -->
|
||||||
|
<rect width="200" height="230" fill="white"/>
|
||||||
|
|
||||||
|
<!-- AprilTag placeholder (simplified) -->
|
||||||
|
<rect x="20" y="20" width="160" height="160"
|
||||||
|
fill="white" stroke="black" stroke-width="2"/>
|
||||||
|
|
||||||
|
<!-- Simplified tag pattern - in reality this would be the actual AprilTag -->
|
||||||
|
<rect x="30" y="30" width="140" height="140"
|
||||||
|
fill="black"/>
|
||||||
|
<rect x="40" y="40" width="120" height="120"
|
||||||
|
fill="white"/>
|
||||||
|
|
||||||
|
<!-- ID text below -->
|
||||||
|
<text x="100.0" y="220" text-anchor="middle"
|
||||||
|
font-family="Arial" font-size="14" font-weight="bold">
|
||||||
|
ID: 056
|
||||||
|
</text>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 687 B |
20
priv/static/apriltags/tag36h11_id_057.svg
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
<svg width="200" height="230" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<!-- White background -->
|
||||||
|
<rect width="200" height="230" fill="white"/>
|
||||||
|
|
||||||
|
<!-- AprilTag placeholder (simplified) -->
|
||||||
|
<rect x="20" y="20" width="160" height="160"
|
||||||
|
fill="white" stroke="black" stroke-width="2"/>
|
||||||
|
|
||||||
|
<!-- Simplified tag pattern - in reality this would be the actual AprilTag -->
|
||||||
|
<rect x="30" y="30" width="140" height="140"
|
||||||
|
fill="black"/>
|
||||||
|
<rect x="40" y="40" width="120" height="120"
|
||||||
|
fill="white"/>
|
||||||
|
|
||||||
|
<!-- ID text below -->
|
||||||
|
<text x="100.0" y="220" text-anchor="middle"
|
||||||
|
font-family="Arial" font-size="14" font-weight="bold">
|
||||||
|
ID: 057
|
||||||
|
</text>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 687 B |
20
priv/static/apriltags/tag36h11_id_058.svg
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
<svg width="200" height="230" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<!-- White background -->
|
||||||
|
<rect width="200" height="230" fill="white"/>
|
||||||
|
|
||||||
|
<!-- AprilTag placeholder (simplified) -->
|
||||||
|
<rect x="20" y="20" width="160" height="160"
|
||||||
|
fill="white" stroke="black" stroke-width="2"/>
|
||||||
|
|
||||||
|
<!-- Simplified tag pattern - in reality this would be the actual AprilTag -->
|
||||||
|
<rect x="30" y="30" width="140" height="140"
|
||||||
|
fill="black"/>
|
||||||
|
<rect x="40" y="40" width="120" height="120"
|
||||||
|
fill="white"/>
|
||||||
|
|
||||||
|
<!-- ID text below -->
|
||||||
|
<text x="100.0" y="220" text-anchor="middle"
|
||||||
|
font-family="Arial" font-size="14" font-weight="bold">
|
||||||
|
ID: 058
|
||||||
|
</text>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 687 B |
20
priv/static/apriltags/tag36h11_id_059.svg
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
<svg width="200" height="230" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<!-- White background -->
|
||||||
|
<rect width="200" height="230" fill="white"/>
|
||||||
|
|
||||||
|
<!-- AprilTag placeholder (simplified) -->
|
||||||
|
<rect x="20" y="20" width="160" height="160"
|
||||||
|
fill="white" stroke="black" stroke-width="2"/>
|
||||||
|
|
||||||
|
<!-- Simplified tag pattern - in reality this would be the actual AprilTag -->
|
||||||
|
<rect x="30" y="30" width="140" height="140"
|
||||||
|
fill="black"/>
|
||||||
|
<rect x="40" y="40" width="120" height="120"
|
||||||
|
fill="white"/>
|
||||||
|
|
||||||
|
<!-- ID text below -->
|
||||||
|
<text x="100.0" y="220" text-anchor="middle"
|
||||||
|
font-family="Arial" font-size="14" font-weight="bold">
|
||||||
|
ID: 059
|
||||||
|
</text>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 687 B |
20
priv/static/apriltags/tag36h11_id_060.svg
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
<svg width="200" height="230" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<!-- White background -->
|
||||||
|
<rect width="200" height="230" fill="white"/>
|
||||||
|
|
||||||
|
<!-- AprilTag placeholder (simplified) -->
|
||||||
|
<rect x="20" y="20" width="160" height="160"
|
||||||
|
fill="white" stroke="black" stroke-width="2"/>
|
||||||
|
|
||||||
|
<!-- Simplified tag pattern - in reality this would be the actual AprilTag -->
|
||||||
|
<rect x="30" y="30" width="140" height="140"
|
||||||
|
fill="black"/>
|
||||||
|
<rect x="40" y="40" width="120" height="120"
|
||||||
|
fill="white"/>
|
||||||
|
|
||||||
|
<!-- ID text below -->
|
||||||
|
<text x="100.0" y="220" text-anchor="middle"
|
||||||
|
font-family="Arial" font-size="14" font-weight="bold">
|
||||||
|
ID: 060
|
||||||
|
</text>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 687 B |
20
priv/static/apriltags/tag36h11_id_061.svg
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
<svg width="200" height="230" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<!-- White background -->
|
||||||
|
<rect width="200" height="230" fill="white"/>
|
||||||
|
|
||||||
|
<!-- AprilTag placeholder (simplified) -->
|
||||||
|
<rect x="20" y="20" width="160" height="160"
|
||||||
|
fill="white" stroke="black" stroke-width="2"/>
|
||||||
|
|
||||||
|
<!-- Simplified tag pattern - in reality this would be the actual AprilTag -->
|
||||||
|
<rect x="30" y="30" width="140" height="140"
|
||||||
|
fill="black"/>
|
||||||
|
<rect x="40" y="40" width="120" height="120"
|
||||||
|
fill="white"/>
|
||||||
|
|
||||||
|
<!-- ID text below -->
|
||||||
|
<text x="100.0" y="220" text-anchor="middle"
|
||||||
|
font-family="Arial" font-size="14" font-weight="bold">
|
||||||
|
ID: 061
|
||||||
|
</text>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 687 B |
20
priv/static/apriltags/tag36h11_id_062.svg
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
<svg width="200" height="230" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<!-- White background -->
|
||||||
|
<rect width="200" height="230" fill="white"/>
|
||||||
|
|
||||||
|
<!-- AprilTag placeholder (simplified) -->
|
||||||
|
<rect x="20" y="20" width="160" height="160"
|
||||||
|
fill="white" stroke="black" stroke-width="2"/>
|
||||||
|
|
||||||
|
<!-- Simplified tag pattern - in reality this would be the actual AprilTag -->
|
||||||
|
<rect x="30" y="30" width="140" height="140"
|
||||||
|
fill="black"/>
|
||||||
|
<rect x="40" y="40" width="120" height="120"
|
||||||
|
fill="white"/>
|
||||||
|
|
||||||
|
<!-- ID text below -->
|
||||||
|
<text x="100.0" y="220" text-anchor="middle"
|
||||||
|
font-family="Arial" font-size="14" font-weight="bold">
|
||||||
|
ID: 062
|
||||||
|
</text>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 687 B |
20
priv/static/apriltags/tag36h11_id_063.svg
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
<svg width="200" height="230" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<!-- White background -->
|
||||||
|
<rect width="200" height="230" fill="white"/>
|
||||||
|
|
||||||
|
<!-- AprilTag placeholder (simplified) -->
|
||||||
|
<rect x="20" y="20" width="160" height="160"
|
||||||
|
fill="white" stroke="black" stroke-width="2"/>
|
||||||
|
|
||||||
|
<!-- Simplified tag pattern - in reality this would be the actual AprilTag -->
|
||||||
|
<rect x="30" y="30" width="140" height="140"
|
||||||
|
fill="black"/>
|
||||||
|
<rect x="40" y="40" width="120" height="120"
|
||||||
|
fill="white"/>
|
||||||
|
|
||||||
|
<!-- ID text below -->
|
||||||
|
<text x="100.0" y="220" text-anchor="middle"
|
||||||
|
font-family="Arial" font-size="14" font-weight="bold">
|
||||||
|
ID: 063
|
||||||
|
</text>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 687 B |
20
priv/static/apriltags/tag36h11_id_064.svg
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
<svg width="200" height="230" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<!-- White background -->
|
||||||
|
<rect width="200" height="230" fill="white"/>
|
||||||
|
|
||||||
|
<!-- AprilTag placeholder (simplified) -->
|
||||||
|
<rect x="20" y="20" width="160" height="160"
|
||||||
|
fill="white" stroke="black" stroke-width="2"/>
|
||||||
|
|
||||||
|
<!-- Simplified tag pattern - in reality this would be the actual AprilTag -->
|
||||||
|
<rect x="30" y="30" width="140" height="140"
|
||||||
|
fill="black"/>
|
||||||
|
<rect x="40" y="40" width="120" height="120"
|
||||||
|
fill="white"/>
|
||||||
|
|
||||||
|
<!-- ID text below -->
|
||||||
|
<text x="100.0" y="220" text-anchor="middle"
|
||||||
|
font-family="Arial" font-size="14" font-weight="bold">
|
||||||
|
ID: 064
|
||||||
|
</text>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 687 B |
20
priv/static/apriltags/tag36h11_id_065.svg
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
<svg width="200" height="230" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<!-- White background -->
|
||||||
|
<rect width="200" height="230" fill="white"/>
|
||||||
|
|
||||||
|
<!-- AprilTag placeholder (simplified) -->
|
||||||
|
<rect x="20" y="20" width="160" height="160"
|
||||||
|
fill="white" stroke="black" stroke-width="2"/>
|
||||||
|
|
||||||
|
<!-- Simplified tag pattern - in reality this would be the actual AprilTag -->
|
||||||
|
<rect x="30" y="30" width="140" height="140"
|
||||||
|
fill="black"/>
|
||||||
|
<rect x="40" y="40" width="120" height="120"
|
||||||
|
fill="white"/>
|
||||||
|
|
||||||
|
<!-- ID text below -->
|
||||||
|
<text x="100.0" y="220" text-anchor="middle"
|
||||||
|
font-family="Arial" font-size="14" font-weight="bold">
|
||||||
|
ID: 065
|
||||||
|
</text>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 687 B |
20
priv/static/apriltags/tag36h11_id_066.svg
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
<svg width="200" height="230" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<!-- White background -->
|
||||||
|
<rect width="200" height="230" fill="white"/>
|
||||||
|
|
||||||
|
<!-- AprilTag placeholder (simplified) -->
|
||||||
|
<rect x="20" y="20" width="160" height="160"
|
||||||
|
fill="white" stroke="black" stroke-width="2"/>
|
||||||
|
|
||||||
|
<!-- Simplified tag pattern - in reality this would be the actual AprilTag -->
|
||||||
|
<rect x="30" y="30" width="140" height="140"
|
||||||
|
fill="black"/>
|
||||||
|
<rect x="40" y="40" width="120" height="120"
|
||||||
|
fill="white"/>
|
||||||
|
|
||||||
|
<!-- ID text below -->
|
||||||
|
<text x="100.0" y="220" text-anchor="middle"
|
||||||
|
font-family="Arial" font-size="14" font-weight="bold">
|
||||||
|
ID: 066
|
||||||
|
</text>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 687 B |
20
priv/static/apriltags/tag36h11_id_067.svg
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
<svg width="200" height="230" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<!-- White background -->
|
||||||
|
<rect width="200" height="230" fill="white"/>
|
||||||
|
|
||||||
|
<!-- AprilTag placeholder (simplified) -->
|
||||||
|
<rect x="20" y="20" width="160" height="160"
|
||||||
|
fill="white" stroke="black" stroke-width="2"/>
|
||||||
|
|
||||||
|
<!-- Simplified tag pattern - in reality this would be the actual AprilTag -->
|
||||||
|
<rect x="30" y="30" width="140" height="140"
|
||||||
|
fill="black"/>
|
||||||
|
<rect x="40" y="40" width="120" height="120"
|
||||||
|
fill="white"/>
|
||||||
|
|
||||||
|
<!-- ID text below -->
|
||||||
|
<text x="100.0" y="220" text-anchor="middle"
|
||||||
|
font-family="Arial" font-size="14" font-weight="bold">
|
||||||
|
ID: 067
|
||||||
|
</text>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 687 B |
20
priv/static/apriltags/tag36h11_id_068.svg
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
<svg width="200" height="230" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<!-- White background -->
|
||||||
|
<rect width="200" height="230" fill="white"/>
|
||||||
|
|
||||||
|
<!-- AprilTag placeholder (simplified) -->
|
||||||
|
<rect x="20" y="20" width="160" height="160"
|
||||||
|
fill="white" stroke="black" stroke-width="2"/>
|
||||||
|
|
||||||
|
<!-- Simplified tag pattern - in reality this would be the actual AprilTag -->
|
||||||
|
<rect x="30" y="30" width="140" height="140"
|
||||||
|
fill="black"/>
|
||||||
|
<rect x="40" y="40" width="120" height="120"
|
||||||
|
fill="white"/>
|
||||||
|
|
||||||
|
<!-- ID text below -->
|
||||||
|
<text x="100.0" y="220" text-anchor="middle"
|
||||||
|
font-family="Arial" font-size="14" font-weight="bold">
|
||||||
|
ID: 068
|
||||||
|
</text>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 687 B |
20
priv/static/apriltags/tag36h11_id_069.svg
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
<svg width="200" height="230" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<!-- White background -->
|
||||||
|
<rect width="200" height="230" fill="white"/>
|
||||||
|
|
||||||
|
<!-- AprilTag placeholder (simplified) -->
|
||||||
|
<rect x="20" y="20" width="160" height="160"
|
||||||
|
fill="white" stroke="black" stroke-width="2"/>
|
||||||
|
|
||||||
|
<!-- Simplified tag pattern - in reality this would be the actual AprilTag -->
|
||||||
|
<rect x="30" y="30" width="140" height="140"
|
||||||
|
fill="black"/>
|
||||||
|
<rect x="40" y="40" width="120" height="120"
|
||||||
|
fill="white"/>
|
||||||
|
|
||||||
|
<!-- ID text below -->
|
||||||
|
<text x="100.0" y="220" text-anchor="middle"
|
||||||
|
font-family="Arial" font-size="14" font-weight="bold">
|
||||||
|
ID: 069
|
||||||
|
</text>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 687 B |
20
priv/static/apriltags/tag36h11_id_070.svg
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
<svg width="200" height="230" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<!-- White background -->
|
||||||
|
<rect width="200" height="230" fill="white"/>
|
||||||
|
|
||||||
|
<!-- AprilTag placeholder (simplified) -->
|
||||||
|
<rect x="20" y="20" width="160" height="160"
|
||||||
|
fill="white" stroke="black" stroke-width="2"/>
|
||||||
|
|
||||||
|
<!-- Simplified tag pattern - in reality this would be the actual AprilTag -->
|
||||||
|
<rect x="30" y="30" width="140" height="140"
|
||||||
|
fill="black"/>
|
||||||
|
<rect x="40" y="40" width="120" height="120"
|
||||||
|
fill="white"/>
|
||||||
|
|
||||||
|
<!-- ID text below -->
|
||||||
|
<text x="100.0" y="220" text-anchor="middle"
|
||||||
|
font-family="Arial" font-size="14" font-weight="bold">
|
||||||
|
ID: 070
|
||||||
|
</text>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 687 B |
20
priv/static/apriltags/tag36h11_id_071.svg
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
<svg width="200" height="230" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<!-- White background -->
|
||||||
|
<rect width="200" height="230" fill="white"/>
|
||||||
|
|
||||||
|
<!-- AprilTag placeholder (simplified) -->
|
||||||
|
<rect x="20" y="20" width="160" height="160"
|
||||||
|
fill="white" stroke="black" stroke-width="2"/>
|
||||||
|
|
||||||
|
<!-- Simplified tag pattern - in reality this would be the actual AprilTag -->
|
||||||
|
<rect x="30" y="30" width="140" height="140"
|
||||||
|
fill="black"/>
|
||||||
|
<rect x="40" y="40" width="120" height="120"
|
||||||
|
fill="white"/>
|
||||||
|
|
||||||
|
<!-- ID text below -->
|
||||||
|
<text x="100.0" y="220" text-anchor="middle"
|
||||||
|
font-family="Arial" font-size="14" font-weight="bold">
|
||||||
|
ID: 071
|
||||||
|
</text>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 687 B |
20
priv/static/apriltags/tag36h11_id_072.svg
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
<svg width="200" height="230" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<!-- White background -->
|
||||||
|
<rect width="200" height="230" fill="white"/>
|
||||||
|
|
||||||
|
<!-- AprilTag placeholder (simplified) -->
|
||||||
|
<rect x="20" y="20" width="160" height="160"
|
||||||
|
fill="white" stroke="black" stroke-width="2"/>
|
||||||
|
|
||||||
|
<!-- Simplified tag pattern - in reality this would be the actual AprilTag -->
|
||||||
|
<rect x="30" y="30" width="140" height="140"
|
||||||
|
fill="black"/>
|
||||||
|
<rect x="40" y="40" width="120" height="120"
|
||||||
|
fill="white"/>
|
||||||
|
|
||||||
|
<!-- ID text below -->
|
||||||
|
<text x="100.0" y="220" text-anchor="middle"
|
||||||
|
font-family="Arial" font-size="14" font-weight="bold">
|
||||||
|
ID: 072
|
||||||
|
</text>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 687 B |
20
priv/static/apriltags/tag36h11_id_073.svg
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
<svg width="200" height="230" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<!-- White background -->
|
||||||
|
<rect width="200" height="230" fill="white"/>
|
||||||
|
|
||||||
|
<!-- AprilTag placeholder (simplified) -->
|
||||||
|
<rect x="20" y="20" width="160" height="160"
|
||||||
|
fill="white" stroke="black" stroke-width="2"/>
|
||||||
|
|
||||||
|
<!-- Simplified tag pattern - in reality this would be the actual AprilTag -->
|
||||||
|
<rect x="30" y="30" width="140" height="140"
|
||||||
|
fill="black"/>
|
||||||
|
<rect x="40" y="40" width="120" height="120"
|
||||||
|
fill="white"/>
|
||||||
|
|
||||||
|
<!-- ID text below -->
|
||||||
|
<text x="100.0" y="220" text-anchor="middle"
|
||||||
|
font-family="Arial" font-size="14" font-weight="bold">
|
||||||
|
ID: 073
|
||||||
|
</text>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 687 B |
20
priv/static/apriltags/tag36h11_id_074.svg
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
<svg width="200" height="230" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<!-- White background -->
|
||||||
|
<rect width="200" height="230" fill="white"/>
|
||||||
|
|
||||||
|
<!-- AprilTag placeholder (simplified) -->
|
||||||
|
<rect x="20" y="20" width="160" height="160"
|
||||||
|
fill="white" stroke="black" stroke-width="2"/>
|
||||||
|
|
||||||
|
<!-- Simplified tag pattern - in reality this would be the actual AprilTag -->
|
||||||
|
<rect x="30" y="30" width="140" height="140"
|
||||||
|
fill="black"/>
|
||||||
|
<rect x="40" y="40" width="120" height="120"
|
||||||
|
fill="white"/>
|
||||||
|
|
||||||
|
<!-- ID text below -->
|
||||||
|
<text x="100.0" y="220" text-anchor="middle"
|
||||||
|
font-family="Arial" font-size="14" font-weight="bold">
|
||||||
|
ID: 074
|
||||||
|
</text>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 687 B |
20
priv/static/apriltags/tag36h11_id_075.svg
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
<svg width="200" height="230" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<!-- White background -->
|
||||||
|
<rect width="200" height="230" fill="white"/>
|
||||||
|
|
||||||
|
<!-- AprilTag placeholder (simplified) -->
|
||||||
|
<rect x="20" y="20" width="160" height="160"
|
||||||
|
fill="white" stroke="black" stroke-width="2"/>
|
||||||
|
|
||||||
|
<!-- Simplified tag pattern - in reality this would be the actual AprilTag -->
|
||||||
|
<rect x="30" y="30" width="140" height="140"
|
||||||
|
fill="black"/>
|
||||||
|
<rect x="40" y="40" width="120" height="120"
|
||||||
|
fill="white"/>
|
||||||
|
|
||||||
|
<!-- ID text below -->
|
||||||
|
<text x="100.0" y="220" text-anchor="middle"
|
||||||
|
font-family="Arial" font-size="14" font-weight="bold">
|
||||||
|
ID: 075
|
||||||
|
</text>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 687 B |
20
priv/static/apriltags/tag36h11_id_076.svg
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
<svg width="200" height="230" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<!-- White background -->
|
||||||
|
<rect width="200" height="230" fill="white"/>
|
||||||
|
|
||||||
|
<!-- AprilTag placeholder (simplified) -->
|
||||||
|
<rect x="20" y="20" width="160" height="160"
|
||||||
|
fill="white" stroke="black" stroke-width="2"/>
|
||||||
|
|
||||||
|
<!-- Simplified tag pattern - in reality this would be the actual AprilTag -->
|
||||||
|
<rect x="30" y="30" width="140" height="140"
|
||||||
|
fill="black"/>
|
||||||
|
<rect x="40" y="40" width="120" height="120"
|
||||||
|
fill="white"/>
|
||||||
|
|
||||||
|
<!-- ID text below -->
|
||||||
|
<text x="100.0" y="220" text-anchor="middle"
|
||||||
|
font-family="Arial" font-size="14" font-weight="bold">
|
||||||
|
ID: 076
|
||||||
|
</text>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 687 B |
20
priv/static/apriltags/tag36h11_id_077.svg
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
<svg width="200" height="230" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<!-- White background -->
|
||||||
|
<rect width="200" height="230" fill="white"/>
|
||||||
|
|
||||||
|
<!-- AprilTag placeholder (simplified) -->
|
||||||
|
<rect x="20" y="20" width="160" height="160"
|
||||||
|
fill="white" stroke="black" stroke-width="2"/>
|
||||||
|
|
||||||
|
<!-- Simplified tag pattern - in reality this would be the actual AprilTag -->
|
||||||
|
<rect x="30" y="30" width="140" height="140"
|
||||||
|
fill="black"/>
|
||||||
|
<rect x="40" y="40" width="120" height="120"
|
||||||
|
fill="white"/>
|
||||||
|
|
||||||
|
<!-- ID text below -->
|
||||||
|
<text x="100.0" y="220" text-anchor="middle"
|
||||||
|
font-family="Arial" font-size="14" font-weight="bold">
|
||||||
|
ID: 077
|
||||||
|
</text>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 687 B |
20
priv/static/apriltags/tag36h11_id_078.svg
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
<svg width="200" height="230" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<!-- White background -->
|
||||||
|
<rect width="200" height="230" fill="white"/>
|
||||||
|
|
||||||
|
<!-- AprilTag placeholder (simplified) -->
|
||||||
|
<rect x="20" y="20" width="160" height="160"
|
||||||
|
fill="white" stroke="black" stroke-width="2"/>
|
||||||
|
|
||||||
|
<!-- Simplified tag pattern - in reality this would be the actual AprilTag -->
|
||||||
|
<rect x="30" y="30" width="140" height="140"
|
||||||
|
fill="black"/>
|
||||||
|
<rect x="40" y="40" width="120" height="120"
|
||||||
|
fill="white"/>
|
||||||
|
|
||||||
|
<!-- ID text below -->
|
||||||
|
<text x="100.0" y="220" text-anchor="middle"
|
||||||
|
font-family="Arial" font-size="14" font-weight="bold">
|
||||||
|
ID: 078
|
||||||
|
</text>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 687 B |
20
priv/static/apriltags/tag36h11_id_079.svg
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
<svg width="200" height="230" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<!-- White background -->
|
||||||
|
<rect width="200" height="230" fill="white"/>
|
||||||
|
|
||||||
|
<!-- AprilTag placeholder (simplified) -->
|
||||||
|
<rect x="20" y="20" width="160" height="160"
|
||||||
|
fill="white" stroke="black" stroke-width="2"/>
|
||||||
|
|
||||||
|
<!-- Simplified tag pattern - in reality this would be the actual AprilTag -->
|
||||||
|
<rect x="30" y="30" width="140" height="140"
|
||||||
|
fill="black"/>
|
||||||
|
<rect x="40" y="40" width="120" height="120"
|
||||||
|
fill="white"/>
|
||||||
|
|
||||||
|
<!-- ID text below -->
|
||||||
|
<text x="100.0" y="220" text-anchor="middle"
|
||||||
|
font-family="Arial" font-size="14" font-weight="bold">
|
||||||
|
ID: 079
|
||||||
|
</text>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 687 B |
20
priv/static/apriltags/tag36h11_id_080.svg
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
<svg width="200" height="230" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<!-- White background -->
|
||||||
|
<rect width="200" height="230" fill="white"/>
|
||||||
|
|
||||||
|
<!-- AprilTag placeholder (simplified) -->
|
||||||
|
<rect x="20" y="20" width="160" height="160"
|
||||||
|
fill="white" stroke="black" stroke-width="2"/>
|
||||||
|
|
||||||
|
<!-- Simplified tag pattern - in reality this would be the actual AprilTag -->
|
||||||
|
<rect x="30" y="30" width="140" height="140"
|
||||||
|
fill="black"/>
|
||||||
|
<rect x="40" y="40" width="120" height="120"
|
||||||
|
fill="white"/>
|
||||||
|
|
||||||
|
<!-- ID text below -->
|
||||||
|
<text x="100.0" y="220" text-anchor="middle"
|
||||||
|
font-family="Arial" font-size="14" font-weight="bold">
|
||||||
|
ID: 080
|
||||||
|
</text>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 687 B |
20
priv/static/apriltags/tag36h11_id_081.svg
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
<svg width="200" height="230" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<!-- White background -->
|
||||||
|
<rect width="200" height="230" fill="white"/>
|
||||||
|
|
||||||
|
<!-- AprilTag placeholder (simplified) -->
|
||||||
|
<rect x="20" y="20" width="160" height="160"
|
||||||
|
fill="white" stroke="black" stroke-width="2"/>
|
||||||
|
|
||||||
|
<!-- Simplified tag pattern - in reality this would be the actual AprilTag -->
|
||||||
|
<rect x="30" y="30" width="140" height="140"
|
||||||
|
fill="black"/>
|
||||||
|
<rect x="40" y="40" width="120" height="120"
|
||||||
|
fill="white"/>
|
||||||
|
|
||||||
|
<!-- ID text below -->
|
||||||
|
<text x="100.0" y="220" text-anchor="middle"
|
||||||
|
font-family="Arial" font-size="14" font-weight="bold">
|
||||||
|
ID: 081
|
||||||
|
</text>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 687 B |
20
priv/static/apriltags/tag36h11_id_082.svg
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
<svg width="200" height="230" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<!-- White background -->
|
||||||
|
<rect width="200" height="230" fill="white"/>
|
||||||
|
|
||||||
|
<!-- AprilTag placeholder (simplified) -->
|
||||||
|
<rect x="20" y="20" width="160" height="160"
|
||||||
|
fill="white" stroke="black" stroke-width="2"/>
|
||||||
|
|
||||||
|
<!-- Simplified tag pattern - in reality this would be the actual AprilTag -->
|
||||||
|
<rect x="30" y="30" width="140" height="140"
|
||||||
|
fill="black"/>
|
||||||
|
<rect x="40" y="40" width="120" height="120"
|
||||||
|
fill="white"/>
|
||||||
|
|
||||||
|
<!-- ID text below -->
|
||||||
|
<text x="100.0" y="220" text-anchor="middle"
|
||||||
|
font-family="Arial" font-size="14" font-weight="bold">
|
||||||
|
ID: 082
|
||||||
|
</text>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 687 B |
20
priv/static/apriltags/tag36h11_id_083.svg
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
<svg width="200" height="230" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<!-- White background -->
|
||||||
|
<rect width="200" height="230" fill="white"/>
|
||||||
|
|
||||||
|
<!-- AprilTag placeholder (simplified) -->
|
||||||
|
<rect x="20" y="20" width="160" height="160"
|
||||||
|
fill="white" stroke="black" stroke-width="2"/>
|
||||||
|
|
||||||
|
<!-- Simplified tag pattern - in reality this would be the actual AprilTag -->
|
||||||
|
<rect x="30" y="30" width="140" height="140"
|
||||||
|
fill="black"/>
|
||||||
|
<rect x="40" y="40" width="120" height="120"
|
||||||
|
fill="white"/>
|
||||||
|
|
||||||
|
<!-- ID text below -->
|
||||||
|
<text x="100.0" y="220" text-anchor="middle"
|
||||||
|
font-family="Arial" font-size="14" font-weight="bold">
|
||||||
|
ID: 083
|
||||||
|
</text>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 687 B |
20
priv/static/apriltags/tag36h11_id_084.svg
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
<svg width="200" height="230" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<!-- White background -->
|
||||||
|
<rect width="200" height="230" fill="white"/>
|
||||||
|
|
||||||
|
<!-- AprilTag placeholder (simplified) -->
|
||||||
|
<rect x="20" y="20" width="160" height="160"
|
||||||
|
fill="white" stroke="black" stroke-width="2"/>
|
||||||
|
|
||||||
|
<!-- Simplified tag pattern - in reality this would be the actual AprilTag -->
|
||||||
|
<rect x="30" y="30" width="140" height="140"
|
||||||
|
fill="black"/>
|
||||||
|
<rect x="40" y="40" width="120" height="120"
|
||||||
|
fill="white"/>
|
||||||
|
|
||||||
|
<!-- ID text below -->
|
||||||
|
<text x="100.0" y="220" text-anchor="middle"
|
||||||
|
font-family="Arial" font-size="14" font-weight="bold">
|
||||||
|
ID: 084
|
||||||
|
</text>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 687 B |
20
priv/static/apriltags/tag36h11_id_085.svg
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
<svg width="200" height="230" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<!-- White background -->
|
||||||
|
<rect width="200" height="230" fill="white"/>
|
||||||
|
|
||||||
|
<!-- AprilTag placeholder (simplified) -->
|
||||||
|
<rect x="20" y="20" width="160" height="160"
|
||||||
|
fill="white" stroke="black" stroke-width="2"/>
|
||||||
|
|
||||||
|
<!-- Simplified tag pattern - in reality this would be the actual AprilTag -->
|
||||||
|
<rect x="30" y="30" width="140" height="140"
|
||||||
|
fill="black"/>
|
||||||
|
<rect x="40" y="40" width="120" height="120"
|
||||||
|
fill="white"/>
|
||||||
|
|
||||||
|
<!-- ID text below -->
|
||||||
|
<text x="100.0" y="220" text-anchor="middle"
|
||||||
|
font-family="Arial" font-size="14" font-weight="bold">
|
||||||
|
ID: 085
|
||||||
|
</text>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 687 B |
20
priv/static/apriltags/tag36h11_id_086.svg
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
<svg width="200" height="230" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<!-- White background -->
|
||||||
|
<rect width="200" height="230" fill="white"/>
|
||||||
|
|
||||||
|
<!-- AprilTag placeholder (simplified) -->
|
||||||
|
<rect x="20" y="20" width="160" height="160"
|
||||||
|
fill="white" stroke="black" stroke-width="2"/>
|
||||||
|
|
||||||
|
<!-- Simplified tag pattern - in reality this would be the actual AprilTag -->
|
||||||
|
<rect x="30" y="30" width="140" height="140"
|
||||||
|
fill="black"/>
|
||||||
|
<rect x="40" y="40" width="120" height="120"
|
||||||
|
fill="white"/>
|
||||||
|
|
||||||
|
<!-- ID text below -->
|
||||||
|
<text x="100.0" y="220" text-anchor="middle"
|
||||||
|
font-family="Arial" font-size="14" font-weight="bold">
|
||||||
|
ID: 086
|
||||||
|
</text>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 687 B |