lookout-config 1.2.2__tar.gz → 1.3.1__tar.gz

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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: lookout_config
3
- Version: 1.2.2
3
+ Version: 1.3.1
4
4
  Summary: A library for reading / writing Lookout config files
5
5
  Home-page: https://github.com/Greenroom-Robotics/lookout
6
6
  Author: Greenroom Robotics
@@ -19,7 +19,7 @@ Requires-Dist: setuptools
19
19
  Requires-Dist: dacite
20
20
  Requires-Dist: PyYAML
21
21
  Requires-Dist: dc-schema
22
- Requires-Dist: greenstream-config==2.13.3
22
+ Requires-Dist: greenstream-config==3.5.3
23
23
  Requires-Dist: gr-urchin
24
24
 
25
25
  # Lookout Config
@@ -0,0 +1,43 @@
1
+ # IMPORTANT
2
+ # After changing this file, run `python3 -m lookout_config.generate_schemas`
3
+ # To re-generate the json schemas
4
+ import yaml
5
+ import os
6
+ from typing import Any
7
+ from pathlib import Path
8
+
9
+ from lookout_config.types import LookoutConfig
10
+
11
+
12
+ LOOKOUT_CONFIG_FILE_NAME = "lookout.yml"
13
+ LOOKOUT_SCHEMA_URL = "https://greenroom-robotics.github.io/lookout/schemas/lookout.schema.json"
14
+
15
+
16
+ def find_config() -> Path:
17
+ """Returns the path to the .config/greenroom directory"""
18
+ return Path.home().joinpath(".config/greenroom")
19
+
20
+
21
+ def get_path():
22
+ return find_config() / LOOKOUT_CONFIG_FILE_NAME
23
+
24
+
25
+ def parse(config: dict[str, Any]) -> LookoutConfig:
26
+ return LookoutConfig(**config)
27
+
28
+
29
+ def read() -> LookoutConfig:
30
+ path = get_path()
31
+ with open(path) as stream:
32
+ return parse(yaml.safe_load(stream))
33
+
34
+
35
+ def write(config: LookoutConfig):
36
+ path = get_path()
37
+ # Make the parent dir if it doesn't exist
38
+ os.makedirs(path.parent, exist_ok=True)
39
+ with open(path, "w") as stream:
40
+ print(f"Writing: {path}")
41
+ headers = f"# yaml-language-server: $schema={LOOKOUT_SCHEMA_URL}"
42
+ data = "\n".join([headers, yaml.dump(config.model_dump(mode="json"))])
43
+ stream.write(data)
@@ -1,7 +1,6 @@
1
1
  import os
2
2
  from pathlib import Path
3
3
  import json
4
- from dc_schema import get_schema
5
4
  from lookout_config import LookoutConfig
6
5
 
7
6
 
@@ -9,7 +8,8 @@ def generate_schemas():
9
8
  """Generates the schemas for the config files"""
10
9
  SCHEMAS_PATH = Path(os.path.dirname(__file__)) / "schemas"
11
10
  with open(SCHEMAS_PATH / "lookout.schema.json", "w") as f:
12
- json.dump(get_schema(LookoutConfig), f, indent=2)
11
+ main_model_schema = LookoutConfig.model_json_schema()
12
+ json.dump(main_model_schema, f, indent=2)
13
13
 
14
14
 
15
15
  if __name__ == "__main__":
@@ -18,8 +18,9 @@ def generate_urdf(
18
18
 
19
19
  # generate links and joints for all vessel cameras
20
20
  camera_links, camera_joints = get_cameras_urdf(
21
- cameras, config.camera_overrides if config.camera_overrides else [None], add_optical_frame
21
+ cameras, [None], add_optical_frame, namespace=config.namespace_vessel
22
22
  )
23
+ namespace_prefix = f"{config.namespace_vessel}_" if config.namespace_vessel != "" else ""
23
24
 
24
25
  urdf = URDF(
25
26
  name="origins",
@@ -28,10 +29,15 @@ def generate_urdf(
28
29
  Material(name="blue", color=[0, 0, 1, 1]),
29
30
  ],
30
31
  links=[
31
- Link(name="ins_link", inertial=None, visuals=None, collisions=None),
32
- Link(name="waterline_link", inertial=None, visuals=None, collisions=None),
32
+ Link(name=f"{namespace_prefix}ins_link", inertial=None, visuals=None, collisions=None),
33
33
  Link(
34
- name="base_link",
34
+ name=f"{namespace_prefix}waterline_link",
35
+ inertial=None,
36
+ visuals=None,
37
+ collisions=None,
38
+ ),
39
+ Link(
40
+ name=f"{namespace_prefix}base_link",
35
41
  inertial=None,
36
42
  visuals=[
37
43
  Visual(
@@ -49,9 +55,9 @@ def generate_urdf(
49
55
  ],
50
56
  joints=[
51
57
  Joint(
52
- name="base_to_ins",
53
- parent="base_link",
54
- child="ins_link",
58
+ name=f"{namespace_prefix}base_to_ins",
59
+ parent=f"{namespace_prefix}base_link",
60
+ child=f"{namespace_prefix}ins_link",
55
61
  joint_type="fixed",
56
62
  origin=xyz_rpy_to_matrix(
57
63
  [
@@ -65,9 +71,9 @@ def generate_urdf(
65
71
  ),
66
72
  ),
67
73
  Joint(
68
- name="base_to_waterline",
69
- parent="base_link",
70
- child="waterline_link",
74
+ name=f"{namespace_prefix}base_to_{namespace_prefix}waterline",
75
+ parent=f"{namespace_prefix}base_link",
76
+ child=f"{namespace_prefix}waterline_link",
71
77
  joint_type="fixed",
72
78
  origin=xyz_rpy_to_matrix([0, 0, -waterline, 0, 0, 0]),
73
79
  ),
@@ -0,0 +1,581 @@
1
+ {
2
+ "$defs": {
3
+ "CameraExtended": {
4
+ "properties": {
5
+ "name": {
6
+ "title": "Name",
7
+ "type": "string"
8
+ },
9
+ "order": {
10
+ "title": "Order",
11
+ "type": "integer"
12
+ },
13
+ "elements": {
14
+ "items": {
15
+ "type": "string"
16
+ },
17
+ "title": "Elements",
18
+ "type": "array"
19
+ },
20
+ "pixel_width": {
21
+ "title": "Pixel Width",
22
+ "type": "integer"
23
+ },
24
+ "pixel_height": {
25
+ "title": "Pixel Height",
26
+ "type": "integer"
27
+ },
28
+ "camera_frame_topic": {
29
+ "anyOf": [
30
+ {
31
+ "type": "string"
32
+ },
33
+ {
34
+ "type": "null"
35
+ }
36
+ ],
37
+ "title": "Camera Frame Topic"
38
+ },
39
+ "camera_info_topic": {
40
+ "anyOf": [
41
+ {
42
+ "type": "string"
43
+ },
44
+ {
45
+ "type": "null"
46
+ }
47
+ ],
48
+ "title": "Camera Info Topic"
49
+ },
50
+ "k_intrinsic": {
51
+ "anyOf": [
52
+ {
53
+ "items": {
54
+ "type": "number"
55
+ },
56
+ "type": "array"
57
+ },
58
+ {
59
+ "type": "null"
60
+ }
61
+ ],
62
+ "title": "K Intrinsic"
63
+ },
64
+ "distortion_parameters": {
65
+ "anyOf": [
66
+ {
67
+ "items": {
68
+ "type": "number"
69
+ },
70
+ "type": "array"
71
+ },
72
+ {
73
+ "type": "null"
74
+ }
75
+ ],
76
+ "title": "Distortion Parameters"
77
+ },
78
+ "distortion_model": {
79
+ "default": "plumb_bob",
80
+ "title": "Distortion Model",
81
+ "type": "string"
82
+ },
83
+ "publish_camera_info": {
84
+ "default": true,
85
+ "title": "Publish Camera Info",
86
+ "type": "boolean"
87
+ },
88
+ "distortion_kmat_alpha": {
89
+ "default": 0.5,
90
+ "title": "Distortion Kmat Alpha",
91
+ "type": "number"
92
+ },
93
+ "offsets": {
94
+ "anyOf": [
95
+ {
96
+ "$ref": "#/$defs/Offsets"
97
+ },
98
+ {
99
+ "type": "null"
100
+ }
101
+ ],
102
+ "default": null
103
+ },
104
+ "type": {
105
+ "default": "color",
106
+ "title": "Type",
107
+ "type": "string"
108
+ },
109
+ "ros_throttle_time": {
110
+ "default": 1e-07,
111
+ "title": "Ros Throttle Time",
112
+ "type": "number"
113
+ },
114
+ "undistort_image": {
115
+ "default": false,
116
+ "title": "Undistort Image",
117
+ "type": "boolean"
118
+ },
119
+ "ptz": {
120
+ "anyOf": [
121
+ {
122
+ "$ref": "#/$defs/PTZOnvif"
123
+ },
124
+ {
125
+ "type": "null"
126
+ }
127
+ ],
128
+ "default": null
129
+ },
130
+ "ignore_regions": {
131
+ "items": {
132
+ "$ref": "#/$defs/Polygon"
133
+ },
134
+ "title": "Ignore Regions",
135
+ "type": "array"
136
+ }
137
+ },
138
+ "required": [
139
+ "name",
140
+ "order",
141
+ "elements",
142
+ "pixel_width",
143
+ "pixel_height",
144
+ "camera_frame_topic",
145
+ "camera_info_topic"
146
+ ],
147
+ "title": "CameraExtended",
148
+ "type": "object"
149
+ },
150
+ "GeolocationMode": {
151
+ "enum": [
152
+ "none",
153
+ "relative_bearing",
154
+ "absolute_bearing",
155
+ "range_bearing"
156
+ ],
157
+ "title": "GeolocationMode",
158
+ "type": "string"
159
+ },
160
+ "LogLevel": {
161
+ "enum": [
162
+ "info",
163
+ "debug"
164
+ ],
165
+ "title": "LogLevel",
166
+ "type": "string"
167
+ },
168
+ "Mode": {
169
+ "enum": [
170
+ "simulator",
171
+ "hardware",
172
+ "stubs",
173
+ "rosbag"
174
+ ],
175
+ "title": "Mode",
176
+ "type": "string"
177
+ },
178
+ "Network": {
179
+ "enum": [
180
+ "shared",
181
+ "host"
182
+ ],
183
+ "title": "Network",
184
+ "type": "string"
185
+ },
186
+ "Offsets": {
187
+ "properties": {
188
+ "roll": {
189
+ "anyOf": [
190
+ {
191
+ "type": "number"
192
+ },
193
+ {
194
+ "type": "null"
195
+ }
196
+ ],
197
+ "default": null,
198
+ "title": "Roll"
199
+ },
200
+ "pitch": {
201
+ "anyOf": [
202
+ {
203
+ "type": "number"
204
+ },
205
+ {
206
+ "type": "null"
207
+ }
208
+ ],
209
+ "default": null,
210
+ "title": "Pitch"
211
+ },
212
+ "yaw": {
213
+ "anyOf": [
214
+ {
215
+ "type": "number"
216
+ },
217
+ {
218
+ "type": "null"
219
+ }
220
+ ],
221
+ "default": null,
222
+ "title": "Yaw"
223
+ },
224
+ "forward": {
225
+ "anyOf": [
226
+ {
227
+ "type": "number"
228
+ },
229
+ {
230
+ "type": "null"
231
+ }
232
+ ],
233
+ "default": null,
234
+ "title": "Forward"
235
+ },
236
+ "left": {
237
+ "anyOf": [
238
+ {
239
+ "type": "number"
240
+ },
241
+ {
242
+ "type": "null"
243
+ }
244
+ ],
245
+ "default": null,
246
+ "title": "Left"
247
+ },
248
+ "up": {
249
+ "anyOf": [
250
+ {
251
+ "type": "number"
252
+ },
253
+ {
254
+ "type": "null"
255
+ }
256
+ ],
257
+ "default": null,
258
+ "title": "Up"
259
+ }
260
+ },
261
+ "title": "Offsets",
262
+ "type": "object"
263
+ },
264
+ "PTZComponent": {
265
+ "properties": {
266
+ "move_type": {
267
+ "enum": [
268
+ "pan",
269
+ "tilt",
270
+ "zoom"
271
+ ],
272
+ "title": "Move Type",
273
+ "type": "string"
274
+ },
275
+ "home": {
276
+ "title": "Home",
277
+ "type": "number"
278
+ },
279
+ "joint_offsets": {
280
+ "anyOf": [
281
+ {
282
+ "$ref": "#/$defs/Offsets"
283
+ },
284
+ {
285
+ "type": "null"
286
+ }
287
+ ],
288
+ "default": null
289
+ },
290
+ "joint_limits": {
291
+ "anyOf": [
292
+ {
293
+ "$ref": "#/$defs/PTZLimits"
294
+ },
295
+ {
296
+ "type": "null"
297
+ }
298
+ ],
299
+ "default": null
300
+ },
301
+ "joystick_axis_index": {
302
+ "anyOf": [
303
+ {
304
+ "type": "integer"
305
+ },
306
+ {
307
+ "type": "null"
308
+ }
309
+ ],
310
+ "default": null,
311
+ "title": "Joystick Axis Index"
312
+ },
313
+ "reverse_joystick_input": {
314
+ "default": false,
315
+ "title": "Reverse Joystick Input",
316
+ "type": "boolean"
317
+ }
318
+ },
319
+ "required": [
320
+ "move_type",
321
+ "home"
322
+ ],
323
+ "title": "PTZComponent",
324
+ "type": "object"
325
+ },
326
+ "PTZControlSettings": {
327
+ "properties": {
328
+ "absolute_move_tolerance": {
329
+ "anyOf": [
330
+ {
331
+ "type": "number"
332
+ },
333
+ {
334
+ "type": "null"
335
+ }
336
+ ],
337
+ "default": 0.0175,
338
+ "title": "Absolute Move Tolerance"
339
+ },
340
+ "query_timeout": {
341
+ "anyOf": [
342
+ {
343
+ "type": "integer"
344
+ },
345
+ {
346
+ "type": "null"
347
+ }
348
+ ],
349
+ "default": 2,
350
+ "title": "Query Timeout"
351
+ },
352
+ "check_camera_rate": {
353
+ "anyOf": [
354
+ {
355
+ "type": "number"
356
+ },
357
+ {
358
+ "type": "null"
359
+ }
360
+ ],
361
+ "default": 1.0,
362
+ "title": "Check Camera Rate"
363
+ },
364
+ "publish_rate": {
365
+ "anyOf": [
366
+ {
367
+ "type": "number"
368
+ },
369
+ {
370
+ "type": "null"
371
+ }
372
+ ],
373
+ "default": 10.0,
374
+ "title": "Publish Rate"
375
+ },
376
+ "wsdl_dir": {
377
+ "anyOf": [
378
+ {
379
+ "type": "string"
380
+ },
381
+ {
382
+ "type": "null"
383
+ }
384
+ ],
385
+ "default": "/home/ros/.local/lib/python3.12/site-packages/wsdl",
386
+ "title": "Wsdl Dir"
387
+ },
388
+ "continuous_state_publishing": {
389
+ "anyOf": [
390
+ {
391
+ "type": "boolean"
392
+ },
393
+ {
394
+ "type": "null"
395
+ }
396
+ ],
397
+ "default": true,
398
+ "title": "Continuous State Publishing"
399
+ },
400
+ "frd_to_flu_transform": {
401
+ "default": true,
402
+ "title": "Frd To Flu Transform",
403
+ "type": "boolean"
404
+ }
405
+ },
406
+ "title": "PTZControlSettings",
407
+ "type": "object"
408
+ },
409
+ "PTZLimits": {
410
+ "properties": {
411
+ "min": {
412
+ "title": "Min",
413
+ "type": "number"
414
+ },
415
+ "max": {
416
+ "title": "Max",
417
+ "type": "number"
418
+ }
419
+ },
420
+ "required": [
421
+ "min",
422
+ "max"
423
+ ],
424
+ "title": "PTZLimits",
425
+ "type": "object"
426
+ },
427
+ "PTZOnvif": {
428
+ "properties": {
429
+ "ip_address": {
430
+ "title": "Ip Address",
431
+ "type": "string"
432
+ },
433
+ "port": {
434
+ "title": "Port",
435
+ "type": "integer"
436
+ },
437
+ "username": {
438
+ "title": "Username",
439
+ "type": "string"
440
+ },
441
+ "password": {
442
+ "title": "Password",
443
+ "type": "string"
444
+ },
445
+ "joystick_topic": {
446
+ "anyOf": [
447
+ {
448
+ "type": "string"
449
+ },
450
+ {
451
+ "type": "null"
452
+ }
453
+ ],
454
+ "title": "Joystick Topic"
455
+ },
456
+ "ptz_components": {
457
+ "items": {
458
+ "$ref": "#/$defs/PTZComponent"
459
+ },
460
+ "title": "Ptz Components",
461
+ "type": "array"
462
+ },
463
+ "settings": {
464
+ "$ref": "#/$defs/PTZControlSettings",
465
+ "default": {
466
+ "absolute_move_tolerance": 0.0175,
467
+ "query_timeout": 2,
468
+ "check_camera_rate": 1.0,
469
+ "publish_rate": 10.0,
470
+ "wsdl_dir": "/home/ros/.local/lib/python3.12/site-packages/wsdl",
471
+ "continuous_state_publishing": true,
472
+ "frd_to_flu_transform": true
473
+ }
474
+ }
475
+ },
476
+ "required": [
477
+ "ip_address",
478
+ "port",
479
+ "username",
480
+ "password",
481
+ "joystick_topic",
482
+ "ptz_components"
483
+ ],
484
+ "title": "PTZOnvif",
485
+ "type": "object"
486
+ },
487
+ "Point": {
488
+ "properties": {
489
+ "x": {
490
+ "title": "X",
491
+ "type": "integer"
492
+ },
493
+ "y": {
494
+ "title": "Y",
495
+ "type": "integer"
496
+ }
497
+ },
498
+ "required": [
499
+ "x",
500
+ "y"
501
+ ],
502
+ "title": "Point",
503
+ "type": "object"
504
+ },
505
+ "Polygon": {
506
+ "properties": {
507
+ "points": {
508
+ "items": {
509
+ "$ref": "#/$defs/Point"
510
+ },
511
+ "title": "Points",
512
+ "type": "array"
513
+ }
514
+ },
515
+ "required": [
516
+ "points"
517
+ ],
518
+ "title": "Polygon",
519
+ "type": "object"
520
+ }
521
+ },
522
+ "properties": {
523
+ "ros_domain_id": {
524
+ "default": 0,
525
+ "title": "Ros Domain Id",
526
+ "type": "integer"
527
+ },
528
+ "static_peers": {
529
+ "items": {
530
+ "type": "string"
531
+ },
532
+ "title": "Static Peers",
533
+ "type": "array"
534
+ },
535
+ "namespace_vessel": {
536
+ "default": "vessel",
537
+ "title": "Namespace Vessel",
538
+ "type": "string"
539
+ },
540
+ "gama_vessel": {
541
+ "default": false,
542
+ "title": "Gama Vessel",
543
+ "type": "boolean"
544
+ },
545
+ "mode": {
546
+ "$ref": "#/$defs/Mode",
547
+ "default": "stubs"
548
+ },
549
+ "log_level": {
550
+ "$ref": "#/$defs/LogLevel",
551
+ "default": "info"
552
+ },
553
+ "cameras": {
554
+ "items": {
555
+ "$ref": "#/$defs/CameraExtended"
556
+ },
557
+ "title": "Cameras",
558
+ "type": "array"
559
+ },
560
+ "network": {
561
+ "$ref": "#/$defs/Network",
562
+ "default": "host"
563
+ },
564
+ "gpu": {
565
+ "default": false,
566
+ "title": "Gpu",
567
+ "type": "boolean"
568
+ },
569
+ "geolocation_mode": {
570
+ "$ref": "#/$defs/GeolocationMode",
571
+ "default": "none"
572
+ },
573
+ "prod": {
574
+ "default": true,
575
+ "title": "Prod",
576
+ "type": "boolean"
577
+ }
578
+ },
579
+ "title": "LookoutConfig",
580
+ "type": "object"
581
+ }
@@ -0,0 +1,99 @@
1
+ # Updates here should also be made to:
2
+ # * lookout_interfaces/msg/Config.msg
3
+ # * lookout_config_manager/mappers.py
4
+
5
+ from enum import Enum
6
+ from pydantic import BaseModel, field_validator, ConfigDict
7
+ from pydantic.fields import Field
8
+
9
+ from greenstream_config.types import Camera
10
+
11
+
12
+ class Mode(str, Enum):
13
+ SIMULATOR = "simulator"
14
+ HARDWARE = "hardware"
15
+ STUBS = "stubs"
16
+ ROSBAG = "rosbag"
17
+
18
+ def __str__(self):
19
+ return self.value
20
+
21
+
22
+ class LogLevel(str, Enum):
23
+ INFO = "info"
24
+ DEBUG = "debug"
25
+
26
+ def __str__(self):
27
+ return self.value
28
+
29
+
30
+ class Network(str, Enum):
31
+ SHARED = "shared"
32
+ HOST = "host"
33
+
34
+ def __str__(self):
35
+ return self.value
36
+
37
+
38
+ class GeolocationMode(str, Enum):
39
+ NONE = "none"
40
+ RELATIVE_BEARING = "relative_bearing"
41
+ ABSOLUTE_BEARING = "absolute_bearing"
42
+ RANGE_BEARING = "range_bearing"
43
+
44
+ def __str__(self):
45
+ return self.value
46
+
47
+
48
+ class Point(BaseModel):
49
+ x: int
50
+ y: int
51
+
52
+ def __eq__(self, other):
53
+ if isinstance(other, Point):
54
+ return self.x == other.x and self.y == other.y
55
+ return False
56
+
57
+
58
+ class Polygon(BaseModel):
59
+ points: list[Point]
60
+
61
+
62
+ class CameraExtended(Camera):
63
+ ignore_regions: list[Polygon] = Field(default_factory=list)
64
+
65
+ @field_validator("ignore_regions")
66
+ def check_polygon(cls, ignore_regions):
67
+ if ignore_regions:
68
+ for polygon in ignore_regions:
69
+ if len(polygon.points) < 4: # 3 points for a triangle, 1 to close the polygon
70
+ raise ValueError("Polygon must have at least 3 sides (4 points)")
71
+ if polygon.points[0] != polygon.points[-1]:
72
+ raise ValueError("Polygon must close. Must have same start and end point")
73
+ return ignore_regions
74
+
75
+
76
+ class LookoutConfig(BaseModel):
77
+ # So enum values are written and read to the yml correctly
78
+ model_config = ConfigDict(
79
+ use_enum_values=False,
80
+ json_encoders={
81
+ Mode: lambda v: v.value,
82
+ LogLevel: lambda v: v.value,
83
+ Network: lambda v: v.value,
84
+ GeolocationMode: lambda v: v.value,
85
+ },
86
+ )
87
+ ros_domain_id: int = 0
88
+ static_peers: list[str] = Field(default_factory=list)
89
+ namespace_vessel: str = "vessel_1"
90
+ gama_vessel: bool = False
91
+ mode: Mode = Mode.HARDWARE
92
+ log_level: LogLevel = LogLevel.INFO
93
+ cameras: list[CameraExtended] = Field(default_factory=list)
94
+ network: Network = Network.HOST
95
+ gpu: bool = True
96
+ geolocation_mode: GeolocationMode = GeolocationMode.NONE
97
+ prod: bool = True
98
+ log_directory: str = "~/greenroom/lookout/logs"
99
+ recording_directory: str = "~/greenroom/lookout/recordings"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: lookout_config
3
- Version: 1.2.2
3
+ Version: 1.3.1
4
4
  Summary: A library for reading / writing Lookout config files
5
5
  Home-page: https://github.com/Greenroom-Robotics/lookout
6
6
  Author: Greenroom Robotics
@@ -19,7 +19,7 @@ Requires-Dist: setuptools
19
19
  Requires-Dist: dacite
20
20
  Requires-Dist: PyYAML
21
21
  Requires-Dist: dc-schema
22
- Requires-Dist: greenstream-config==2.13.3
22
+ Requires-Dist: greenstream-config==3.5.3
23
23
  Requires-Dist: gr-urchin
24
24
 
25
25
  # Lookout Config
@@ -2,9 +2,9 @@ README.md
2
2
  setup.cfg
3
3
  setup.py
4
4
  lookout_config/__init__.py
5
- lookout_config/generate_cameras.py
6
5
  lookout_config/generate_schemas.py
7
6
  lookout_config/generate_urdf.py
7
+ lookout_config/types.py
8
8
  lookout_config.egg-info/PKG-INFO
9
9
  lookout_config.egg-info/SOURCES.txt
10
10
  lookout_config.egg-info/dependency_links.txt
@@ -2,5 +2,5 @@ setuptools
2
2
  dacite
3
3
  PyYAML
4
4
  dc-schema
5
- greenstream-config==2.13.3
5
+ greenstream-config==3.5.3
6
6
  gr-urchin
@@ -1,6 +1,6 @@
1
1
  [metadata]
2
2
  name = lookout_config
3
- version = 1.2.2
3
+ version = 1.3.1
4
4
  url = https://github.com/Greenroom-Robotics/lookout
5
5
  author = Greenroom Robotics
6
6
  author_email = team@greenroomrobotics.com
@@ -26,7 +26,7 @@ install_requires =
26
26
  dacite
27
27
  PyYAML
28
28
  dc-schema
29
- greenstream-config==2.13.3
29
+ greenstream-config==3.5.3
30
30
  gr-urchin
31
31
  zip_safe = true
32
32
 
@@ -1,96 +0,0 @@
1
- # IMPORTANT
2
- # After changing this file, run `python3 -m lookout_config.generate_schemas`
3
- # To re-generate the json schemas
4
- import yaml
5
- import os
6
- from dataclasses import dataclass, field
7
- from enum import Enum
8
- from dacite import from_dict, Config
9
- from typing import Optional, Any, List, Annotated
10
- from dc_schema import SchemaAnnotation
11
- from dataclasses import asdict
12
- from pathlib import Path
13
- from greenstream_config.types import CameraOverride
14
-
15
-
16
- LOOKOUT_CONFIG_FILE_NAME = "lookout.yml"
17
- LOOKOUT_SCHEMA_URL = "https://greenroom-robotics.github.io/lookout/schemas/lookout.schema.json"
18
-
19
-
20
- def join_lines(*lines: str) -> str:
21
- return "\n".join(lines)
22
-
23
-
24
- class Mode(str, Enum):
25
- SIMULATOR = "simulator"
26
- HARDWARE = "hardware"
27
- STUBS = "stubs"
28
- ROSBAG = "rosbag"
29
-
30
-
31
- class LogLevel(str, Enum):
32
- INFO = "info"
33
- DEBUG = "debug"
34
-
35
-
36
- class Network(str, Enum):
37
- SHARED = "shared"
38
- HOST = "host"
39
-
40
-
41
- @dataclass
42
- class LookoutConfig:
43
- ros_domain_id: int = 0
44
- namespace_vessel: str = "vessel"
45
- gama_vessel: bool = False
46
- mode: Mode = Mode.STUBS
47
- log_level: LogLevel = LogLevel.INFO
48
- camera_overrides: Optional[List[Optional[CameraOverride]]] = None
49
- network: Network = Network.HOST
50
- gpu: bool = False
51
-
52
-
53
- def find_config() -> Path:
54
- """Returns the path to the .config/greenroom directory"""
55
- return Path.home().joinpath(".config/greenroom")
56
-
57
-
58
- def dacite_to_dict(obj: Any):
59
- def dict_factory(data: Any):
60
- def convert_value(obj: Any):
61
- if isinstance(obj, Enum):
62
- return obj.value
63
- return obj
64
-
65
- return {k: convert_value(v) for k, v in data}
66
-
67
- return asdict(obj, dict_factory=dict_factory)
68
-
69
-
70
- def get_path():
71
- return find_config() / LOOKOUT_CONFIG_FILE_NAME
72
-
73
-
74
- def parse(config: dict[str, Any]) -> LookoutConfig:
75
- return from_dict(
76
- LookoutConfig,
77
- config,
78
- config=Config(cast=[LogLevel, Mode, Network]),
79
- )
80
-
81
-
82
- def read() -> LookoutConfig:
83
- path = get_path()
84
- with open(path) as stream:
85
- return parse(yaml.safe_load(stream))
86
-
87
-
88
- def write(config: LookoutConfig):
89
- path = get_path()
90
- # Make the parent dir if it doesn't exist
91
- os.makedirs(path.parent, exist_ok=True)
92
- with open(path, "w") as stream:
93
- print(f"Writing: {path}")
94
- headers = f"# yaml-language-server: $schema={LOOKOUT_SCHEMA_URL}"
95
- data = "\n".join([headers, yaml.dump(dacite_to_dict(config))])
96
- stream.write(data)
@@ -1,190 +0,0 @@
1
- from typing import List
2
- from greenstream_config import Camera, Offsets
3
- from lookout_config import Mode
4
- from math import radians
5
-
6
-
7
- def generate_cameras_armidale(mode: Mode, namespace: str):
8
- # !! IMPORTANT !!
9
- # Changes here should probably be made in gama also
10
-
11
- k_intrinsic = [1097.44852, 0.0, 992.544475, 0.0, 1101.33980, 552.247413, 0.0, 0.0, 1.0]
12
- # Distortion parameters are broken in foxglove :(
13
- # distortion_parameters = [
14
- # -0.388772321,
15
- # 0.194568646,
16
- # -0.000662550588,
17
- # 0.000224063281,
18
- # -0.0503775800,
19
- # ]
20
-
21
- cameras: List[Camera] = [
22
- Camera(
23
- name="port",
24
- type="color",
25
- order=0,
26
- elements=[
27
- "rtspsrc location=rtsp://admin:@192.168.2.21:554/live/0/MAIN latency=10",
28
- "rtph264depay",
29
- "h264parse",
30
- "avdec_h264",
31
- "videoconvert",
32
- ],
33
- pixel_height=1080,
34
- pixel_width=1920,
35
- sensor_height_mm=2.21,
36
- sensor_width_mm=3.92,
37
- fov=125.0,
38
- camera_frame_topic="perception/frames/port_color",
39
- camera_info_topic="sensors/cameras/port_color/camera_info",
40
- camera_info_ext_topic="sensors/cameras/port_color/camera_info_ext",
41
- k_intrinsic=k_intrinsic,
42
- # distortion_parameters=distortion_parameters,
43
- offsets=Offsets(
44
- roll=0.0,
45
- pitch=radians(20.0),
46
- yaw=radians(45.0),
47
- forward=2.275,
48
- left=2.850,
49
- up=-0.155,
50
- ),
51
- ),
52
- Camera(
53
- name="bow",
54
- type="color",
55
- order=1,
56
- elements=[
57
- "rtspsrc location=rtsp://admin:@192.168.2.22:554/live/0/MAIN latency=10",
58
- "rtph264depay",
59
- "h264parse",
60
- "avdec_h264",
61
- "videoconvert",
62
- ],
63
- pixel_height=1080,
64
- pixel_width=1920,
65
- sensor_height_mm=2.21,
66
- sensor_width_mm=3.92,
67
- fov=125.0,
68
- camera_frame_topic="perception/frames/bow_color",
69
- camera_info_topic="sensors/cameras/bow_color/camera_info",
70
- camera_info_ext_topic="sensors/cameras/bow_color/camera_info_ext",
71
- k_intrinsic=k_intrinsic,
72
- # distortion_parameters=distortion_parameters,
73
- offsets=Offsets(
74
- roll=radians(2.0),
75
- pitch=radians(5.85),
76
- yaw=0.0,
77
- forward=3.190,
78
- left=0.015,
79
- up=-0.205,
80
- ),
81
- ),
82
- Camera(
83
- name="stbd",
84
- type="color",
85
- order=2,
86
- elements=[
87
- "rtspsrc location=rtsp://admin:@192.168.2.23:554/live/0/MAIN latency=10",
88
- "rtph264depay",
89
- "h264parse",
90
- "avdec_h264",
91
- "videoconvert",
92
- ],
93
- pixel_height=1080,
94
- pixel_width=1920,
95
- sensor_height_mm=2.21,
96
- sensor_width_mm=3.92,
97
- fov=125.0,
98
- camera_frame_topic="perception/frames/stbd_color",
99
- camera_info_topic="sensors/cameras/stbd_color/camera_info",
100
- camera_info_ext_topic="sensors/cameras/stbd_color/camera_info_ext",
101
- k_intrinsic=k_intrinsic,
102
- # distortion_parameters=distortion_parameters,
103
- offsets=Offsets(
104
- roll=0.0,
105
- pitch=radians(20.0),
106
- yaw=radians(-45.0),
107
- forward=2.275,
108
- left=-2.850,
109
- up=-0.155,
110
- ),
111
- ),
112
- Camera(
113
- name="stern_port",
114
- type="color",
115
- order=3,
116
- elements=[
117
- "rtspsrc location=rtsp://admin:@192.168.2.24:554/live/0/MAIN latency=10",
118
- "rtph264depay",
119
- "h264parse",
120
- "avdec_h264",
121
- "videoconvert",
122
- ],
123
- pixel_height=1080,
124
- pixel_width=1920,
125
- sensor_height_mm=2.21,
126
- sensor_width_mm=3.92,
127
- fov=125.0,
128
- camera_frame_topic="perception/frames/stern_port_color",
129
- camera_info_topic="sensors/cameras/stern_port_color/camera_info",
130
- camera_info_ext_topic="sensors/cameras/stern_port_color/camera_info_ext",
131
- k_intrinsic=k_intrinsic,
132
- # distortion_parameters=distortion_parameters,
133
- offsets=Offsets(
134
- roll=0.0,
135
- pitch=radians(20.0),
136
- yaw=radians(135.0),
137
- forward=-4.980,
138
- left=2.850,
139
- up=-0.155,
140
- ),
141
- ),
142
- Camera(
143
- name="stern_stbd",
144
- type="color",
145
- order=4,
146
- elements=[
147
- "rtspsrc location=rtsp://admin:@192.168.2.25:554/live/0/MAIN latency=10",
148
- "rtph264depay",
149
- "h264parse",
150
- "avdec_h264",
151
- "videoconvert",
152
- ],
153
- pixel_height=1080,
154
- pixel_width=1920,
155
- sensor_height_mm=2.21,
156
- sensor_width_mm=3.92,
157
- fov=125.0,
158
- camera_frame_topic="perception/frames/stern_stbd_color",
159
- camera_info_topic="sensors/cameras/stern_stbd_color/camera_info",
160
- camera_info_ext_topic="sensors/cameras/stern_stbd_color/camera_info_ext",
161
- k_intrinsic=k_intrinsic,
162
- # distortion_parameters=distortion_parameters,
163
- offsets=Offsets(
164
- roll=0.0,
165
- pitch=radians(20.0),
166
- yaw=radians(-135.0),
167
- forward=-4.980,
168
- left=-2.850,
169
- up=-0.155,
170
- ),
171
- ),
172
- ]
173
-
174
- if mode == Mode.STUBS:
175
- for camera in cameras:
176
- camera.elements = [
177
- "videotestsrc pattern=ball",
178
- "video/x-raw, format=RGB,width=1920,height=1080",
179
- ]
180
- elif mode == Mode.SIMULATOR or mode == Mode.ROSBAG:
181
- for camera in cameras:
182
- camera.elements = [
183
- f"rosimagesrc ros-topic=sensors/cameras/{camera.name}_{camera.type}/image_raw ros-name='gst_rosimagesrc_{camera.name}_{camera.type}' ros-namespace='{namespace}'"
184
- ]
185
-
186
- return cameras
187
-
188
-
189
- def generate_cameras(mode: Mode, namespace: str):
190
- return generate_cameras_armidale(mode, namespace)
@@ -1,139 +0,0 @@
1
- {
2
- "$schema": "https://json-schema.org/draft/2020-12/schema",
3
- "type": "object",
4
- "title": "LookoutConfig",
5
- "properties": {
6
- "ros_domain_id": {
7
- "type": "integer",
8
- "default": 0
9
- },
10
- "namespace_vessel": {
11
- "type": "string",
12
- "default": "vessel"
13
- },
14
- "gama_vessel": {
15
- "type": "boolean",
16
- "default": false
17
- },
18
- "mode": {
19
- "allOf": [
20
- {
21
- "$ref": "#/$defs/Mode"
22
- }
23
- ],
24
- "default": "stubs"
25
- },
26
- "log_level": {
27
- "allOf": [
28
- {
29
- "$ref": "#/$defs/LogLevel"
30
- }
31
- ],
32
- "default": "info"
33
- },
34
- "greenstream": {
35
- "allOf": [
36
- {
37
- "$ref": "#/$defs/Greenstream"
38
- }
39
- ]
40
- },
41
- "network": {
42
- "allOf": [
43
- {
44
- "$ref": "#/$defs/Network"
45
- }
46
- ],
47
- "default": "host"
48
- }
49
- },
50
- "$defs": {
51
- "Mode": {
52
- "title": "Mode",
53
- "enum": [
54
- "simulator",
55
- "hardware",
56
- "stubs"
57
- ]
58
- },
59
- "LogLevel": {
60
- "title": "LogLevel",
61
- "enum": [
62
- "info",
63
- "debug"
64
- ]
65
- },
66
- "Pipeline": {
67
- "type": "object",
68
- "title": "Pipeline",
69
- "properties": {
70
- "name": {
71
- "type": "string"
72
- },
73
- "order": {
74
- "anyOf": [
75
- {
76
- "type": "integer"
77
- },
78
- {
79
- "type": "null"
80
- }
81
- ]
82
- },
83
- "elements": {
84
- "type": "array",
85
- "items": {
86
- "type": "string"
87
- }
88
- }
89
- },
90
- "required": [
91
- "name",
92
- "order",
93
- "elements"
94
- ]
95
- },
96
- "Greenstream": {
97
- "type": "object",
98
- "title": "Greenstream",
99
- "properties": {
100
- "pipeline_overrides": {
101
- "anyOf": [
102
- {
103
- "type": "array",
104
- "items": {
105
- "anyOf": [
106
- {
107
- "allOf": [
108
- {
109
- "$ref": "#/$defs/Pipeline"
110
- }
111
- ]
112
- },
113
- {
114
- "type": "null"
115
- }
116
- ]
117
- }
118
- },
119
- {
120
- "type": "null"
121
- }
122
- ],
123
- "default": null,
124
- "description": "A list of greenstream pipelines.\nThese will only take affect if the the mode is 'hardware'\n\nSet these to 'null' to ignore the override.",
125
- "examples": [
126
- "- null\n- name: bow\n elements:\n - v4l2src\n - video/x-raw, format=RGB,width=1280,height=720"
127
- ]
128
- }
129
- }
130
- },
131
- "Network": {
132
- "title": "Network",
133
- "enum": [
134
- "shared",
135
- "host"
136
- ]
137
- }
138
- }
139
- }
File without changes
File without changes