calibrate-suite 0.1.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (47) hide show
  1. calibrate_suite-0.1.0.dist-info/METADATA +761 -0
  2. calibrate_suite-0.1.0.dist-info/RECORD +47 -0
  3. calibrate_suite-0.1.0.dist-info/WHEEL +5 -0
  4. calibrate_suite-0.1.0.dist-info/entry_points.txt +3 -0
  5. calibrate_suite-0.1.0.dist-info/licenses/LICENSE +201 -0
  6. calibrate_suite-0.1.0.dist-info/top_level.txt +4 -0
  7. fleet_server/__init__.py +32 -0
  8. fleet_server/app.py +377 -0
  9. fleet_server/config.py +91 -0
  10. fleet_server/templates/error.html +57 -0
  11. fleet_server/templates/index.html +137 -0
  12. fleet_server/templates/viewer.html +490 -0
  13. fleet_server/utils.py +178 -0
  14. gui/__init__.py +2 -0
  15. gui/assets/2d-or-3d-fleet-upload.png +0 -0
  16. gui/assets/2d_3d_overlay_output.jpg +0 -0
  17. gui/assets/3d-or-2d-overlay_page.png +0 -0
  18. gui/assets/3d-or-2d-record-page.png +0 -0
  19. gui/assets/3d_3d_overlay_output.png +0 -0
  20. gui/assets/3d_or_2d_calibrate-page.png +0 -0
  21. gui/assets/GUI_homepage.png +0 -0
  22. gui/assets/hardware_setup.jpeg +0 -0
  23. gui/assets/single_lidar_calibrate_page.png +0 -0
  24. gui/assets/single_lidar_output.png +0 -0
  25. gui/assets/single_lidar_record_page.png +0 -0
  26. gui/assets/virya.jpg +0 -0
  27. gui/main.py +23 -0
  28. gui/widgets/calibrator_widget.py +977 -0
  29. gui/widgets/extractor_widget.py +561 -0
  30. gui/widgets/home_widget.py +117 -0
  31. gui/widgets/recorder_widget.py +127 -0
  32. gui/widgets/single_lidar_widget.py +673 -0
  33. gui/widgets/three_d_calib_widget.py +87 -0
  34. gui/widgets/two_d_calib_widget.py +86 -0
  35. gui/widgets/uploader_widget.py +151 -0
  36. gui/widgets/validator_widget.py +614 -0
  37. gui/windows/main_window.py +56 -0
  38. gui/windows/main_window_ui.py +65 -0
  39. rviz_configs/2D-3D.rviz +183 -0
  40. rviz_configs/3D-3D.rviz +184 -0
  41. rviz_configs/default_calib.rviz +167 -0
  42. utils/__init__.py +13 -0
  43. utils/calibration_common.py +23 -0
  44. utils/cli_calibrate.py +53 -0
  45. utils/cli_fleet_server.py +64 -0
  46. utils/data_extractor_common.py +87 -0
  47. utils/gui_helpers.py +25 -0
fleet_server/config.py ADDED
@@ -0,0 +1,91 @@
1
+ """Fleet Server Configuration Management
2
+
3
+ Loads environment variables from .env file and provides defaults.
4
+ """
5
+
6
+ import os
7
+ from pathlib import Path
8
+
9
+ # Try to import dotenv, fallback if not available
10
+ try:
11
+ from dotenv import load_dotenv
12
+ DOTENV_AVAILABLE = True
13
+ except ImportError:
14
+ DOTENV_AVAILABLE = False
15
+
16
+ # Load .env file from fleet_server directory if dotenv is available
17
+ FLEET_SERVER_DIR = Path(__file__).parent.absolute()
18
+ ENV_FILE = FLEET_SERVER_DIR / '.env'
19
+ if DOTENV_AVAILABLE and ENV_FILE.exists():
20
+ load_dotenv(ENV_FILE)
21
+
22
+ class Config:
23
+ """Base configuration"""
24
+ # Server Settings
25
+ FLASK_HOST = os.getenv('FLASK_HOST', '0.0.0.0')
26
+ FLASK_PORT = int(os.getenv('FLASK_PORT', 5000))
27
+ FLASK_ENV = os.getenv('FLASK_ENV', 'development')
28
+ FLASK_DEBUG = os.getenv('FLASK_DEBUG', 'False').lower() == 'true'
29
+
30
+ # Database Path (use absolute path)
31
+ DATABASE_PATH = os.getenv(
32
+ 'DATABASE_PATH',
33
+ str(FLEET_SERVER_DIR / 'fleet.db')
34
+ )
35
+
36
+ # Upload Directory (use absolute path)
37
+ UPLOAD_FOLDER = os.getenv(
38
+ 'UPLOAD_FOLDER',
39
+ str(FLEET_SERVER_DIR / 'uploads')
40
+ )
41
+
42
+ # Logs Directory
43
+ LOGS_FOLDER = str(FLEET_SERVER_DIR / 'logs')
44
+ LOG_FILE = os.getenv(
45
+ 'LOG_FILE',
46
+ str(FLEET_SERVER_DIR / 'logs' / 'fleet_server.log')
47
+ )
48
+ LOG_LEVEL = os.getenv('LOG_LEVEL', 'INFO')
49
+
50
+ # Security Settings
51
+ MAX_UPLOAD_SIZE = int(os.getenv('MAX_UPLOAD_SIZE', 104857600)) # 100MB default
52
+ ALLOWED_EXTENSIONS = set(os.getenv('ALLOWED_EXTENSIONS', 'yaml,yml,pcd,zip').split(','))
53
+
54
+ # API Settings
55
+ API_KEY_ENABLED = os.getenv('API_KEY_ENABLED', 'False').lower() == 'true'
56
+ API_KEY = os.getenv('API_KEY', 'your_secret_key_here')
57
+
58
+ @classmethod
59
+ def ensure_directories(cls):
60
+ """Create required directories if they don't exist"""
61
+ Path(cls.UPLOAD_FOLDER).mkdir(parents=True, exist_ok=True)
62
+ Path(cls.LOGS_FOLDER).mkdir(parents=True, exist_ok=True)
63
+
64
+ # Development Configuration
65
+ class DevelopmentConfig(Config):
66
+ FLASK_ENV = 'development'
67
+ FLASK_DEBUG = True
68
+
69
+ # Production Configuration
70
+ class ProductionConfig(Config):
71
+ FLASK_ENV = 'production'
72
+ FLASK_DEBUG = False
73
+
74
+ # Testing Configuration
75
+ class TestingConfig(Config):
76
+ TESTING = True
77
+ FLASK_DEBUG = True
78
+ DATABASE_PATH = str(FLEET_SERVER_DIR / 'test_fleet.db')
79
+
80
+ # Select configuration based on environment
81
+ config = {
82
+ 'development': DevelopmentConfig,
83
+ 'production': ProductionConfig,
84
+ 'testing': TestingConfig,
85
+ }
86
+
87
+ def get_config(env=None):
88
+ """Get configuration object based on environment"""
89
+ if env is None:
90
+ env = os.getenv('FLASK_ENV', 'development')
91
+ return config.get(env, DevelopmentConfig)
@@ -0,0 +1,57 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>Error - Fleet Server</title>
7
+ <style>
8
+ :root {
9
+ --bg-color: #121212;
10
+ --card-bg: #1e1e1e;
11
+ --text-primary: #e0e0e0;
12
+ --error: #f44336;
13
+ }
14
+ body {
15
+ background-color: var(--bg-color);
16
+ color: var(--text-primary);
17
+ font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
18
+ margin: 0;
19
+ padding: 20px;
20
+ }
21
+ .error-container {
22
+ max-width: 600px;
23
+ margin: 50px auto;
24
+ background-color: var(--card-bg);
25
+ padding: 30px;
26
+ border-radius: 8px;
27
+ border-left: 5px solid var(--error);
28
+ }
29
+ h1 {
30
+ color: var(--error);
31
+ }
32
+ .error-message {
33
+ background-color: #1a1a1a;
34
+ padding: 15px;
35
+ border-radius: 4px;
36
+ margin: 20px 0;
37
+ font-family: monospace;
38
+ white-space: pre-wrap;
39
+ }
40
+ a {
41
+ color: #2196F3;
42
+ text-decoration: none;
43
+ }
44
+ a:hover {
45
+ text-decoration: underline;
46
+ }
47
+ </style>
48
+ </head>
49
+ <body>
50
+ <div class="error-container">
51
+ <h1>⚠️ Error</h1>
52
+ <p>An error occurred while processing your request:</p>
53
+ <div class="error-message">{{ error }}</div>
54
+ <p><a href="/">← Back to Dashboard</a></p>
55
+ </div>
56
+ </body>
57
+ </html>
@@ -0,0 +1,137 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+
4
+ <head>
5
+ <meta charset="UTF-8">
6
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
7
+ <title>Fleet Calibration Manager</title>
8
+ <style>
9
+ :root {
10
+ --bg-color: #121212;
11
+ --card-bg: #1e1e1e;
12
+ --text-primary: #e0e0e0;
13
+ --accent: #2196F3;
14
+ }
15
+
16
+ body {
17
+ background-color: var(--bg-color);
18
+ color: var(--text-primary);
19
+ font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
20
+ margin: 0;
21
+ padding: 20px;
22
+ }
23
+
24
+ h1,
25
+ h2 {
26
+ color: var(--accent);
27
+ }
28
+
29
+ .grid {
30
+ display: grid;
31
+ grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
32
+ gap: 20px;
33
+ margin-bottom: 40px;
34
+ }
35
+
36
+ .card {
37
+ background-color: var(--card-bg);
38
+ padding: 20px;
39
+ border-radius: 8px;
40
+ box-shadow: 0 4px 6px rgba(0, 0, 0, 0.3);
41
+ transition: transform 0.2s;
42
+ }
43
+
44
+ .card:hover {
45
+ transform: translateY(-5px);
46
+ }
47
+
48
+ .status {
49
+ display: inline-block;
50
+ padding: 4px 8px;
51
+ border-radius: 4px;
52
+ font-size: 0.8em;
53
+ background: #4CAF50;
54
+ color: white;
55
+ }
56
+
57
+ table {
58
+ width: 100%;
59
+ border-collapse: collapse;
60
+ background: var(--card-bg);
61
+ border-radius: 8px;
62
+ overflow: hidden;
63
+ }
64
+
65
+ th,
66
+ td {
67
+ padding: 12px;
68
+ text-align: left;
69
+ border-bottom: 1px solid #333;
70
+ }
71
+
72
+ th {
73
+ background-color: #333;
74
+ }
75
+
76
+ .btn {
77
+ text-decoration: none;
78
+ padding: 5px 10px;
79
+ border-radius: 4px;
80
+ margin-right: 5px;
81
+ font-size: 0.9em;
82
+ }
83
+
84
+ .view {
85
+ background-color: #2196F3;
86
+ color: white;
87
+ }
88
+
89
+ .down {
90
+ background-color: #555;
91
+ color: white;
92
+ }
93
+ </style>
94
+ </head>
95
+
96
+ <body>
97
+ <h1>🚀 Fleet Calibration Status</h1>
98
+
99
+ <h2>Active Robots</h2>
100
+ <div class="grid">
101
+ {% for robot in robots %}
102
+ <div class="card">
103
+ <h3>{{ robot['name'] }}</h3>
104
+ <p>Model: {{ robot['model'] }}</p>
105
+ <p>Last Calib: {{ robot['last_calib_date'] | format_timestamp }}</p>
106
+ <span class="status">Active</span>
107
+ </div>
108
+ {% endfor %}
109
+ </div>
110
+
111
+ <h2>Recent Calibrations</h2>
112
+ <table>
113
+ <thead>
114
+ <tr>
115
+ <th>Time</th>
116
+ <th>Robot ID</th>
117
+ <th>Score (RMSE)</th>
118
+ <th>Actions</th>
119
+ </tr>
120
+ </thead>
121
+ <tbody>
122
+ {% for cal in recent %}
123
+ <tr>
124
+ <td>{{ cal['timestamp'] | format_timestamp }}</td>
125
+ <td>{{ cal['robot_id'] }}</td>
126
+ <td>{{ cal['score'] }} m</td>
127
+ <td>
128
+ <a href="/view/{{ cal['id'] }}" class="btn view">👁️ View 3D</a>
129
+ <a href="/files/{{ cal['artifacts_path'] | basename }}" class="btn down">⬇️ DL</a>
130
+ </td>
131
+ </tr>
132
+ {% endfor %}
133
+ </tbody>
134
+ </table>
135
+ </body>
136
+
137
+ </html>