standardbots 2.0.0.dev1744991656__tar.gz → 2.0.0.dev1744991699__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.
Potentially problematic release.
This version of standardbots might be problematic. Click here for more details.
- {standardbots-2.0.0.dev1744991656 → standardbots-2.0.0.dev1744991699}/PKG-INFO +1 -1
- {standardbots-2.0.0.dev1744991656 → standardbots-2.0.0.dev1744991699}/README.md +42 -8
- {standardbots-2.0.0.dev1744991656 → standardbots-2.0.0.dev1744991699}/setup.py +1 -1
- {standardbots-2.0.0.dev1744991656 → standardbots-2.0.0.dev1744991699}/standardbots/auto_generated/apis.py +547 -0
- {standardbots-2.0.0.dev1744991656 → standardbots-2.0.0.dev1744991699}/standardbots/auto_generated/models.py +1099 -10
- {standardbots-2.0.0.dev1744991656 → standardbots-2.0.0.dev1744991699}/standardbots.egg-info/PKG-INFO +1 -1
- {standardbots-2.0.0.dev1744991656 → standardbots-2.0.0.dev1744991699}/standardbots.egg-info/SOURCES.txt +1 -0
- {standardbots-2.0.0.dev1744991656 → standardbots-2.0.0.dev1744991699}/tests/fixtures/client_fixt.py +0 -2
- standardbots-2.0.0.dev1744991699/tests/fixtures/robot_fixt.py +31 -0
- {standardbots-2.0.0.dev1744991656 → standardbots-2.0.0.dev1744991699}/tests/fixtures/routines_fixt.py +23 -0
- {standardbots-2.0.0.dev1744991656 → standardbots-2.0.0.dev1744991699}/tests/test_apis.py +131 -46
- {standardbots-2.0.0.dev1744991656 → standardbots-2.0.0.dev1744991699}/setup.cfg +0 -0
- {standardbots-2.0.0.dev1744991656 → standardbots-2.0.0.dev1744991699}/standardbots/__init__.py +0 -0
- {standardbots-2.0.0.dev1744991656 → standardbots-2.0.0.dev1744991699}/standardbots/auto_generated/__init__.py +0 -0
- {standardbots-2.0.0.dev1744991656 → standardbots-2.0.0.dev1744991699}/standardbots.egg-info/dependency_links.txt +0 -0
- {standardbots-2.0.0.dev1744991656 → standardbots-2.0.0.dev1744991699}/standardbots.egg-info/requires.txt +0 -0
- {standardbots-2.0.0.dev1744991656 → standardbots-2.0.0.dev1744991699}/standardbots.egg-info/top_level.txt +0 -0
- {standardbots-2.0.0.dev1744991656 → standardbots-2.0.0.dev1744991699}/tests/fixtures/__init__.py +0 -0
|
@@ -24,6 +24,8 @@ To run a script move into the `sdks/python` folder and run `python playground/fi
|
|
|
24
24
|
|
|
25
25
|
You may now use the `botctl` commands to setup and run tests.
|
|
26
26
|
|
|
27
|
+
Set up the testing environment on the computer where you are running the tests:
|
|
28
|
+
|
|
27
29
|
```bash
|
|
28
30
|
# Setup testing environment
|
|
29
31
|
botctl publicapi test:setup --help
|
|
@@ -32,6 +34,11 @@ botctl publicapi test:setup --help
|
|
|
32
34
|
botctl publicapi test --help
|
|
33
35
|
```
|
|
34
36
|
|
|
37
|
+
Set up the bot environment on the robot:
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
botctl publicapi test:setup-bot
|
|
41
|
+
```
|
|
35
42
|
|
|
36
43
|
## Setup
|
|
37
44
|
|
|
@@ -99,11 +106,8 @@ At start of testing, robot should:
|
|
|
99
106
|
The basic idea here is:
|
|
100
107
|
|
|
101
108
|
- These special tests will not be run by default.
|
|
102
|
-
- You may pass a flag (e.g. `--
|
|
109
|
+
- You may pass a flag (e.g. `--camera-disconnected`) when the bot is in the correct state to run the tests.
|
|
103
110
|
- Markers usage:
|
|
104
|
-
- When `--routine-running` flag is passed:
|
|
105
|
-
1. Tests with the flag are run.
|
|
106
|
-
2. Tests without the flag are not run.
|
|
107
111
|
- When `--gripper=<type>` flag is passed(`type` is value from `GripperKindEnum` enum):
|
|
108
112
|
1. Tests expect that this specific gripper is connected
|
|
109
113
|
2. Tests without the flag are not run.
|
|
@@ -113,12 +117,12 @@ The basic idea here is:
|
|
|
113
117
|
|
|
114
118
|
We use [pytest markers](https://docs.pytest.org/en/7.1.x/example/markers.html) to do this.
|
|
115
119
|
|
|
116
|
-
####
|
|
120
|
+
#### Camera disconnected
|
|
117
121
|
|
|
118
|
-
The
|
|
122
|
+
The wrist camera should be disabled. Then run:
|
|
119
123
|
|
|
120
124
|
```bash
|
|
121
|
-
python3 -m pytest ./tests --cov=standardbots --
|
|
125
|
+
python3 -m pytest ./tests --cov=standardbots --camera-disconnected
|
|
122
126
|
```
|
|
123
127
|
|
|
124
128
|
#### E-stop
|
|
@@ -162,5 +166,35 @@ To test custom sensors:
|
|
|
162
166
|
Then run:
|
|
163
167
|
|
|
164
168
|
```bash
|
|
165
|
-
python3 -m pytest ./tests --cov=standardbots --
|
|
169
|
+
python3 -m pytest ./tests --cov=standardbots --gripper=custom_sensors
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
## Database backups
|
|
173
|
+
|
|
174
|
+
> See command: `botctl publicapi test:setup-bot`.
|
|
175
|
+
|
|
176
|
+
We now have a common robot database state that can be used for testing. While this isn't necessary for use, it does provide a common state for testing.
|
|
177
|
+
|
|
178
|
+
### How to create a new backup
|
|
179
|
+
|
|
180
|
+
In the place where you are running the stack and want to create the backup (e.g. on the control box):
|
|
181
|
+
|
|
182
|
+
```bash
|
|
183
|
+
DB_USER=sb
|
|
184
|
+
DB_NAME=sb
|
|
185
|
+
BACKUP_FILE=$HOME/db-backup-publicapi-test.sql
|
|
186
|
+
|
|
187
|
+
docker exec -it postgres-bot pg_dump -U $DB_USER -d $DB_NAME -F c -f /tmp/backup.sql
|
|
188
|
+
|
|
189
|
+
docker cp postgres-bot:/tmp/backup.sql $BACKUP_FILE
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
If you need to download to the actual development environment:
|
|
193
|
+
|
|
194
|
+
```bash
|
|
195
|
+
CB_FILE=/home/control-box-bot/db-backup-publicapi-test.sql
|
|
196
|
+
VM_FILE=~/sb/golang/apps/botctl/commands/publicapi/db-backup-publicapi-test.sql
|
|
197
|
+
|
|
198
|
+
# Move directly to VM:
|
|
199
|
+
scp cb2047:$CB_FILE $VM_FILE
|
|
166
200
|
```
|
|
@@ -354,6 +354,368 @@ class Default:
|
|
|
354
354
|
if parsed is None and (is_user_error or is_unavailable):
|
|
355
355
|
parsed = models.parse_error_response(json.loads(response.data))
|
|
356
356
|
|
|
357
|
+
return Response(
|
|
358
|
+
parsed,
|
|
359
|
+
response.status,
|
|
360
|
+
response
|
|
361
|
+
)
|
|
362
|
+
except urllib3.exceptions.MaxRetryError:
|
|
363
|
+
return Response(
|
|
364
|
+
models.ErrorResponse(
|
|
365
|
+
error=models.ErrorEnum.InternalServerError,
|
|
366
|
+
message="Connection Refused"
|
|
367
|
+
),
|
|
368
|
+
503,
|
|
369
|
+
None
|
|
370
|
+
)
|
|
371
|
+
class Payload:
|
|
372
|
+
def __init__(self, request_manager: RequestManager):
|
|
373
|
+
self._request_manager = request_manager
|
|
374
|
+
|
|
375
|
+
|
|
376
|
+
def set_payload(
|
|
377
|
+
self,
|
|
378
|
+
body: models.PayloadStateRequest,
|
|
379
|
+
) -> Response[
|
|
380
|
+
None,
|
|
381
|
+
None
|
|
382
|
+
]:
|
|
383
|
+
"""
|
|
384
|
+
Set a value for the mass being carried by the robot's end-effector.
|
|
385
|
+
|
|
386
|
+
"""
|
|
387
|
+
path = "/api/v1/payload"
|
|
388
|
+
try:
|
|
389
|
+
response = self._request_manager.request(
|
|
390
|
+
"POST",
|
|
391
|
+
path,
|
|
392
|
+
headers=self._request_manager.json_headers(),
|
|
393
|
+
body=json.dumps(models.serialize_payload_state_request(body)),
|
|
394
|
+
)
|
|
395
|
+
parsed = None
|
|
396
|
+
|
|
397
|
+
is_user_error = response.status >= 400 and response.status <= 500
|
|
398
|
+
is_unavailable = response.status == 503
|
|
399
|
+
if parsed is None and (is_user_error or is_unavailable):
|
|
400
|
+
parsed = models.parse_error_response(json.loads(response.data))
|
|
401
|
+
|
|
402
|
+
return Response(
|
|
403
|
+
parsed,
|
|
404
|
+
response.status,
|
|
405
|
+
response
|
|
406
|
+
)
|
|
407
|
+
except urllib3.exceptions.MaxRetryError:
|
|
408
|
+
return Response(
|
|
409
|
+
models.ErrorResponse(
|
|
410
|
+
error=models.ErrorEnum.InternalServerError,
|
|
411
|
+
message="Connection Refused"
|
|
412
|
+
),
|
|
413
|
+
503,
|
|
414
|
+
None
|
|
415
|
+
)
|
|
416
|
+
def get_payload(
|
|
417
|
+
self,
|
|
418
|
+
) -> Response[
|
|
419
|
+
Union[
|
|
420
|
+
models.PayloadStateResponse,
|
|
421
|
+
models.ErrorResponse,
|
|
422
|
+
None
|
|
423
|
+
],
|
|
424
|
+
models.PayloadStateResponse
|
|
425
|
+
]:
|
|
426
|
+
"""
|
|
427
|
+
Get the current mass value being carried by the robot's end-effector.
|
|
428
|
+
|
|
429
|
+
"""
|
|
430
|
+
path = "/api/v1/payload"
|
|
431
|
+
try:
|
|
432
|
+
response = self._request_manager.request(
|
|
433
|
+
"GET",
|
|
434
|
+
path,
|
|
435
|
+
headers=self._request_manager.json_headers(),
|
|
436
|
+
)
|
|
437
|
+
parsed = None
|
|
438
|
+
if response.status == 200:
|
|
439
|
+
parsed = models.parse_payload_state_response(json.loads(response.data))
|
|
440
|
+
|
|
441
|
+
is_user_error = response.status >= 400 and response.status <= 500
|
|
442
|
+
is_unavailable = response.status == 503
|
|
443
|
+
if parsed is None and (is_user_error or is_unavailable):
|
|
444
|
+
parsed = models.parse_error_response(json.loads(response.data))
|
|
445
|
+
|
|
446
|
+
return Response(
|
|
447
|
+
parsed,
|
|
448
|
+
response.status,
|
|
449
|
+
response
|
|
450
|
+
)
|
|
451
|
+
except urllib3.exceptions.MaxRetryError:
|
|
452
|
+
return Response(
|
|
453
|
+
models.ErrorResponse(
|
|
454
|
+
error=models.ErrorEnum.InternalServerError,
|
|
455
|
+
message="Connection Refused"
|
|
456
|
+
),
|
|
457
|
+
503,
|
|
458
|
+
None
|
|
459
|
+
)
|
|
460
|
+
class Recorder:
|
|
461
|
+
def __init__(self, request_manager: RequestManager):
|
|
462
|
+
self._request_manager = request_manager
|
|
463
|
+
|
|
464
|
+
|
|
465
|
+
def get_recorder_state(
|
|
466
|
+
self,
|
|
467
|
+
) -> Response[
|
|
468
|
+
Union[
|
|
469
|
+
models.RecorderState,
|
|
470
|
+
models.ErrorResponse,
|
|
471
|
+
None
|
|
472
|
+
],
|
|
473
|
+
models.RecorderState
|
|
474
|
+
]:
|
|
475
|
+
"""
|
|
476
|
+
Get the state of the recorder
|
|
477
|
+
"""
|
|
478
|
+
path = "/api/v1/recorder/state"
|
|
479
|
+
try:
|
|
480
|
+
response = self._request_manager.request(
|
|
481
|
+
"GET",
|
|
482
|
+
path,
|
|
483
|
+
headers=self._request_manager.json_headers(),
|
|
484
|
+
)
|
|
485
|
+
parsed = None
|
|
486
|
+
if response.status == 200:
|
|
487
|
+
parsed = models.parse_recorder_state(json.loads(response.data))
|
|
488
|
+
|
|
489
|
+
is_user_error = response.status >= 400 and response.status <= 500
|
|
490
|
+
is_unavailable = response.status == 503
|
|
491
|
+
if parsed is None and (is_user_error or is_unavailable):
|
|
492
|
+
parsed = models.parse_error_response(json.loads(response.data))
|
|
493
|
+
|
|
494
|
+
return Response(
|
|
495
|
+
parsed,
|
|
496
|
+
response.status,
|
|
497
|
+
response
|
|
498
|
+
)
|
|
499
|
+
except urllib3.exceptions.MaxRetryError:
|
|
500
|
+
return Response(
|
|
501
|
+
models.ErrorResponse(
|
|
502
|
+
error=models.ErrorEnum.InternalServerError,
|
|
503
|
+
message="Connection Refused"
|
|
504
|
+
),
|
|
505
|
+
503,
|
|
506
|
+
None
|
|
507
|
+
)
|
|
508
|
+
def update_recording(
|
|
509
|
+
self,
|
|
510
|
+
body: models.RecorderConfig,
|
|
511
|
+
) -> Response[
|
|
512
|
+
Union[
|
|
513
|
+
models.UpdateRecordingResponse,
|
|
514
|
+
models.ErrorResponse,
|
|
515
|
+
None
|
|
516
|
+
],
|
|
517
|
+
models.UpdateRecordingResponse
|
|
518
|
+
]:
|
|
519
|
+
"""
|
|
520
|
+
Update recording configuration
|
|
521
|
+
"""
|
|
522
|
+
path = "/api/v1/recorder/update"
|
|
523
|
+
try:
|
|
524
|
+
response = self._request_manager.request(
|
|
525
|
+
"POST",
|
|
526
|
+
path,
|
|
527
|
+
headers=self._request_manager.json_headers(),
|
|
528
|
+
body=json.dumps(models.serialize_recorder_config(body)),
|
|
529
|
+
)
|
|
530
|
+
parsed = None
|
|
531
|
+
if response.status == 200:
|
|
532
|
+
parsed = models.parse_update_recording_response(json.loads(response.data))
|
|
533
|
+
|
|
534
|
+
is_user_error = response.status >= 400 and response.status <= 500
|
|
535
|
+
is_unavailable = response.status == 503
|
|
536
|
+
if parsed is None and (is_user_error or is_unavailable):
|
|
537
|
+
parsed = models.parse_error_response(json.loads(response.data))
|
|
538
|
+
|
|
539
|
+
return Response(
|
|
540
|
+
parsed,
|
|
541
|
+
response.status,
|
|
542
|
+
response
|
|
543
|
+
)
|
|
544
|
+
except urllib3.exceptions.MaxRetryError:
|
|
545
|
+
return Response(
|
|
546
|
+
models.ErrorResponse(
|
|
547
|
+
error=models.ErrorEnum.InternalServerError,
|
|
548
|
+
message="Connection Refused"
|
|
549
|
+
),
|
|
550
|
+
503,
|
|
551
|
+
None
|
|
552
|
+
)
|
|
553
|
+
def enable_recorder_bot(
|
|
554
|
+
self,
|
|
555
|
+
body: models.ToggleRecorderBotRequest,
|
|
556
|
+
) -> Response[
|
|
557
|
+
Union[
|
|
558
|
+
models.UpdateRecordingResponse,
|
|
559
|
+
models.ErrorResponse,
|
|
560
|
+
None
|
|
561
|
+
],
|
|
562
|
+
models.UpdateRecordingResponse
|
|
563
|
+
]:
|
|
564
|
+
"""
|
|
565
|
+
Enable or disable a secondary bot
|
|
566
|
+
"""
|
|
567
|
+
path = "/api/v1/recorder/set-bot-enabled"
|
|
568
|
+
try:
|
|
569
|
+
response = self._request_manager.request(
|
|
570
|
+
"POST",
|
|
571
|
+
path,
|
|
572
|
+
headers=self._request_manager.json_headers(),
|
|
573
|
+
body=json.dumps(models.serialize_toggle_recorder_bot_request(body)),
|
|
574
|
+
)
|
|
575
|
+
parsed = None
|
|
576
|
+
if response.status == 200:
|
|
577
|
+
parsed = models.parse_update_recording_response(json.loads(response.data))
|
|
578
|
+
|
|
579
|
+
is_user_error = response.status >= 400 and response.status <= 500
|
|
580
|
+
is_unavailable = response.status == 503
|
|
581
|
+
if parsed is None and (is_user_error or is_unavailable):
|
|
582
|
+
parsed = models.parse_error_response(json.loads(response.data))
|
|
583
|
+
|
|
584
|
+
return Response(
|
|
585
|
+
parsed,
|
|
586
|
+
response.status,
|
|
587
|
+
response
|
|
588
|
+
)
|
|
589
|
+
except urllib3.exceptions.MaxRetryError:
|
|
590
|
+
return Response(
|
|
591
|
+
models.ErrorResponse(
|
|
592
|
+
error=models.ErrorEnum.InternalServerError,
|
|
593
|
+
message="Connection Refused"
|
|
594
|
+
),
|
|
595
|
+
503,
|
|
596
|
+
None
|
|
597
|
+
)
|
|
598
|
+
def start_recording(
|
|
599
|
+
self,
|
|
600
|
+
body: models.StartRecordingRequest,
|
|
601
|
+
) -> Response[
|
|
602
|
+
Union[
|
|
603
|
+
models.StartRecordingResponse,
|
|
604
|
+
models.ErrorResponse,
|
|
605
|
+
None
|
|
606
|
+
],
|
|
607
|
+
models.StartRecordingResponse
|
|
608
|
+
]:
|
|
609
|
+
"""
|
|
610
|
+
Start recording movement and camera data
|
|
611
|
+
"""
|
|
612
|
+
path = "/api/v1/recorder/start"
|
|
613
|
+
try:
|
|
614
|
+
response = self._request_manager.request(
|
|
615
|
+
"POST",
|
|
616
|
+
path,
|
|
617
|
+
headers=self._request_manager.json_headers(),
|
|
618
|
+
body=json.dumps(models.serialize_start_recording_request(body)),
|
|
619
|
+
)
|
|
620
|
+
parsed = None
|
|
621
|
+
if response.status == 200:
|
|
622
|
+
parsed = models.parse_start_recording_response(json.loads(response.data))
|
|
623
|
+
|
|
624
|
+
is_user_error = response.status >= 400 and response.status <= 500
|
|
625
|
+
is_unavailable = response.status == 503
|
|
626
|
+
if parsed is None and (is_user_error or is_unavailable):
|
|
627
|
+
parsed = models.parse_error_response(json.loads(response.data))
|
|
628
|
+
|
|
629
|
+
return Response(
|
|
630
|
+
parsed,
|
|
631
|
+
response.status,
|
|
632
|
+
response
|
|
633
|
+
)
|
|
634
|
+
except urllib3.exceptions.MaxRetryError:
|
|
635
|
+
return Response(
|
|
636
|
+
models.ErrorResponse(
|
|
637
|
+
error=models.ErrorEnum.InternalServerError,
|
|
638
|
+
message="Connection Refused"
|
|
639
|
+
),
|
|
640
|
+
503,
|
|
641
|
+
None
|
|
642
|
+
)
|
|
643
|
+
def stop_recording(
|
|
644
|
+
self,
|
|
645
|
+
body: models.StopRecordingRequest,
|
|
646
|
+
) -> Response[
|
|
647
|
+
Union[
|
|
648
|
+
models.StopRecordingResponse,
|
|
649
|
+
models.ErrorResponse,
|
|
650
|
+
None
|
|
651
|
+
],
|
|
652
|
+
models.StopRecordingResponse
|
|
653
|
+
]:
|
|
654
|
+
"""
|
|
655
|
+
Stop recording movement and camera data
|
|
656
|
+
"""
|
|
657
|
+
path = "/api/v1/recorder/stop"
|
|
658
|
+
try:
|
|
659
|
+
response = self._request_manager.request(
|
|
660
|
+
"POST",
|
|
661
|
+
path,
|
|
662
|
+
headers=self._request_manager.json_headers(),
|
|
663
|
+
body=json.dumps(models.serialize_stop_recording_request(body)),
|
|
664
|
+
)
|
|
665
|
+
parsed = None
|
|
666
|
+
if response.status == 200:
|
|
667
|
+
parsed = models.parse_stop_recording_response(json.loads(response.data))
|
|
668
|
+
|
|
669
|
+
is_user_error = response.status >= 400 and response.status <= 500
|
|
670
|
+
is_unavailable = response.status == 503
|
|
671
|
+
if parsed is None and (is_user_error or is_unavailable):
|
|
672
|
+
parsed = models.parse_error_response(json.loads(response.data))
|
|
673
|
+
|
|
674
|
+
return Response(
|
|
675
|
+
parsed,
|
|
676
|
+
response.status,
|
|
677
|
+
response
|
|
678
|
+
)
|
|
679
|
+
except urllib3.exceptions.MaxRetryError:
|
|
680
|
+
return Response(
|
|
681
|
+
models.ErrorResponse(
|
|
682
|
+
error=models.ErrorEnum.InternalServerError,
|
|
683
|
+
message="Connection Refused"
|
|
684
|
+
),
|
|
685
|
+
503,
|
|
686
|
+
None
|
|
687
|
+
)
|
|
688
|
+
def save_recording(
|
|
689
|
+
self,
|
|
690
|
+
body: models.SaveRecordingRequest,
|
|
691
|
+
) -> Response[
|
|
692
|
+
Union[
|
|
693
|
+
models.SaveRecordingResponse,
|
|
694
|
+
models.ErrorResponse,
|
|
695
|
+
None
|
|
696
|
+
],
|
|
697
|
+
models.SaveRecordingResponse
|
|
698
|
+
]:
|
|
699
|
+
"""
|
|
700
|
+
Save recording to marvin app
|
|
701
|
+
"""
|
|
702
|
+
path = "/api/v1/recorder/save"
|
|
703
|
+
try:
|
|
704
|
+
response = self._request_manager.request(
|
|
705
|
+
"POST",
|
|
706
|
+
path,
|
|
707
|
+
headers=self._request_manager.json_headers(),
|
|
708
|
+
body=json.dumps(models.serialize_save_recording_request(body)),
|
|
709
|
+
)
|
|
710
|
+
parsed = None
|
|
711
|
+
if response.status == 200:
|
|
712
|
+
parsed = models.parse_save_recording_response(json.loads(response.data))
|
|
713
|
+
|
|
714
|
+
is_user_error = response.status >= 400 and response.status <= 500
|
|
715
|
+
is_unavailable = response.status == 503
|
|
716
|
+
if parsed is None and (is_user_error or is_unavailable):
|
|
717
|
+
parsed = models.parse_error_response(json.loads(response.data))
|
|
718
|
+
|
|
357
719
|
return Response(
|
|
358
720
|
parsed,
|
|
359
721
|
response.status,
|
|
@@ -470,18 +832,203 @@ class Default:
|
|
|
470
832
|
503,
|
|
471
833
|
None
|
|
472
834
|
)
|
|
835
|
+
class Teleop:
|
|
836
|
+
def __init__(self, request_manager: RequestManager):
|
|
837
|
+
self._request_manager = request_manager
|
|
838
|
+
|
|
839
|
+
|
|
840
|
+
def get_state(
|
|
841
|
+
self,
|
|
842
|
+
) -> Response[
|
|
843
|
+
Union[
|
|
844
|
+
models.TeleopState,
|
|
845
|
+
models.ErrorResponse,
|
|
846
|
+
None
|
|
847
|
+
],
|
|
848
|
+
models.TeleopState
|
|
849
|
+
]:
|
|
850
|
+
"""
|
|
851
|
+
Get the state of the teleop
|
|
852
|
+
"""
|
|
853
|
+
path = "/api/v1/teleop/state"
|
|
854
|
+
try:
|
|
855
|
+
response = self._request_manager.request(
|
|
856
|
+
"GET",
|
|
857
|
+
path,
|
|
858
|
+
headers=self._request_manager.json_headers(),
|
|
859
|
+
)
|
|
860
|
+
parsed = None
|
|
861
|
+
if response.status == 200:
|
|
862
|
+
parsed = models.parse_teleop_state(json.loads(response.data))
|
|
863
|
+
|
|
864
|
+
is_user_error = response.status >= 400 and response.status <= 500
|
|
865
|
+
is_unavailable = response.status == 503
|
|
866
|
+
if parsed is None and (is_user_error or is_unavailable):
|
|
867
|
+
parsed = models.parse_error_response(json.loads(response.data))
|
|
868
|
+
|
|
869
|
+
return Response(
|
|
870
|
+
parsed,
|
|
871
|
+
response.status,
|
|
872
|
+
response
|
|
873
|
+
)
|
|
874
|
+
except urllib3.exceptions.MaxRetryError:
|
|
875
|
+
return Response(
|
|
876
|
+
models.ErrorResponse(
|
|
877
|
+
error=models.ErrorEnum.InternalServerError,
|
|
878
|
+
message="Connection Refused"
|
|
879
|
+
),
|
|
880
|
+
503,
|
|
881
|
+
None
|
|
882
|
+
)
|
|
883
|
+
def enable_bot(
|
|
884
|
+
self,
|
|
885
|
+
body: models.ToggleTeleopBotRequest,
|
|
886
|
+
) -> Response[
|
|
887
|
+
Union[
|
|
888
|
+
models.TeleopState,
|
|
889
|
+
models.ErrorResponse,
|
|
890
|
+
None
|
|
891
|
+
],
|
|
892
|
+
models.TeleopState
|
|
893
|
+
]:
|
|
894
|
+
"""
|
|
895
|
+
Enable or disable a secondary bot
|
|
896
|
+
"""
|
|
897
|
+
path = "/api/v1/teleop/set-bot-enabled"
|
|
898
|
+
try:
|
|
899
|
+
response = self._request_manager.request(
|
|
900
|
+
"POST",
|
|
901
|
+
path,
|
|
902
|
+
headers=self._request_manager.json_headers(),
|
|
903
|
+
body=json.dumps(models.serialize_toggle_teleop_bot_request(body)),
|
|
904
|
+
)
|
|
905
|
+
parsed = None
|
|
906
|
+
if response.status == 200:
|
|
907
|
+
parsed = models.parse_teleop_state(json.loads(response.data))
|
|
908
|
+
|
|
909
|
+
is_user_error = response.status >= 400 and response.status <= 500
|
|
910
|
+
is_unavailable = response.status == 503
|
|
911
|
+
if parsed is None and (is_user_error or is_unavailable):
|
|
912
|
+
parsed = models.parse_error_response(json.loads(response.data))
|
|
913
|
+
|
|
914
|
+
return Response(
|
|
915
|
+
parsed,
|
|
916
|
+
response.status,
|
|
917
|
+
response
|
|
918
|
+
)
|
|
919
|
+
except urllib3.exceptions.MaxRetryError:
|
|
920
|
+
return Response(
|
|
921
|
+
models.ErrorResponse(
|
|
922
|
+
error=models.ErrorEnum.InternalServerError,
|
|
923
|
+
message="Connection Refused"
|
|
924
|
+
),
|
|
925
|
+
503,
|
|
926
|
+
None
|
|
927
|
+
)
|
|
928
|
+
def start_teleop(
|
|
929
|
+
self,
|
|
930
|
+
) -> Response[
|
|
931
|
+
Union[
|
|
932
|
+
models.StartTeleopResponse,
|
|
933
|
+
models.ErrorResponse,
|
|
934
|
+
None
|
|
935
|
+
],
|
|
936
|
+
models.StartTeleopResponse
|
|
937
|
+
]:
|
|
938
|
+
"""
|
|
939
|
+
Start teleoperation
|
|
940
|
+
"""
|
|
941
|
+
path = "/api/v1/teleop/start"
|
|
942
|
+
try:
|
|
943
|
+
response = self._request_manager.request(
|
|
944
|
+
"POST",
|
|
945
|
+
path,
|
|
946
|
+
headers=self._request_manager.json_headers(),
|
|
947
|
+
)
|
|
948
|
+
parsed = None
|
|
949
|
+
if response.status == 200:
|
|
950
|
+
parsed = models.parse_start_teleop_response(json.loads(response.data))
|
|
951
|
+
|
|
952
|
+
is_user_error = response.status >= 400 and response.status <= 500
|
|
953
|
+
is_unavailable = response.status == 503
|
|
954
|
+
if parsed is None and (is_user_error or is_unavailable):
|
|
955
|
+
parsed = models.parse_error_response(json.loads(response.data))
|
|
956
|
+
|
|
957
|
+
return Response(
|
|
958
|
+
parsed,
|
|
959
|
+
response.status,
|
|
960
|
+
response
|
|
961
|
+
)
|
|
962
|
+
except urllib3.exceptions.MaxRetryError:
|
|
963
|
+
return Response(
|
|
964
|
+
models.ErrorResponse(
|
|
965
|
+
error=models.ErrorEnum.InternalServerError,
|
|
966
|
+
message="Connection Refused"
|
|
967
|
+
),
|
|
968
|
+
503,
|
|
969
|
+
None
|
|
970
|
+
)
|
|
971
|
+
def stop_teleop(
|
|
972
|
+
self,
|
|
973
|
+
) -> Response[
|
|
974
|
+
Union[
|
|
975
|
+
models.StopTeleopResponse,
|
|
976
|
+
models.ErrorResponse,
|
|
977
|
+
None
|
|
978
|
+
],
|
|
979
|
+
models.StopTeleopResponse
|
|
980
|
+
]:
|
|
981
|
+
"""
|
|
982
|
+
Stop recording movement and camera data
|
|
983
|
+
"""
|
|
984
|
+
path = "/api/v1/teleop/stop"
|
|
985
|
+
try:
|
|
986
|
+
response = self._request_manager.request(
|
|
987
|
+
"POST",
|
|
988
|
+
path,
|
|
989
|
+
headers=self._request_manager.json_headers(),
|
|
990
|
+
)
|
|
991
|
+
parsed = None
|
|
992
|
+
if response.status == 200:
|
|
993
|
+
parsed = models.parse_stop_teleop_response(json.loads(response.data))
|
|
994
|
+
|
|
995
|
+
is_user_error = response.status >= 400 and response.status <= 500
|
|
996
|
+
is_unavailable = response.status == 503
|
|
997
|
+
if parsed is None and (is_user_error or is_unavailable):
|
|
998
|
+
parsed = models.parse_error_response(json.loads(response.data))
|
|
999
|
+
|
|
1000
|
+
return Response(
|
|
1001
|
+
parsed,
|
|
1002
|
+
response.status,
|
|
1003
|
+
response
|
|
1004
|
+
)
|
|
1005
|
+
except urllib3.exceptions.MaxRetryError:
|
|
1006
|
+
return Response(
|
|
1007
|
+
models.ErrorResponse(
|
|
1008
|
+
error=models.ErrorEnum.InternalServerError,
|
|
1009
|
+
message="Connection Refused"
|
|
1010
|
+
),
|
|
1011
|
+
503,
|
|
1012
|
+
None
|
|
1013
|
+
)
|
|
473
1014
|
|
|
474
1015
|
calibration: Calibration
|
|
475
1016
|
equipment: Equipment
|
|
1017
|
+
payload: Payload
|
|
1018
|
+
recorder: Recorder
|
|
476
1019
|
sensors: Sensors
|
|
477
1020
|
space: Space
|
|
1021
|
+
teleop: Teleop
|
|
478
1022
|
|
|
479
1023
|
def __init__(self, request_manager: RequestManager):
|
|
480
1024
|
self._request_manager = request_manager
|
|
481
1025
|
self.calibration = Default.Calibration(request_manager)
|
|
482
1026
|
self.equipment = Default.Equipment(request_manager)
|
|
1027
|
+
self.payload = Default.Payload(request_manager)
|
|
1028
|
+
self.recorder = Default.Recorder(request_manager)
|
|
483
1029
|
self.sensors = Default.Sensors(request_manager)
|
|
484
1030
|
self.space = Default.Space(request_manager)
|
|
1031
|
+
self.teleop = Default.Teleop(request_manager)
|
|
485
1032
|
|
|
486
1033
|
class Movement:
|
|
487
1034
|
_request_manager: RequestManager
|