bluer-ugv 7.165.1__py3-none-any.whl → 7.196.1__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 (28) hide show
  1. bluer_ugv/.abcli/swallow/env/set.sh +2 -0
  2. bluer_ugv/.abcli/swallow/keyboard/test.sh +9 -0
  3. bluer_ugv/.abcli/swallow/keyboard.sh +17 -0
  4. bluer_ugv/.abcli/tests/help.sh +5 -1
  5. bluer_ugv/README/swallow/digital/design/__init__.py +7 -1
  6. bluer_ugv/__init__.py +1 -1
  7. bluer_ugv/config.env +1 -0
  8. bluer_ugv/env.py +5 -0
  9. bluer_ugv/help/swallow/__init__.py +2 -0
  10. bluer_ugv/help/swallow/env.py +2 -1
  11. bluer_ugv/help/swallow/keyboard.py +33 -0
  12. bluer_ugv/swallow/session/classical/camera/generic.py +1 -1
  13. bluer_ugv/swallow/session/classical/camera/navigation.py +1 -1
  14. bluer_ugv/swallow/session/classical/camera/tracking.py +1 -1
  15. bluer_ugv/swallow/session/classical/camera/yolo.py +12 -6
  16. bluer_ugv/swallow/session/classical/keyboard/__init__.py +0 -0
  17. bluer_ugv/swallow/session/classical/keyboard/__main__.py +31 -0
  18. bluer_ugv/swallow/session/classical/{keyboard.py → keyboard/classes.py} +25 -40
  19. bluer_ugv/swallow/session/classical/keyboard/keys.py +81 -0
  20. bluer_ugv/swallow/session/classical/keyboard/testing.py +22 -0
  21. bluer_ugv/swallow/session/classical/session.py +1 -1
  22. bluer_ugv/swallow/session/classical/setpoint/classes.py +47 -2
  23. bluer_ugv/swallow/session/classical/ultrasonic_sensor/classes.py +1 -1
  24. {bluer_ugv-7.165.1.dist-info → bluer_ugv-7.196.1.dist-info}/METADATA +2 -2
  25. {bluer_ugv-7.165.1.dist-info → bluer_ugv-7.196.1.dist-info}/RECORD +28 -21
  26. {bluer_ugv-7.165.1.dist-info → bluer_ugv-7.196.1.dist-info}/WHEEL +0 -0
  27. {bluer_ugv-7.165.1.dist-info → bluer_ugv-7.196.1.dist-info}/licenses/LICENSE +0 -0
  28. {bluer_ugv-7.165.1.dist-info → bluer_ugv-7.196.1.dist-info}/top_level.txt +0 -0
@@ -5,6 +5,8 @@ function bluer_ugv_swallow_env_set() {
5
5
 
6
6
  if [[ "$var_name" == "steering" ]]; then
7
7
  var_name=BLUER_SBC_SWALLOW_HAS_STEERING
8
+ elif [[ "$var_name" == "full_keyboard" ]]; then
9
+ var_name=BLUER_SBC_SWALLOW_HAS_FULL_KEYBOARD
8
10
  else
9
11
  bluer_ai_log_error "$var_name: var not found."
10
12
  return 1
@@ -0,0 +1,9 @@
1
+ #! /usr/bin/env bash
2
+
3
+ function bluer_ugv_swallow_keyboard_test() {
4
+ bluer_ai_eval ,$1 \
5
+ sudo -E $(which python3) \
6
+ -m bluer_ugv.swallow.session.classical.keyboard \
7
+ test \
8
+ "${@:2}"
9
+ }
@@ -0,0 +1,17 @@
1
+ #! /usr/bin/env bash
2
+
3
+ function bluer_ugv_swallow_keyboard() {
4
+ local task=$1
5
+
6
+ local function_name=bluer_ugv_swallow_keyboard_$task
7
+ if [[ $(type -t $function_name) == "function" ]]; then
8
+ $function_name "${@:2}"
9
+ return
10
+ fi
11
+
12
+ sudo -E $(which python3) \
13
+ -m bluer_ugv.swallow.session.classical.keyboard \
14
+ "$@"
15
+ }
16
+
17
+ bluer_ai_source_caller_suffix_path /keyboard
@@ -13,12 +13,16 @@ function test_bluer_ugv_help() {
13
13
  "@swallow dataset list" \
14
14
  "@swallow dataset upload" \
15
15
  \
16
+ "@swallow debug" \
17
+ \
16
18
  "@swallow env" \
17
19
  "@swallow env cp" \
18
20
  "@swallow env list" \
19
21
  "@swallow env set" \
20
22
  \
21
- "@swallow debug" \
23
+ "@swallow keyboard" \
24
+ "@swallow keyboard test" \
25
+ \
22
26
  "@swallow select_target" \
23
27
  \
24
28
  "@swallow ultrasonic" \
@@ -8,6 +8,7 @@ from bluer_ugv.README.swallow.consts import (
8
8
  )
9
9
  from bluer_ugv.designs.swallow.parts import dict_of_parts
10
10
  from bluer_ugv.README.swallow.digital.design import mechanical, ultrasonic_sensor
11
+ from bluer_ugv.swallow.session.classical.keyboard.keys import ControlKeys
11
12
 
12
13
 
13
14
  docs = (
@@ -20,11 +21,16 @@ docs = (
20
21
  },
21
22
  {
22
23
  "path": "../docs/swallow/digital/design/operation.md",
24
+ "cols": 2,
23
25
  "items": ImageItems(
24
26
  {
25
- f"{swallow_assets2}/20251005_113232.jpg": "",
27
+ f"{swallow_assets2}/20251019_121811.jpg": "",
28
+ f"{swallow_assets2}/20251019_121842.jpg": "",
26
29
  }
27
30
  ),
31
+ "macros": {
32
+ "keys:::": ControlKeys.as_table(),
33
+ },
28
34
  },
29
35
  {
30
36
  "path": "../docs/swallow/digital/design/parts.md",
bluer_ugv/__init__.py CHANGED
@@ -4,7 +4,7 @@ ICON = "🐬"
4
4
 
5
5
  DESCRIPTION = f"{ICON} AI x UGV."
6
6
 
7
- VERSION = "7.165.1"
7
+ VERSION = "7.196.1"
8
8
 
9
9
  REPO_NAME = "bluer-ugv"
10
10
 
bluer_ugv/config.env CHANGED
@@ -4,6 +4,7 @@ BLUER_UGV_CAMERA_TRAINING_PERIOD=3.0
4
4
  BLUER_UGV_CAMERA_ACTION_PERIOD=0.5
5
5
 
6
6
  BLUER_UGV_SWALLOW_STEERING_SETPOINT=50
7
+ BLUER_UGV_SWALLOW_STEERING_YOLO_EXPIRY=0.1
7
8
 
8
9
  BLUER_UGV_MOUSEPAD_ENABLED=0
9
10
 
bluer_ugv/env.py CHANGED
@@ -23,6 +23,11 @@ BLUER_UGV_SWALLOW_STEERING_SETPOINT = get_env(
23
23
  50,
24
24
  )
25
25
 
26
+ BLUER_UGV_SWALLOW_STEERING_YOLO_EXPIRY = get_env(
27
+ "BLUER_UGV_SWALLOW_STEERING_YOLO_EXPIRY",
28
+ 0.1,
29
+ )
30
+
26
31
  BLUER_UGV_MOUSEPAD_ENABLED = get_env(
27
32
  "BLUER_UGV_MOUSEPAD_ENABLED",
28
33
  0,
@@ -1,6 +1,7 @@
1
1
  from bluer_ugv.help.swallow.dataset import help_functions as help_dataset
2
2
  from bluer_ugv.help.swallow.debug import help_debug
3
3
  from bluer_ugv.help.swallow.env import help_functions as help_env
4
+ from bluer_ugv.help.swallow.keyboard import help_functions as help_keyboard
4
5
  from bluer_ugv.help.swallow.select_target import help_select_target
5
6
  from bluer_ugv.help.swallow.ultrasonic_sensor import (
6
7
  help_functions as help_ultrasonic_sensor,
@@ -10,6 +11,7 @@ help_functions = {
10
11
  "dataset": help_dataset,
11
12
  "debug": help_debug,
12
13
  "env": help_env,
14
+ "keyboard": help_keyboard,
13
15
  "select_target": help_select_target,
14
16
  "ultrasonic": help_ultrasonic_sensor,
15
17
  }
@@ -43,11 +43,12 @@ def help_set(
43
43
  "@swallow",
44
44
  "env",
45
45
  "set",
46
- "steering",
46
+ "full_keyboard | steering",
47
47
  "0 | 1",
48
48
  ],
49
49
  "set env.",
50
50
  {
51
+ "full_keyboard: BLUER_SBC_SWALLOW_HAS_FULL_KEYBOARD": "",
51
52
  "steering: BLUER_SBC_SWALLOW_HAS_STEERING": "",
52
53
  },
53
54
  mono=mono,
@@ -0,0 +1,33 @@
1
+ from typing import List
2
+
3
+ from bluer_options.terminal import show_usage, xtra
4
+
5
+ from bluer_ugv import env
6
+
7
+
8
+ def help_test(
9
+ tokens: List[str],
10
+ mono: bool,
11
+ ) -> str:
12
+ options = xtra("dryrun", mono=mono)
13
+
14
+ args = [
15
+ "[--keys 1234567890-+/.]",
16
+ ]
17
+
18
+ return show_usage(
19
+ [
20
+ "@swallow",
21
+ "keyboard",
22
+ "test",
23
+ f"[{options}]",
24
+ ]
25
+ + args,
26
+ "test keyboard.",
27
+ mono=mono,
28
+ )
29
+
30
+
31
+ help_functions = {
32
+ "test": help_test,
33
+ }
@@ -4,7 +4,7 @@ from bluer_algo.socket.classes import SocketComm, DEV_HOST
4
4
  from bluer_sbc.imager.camera import instance as camera
5
5
  from bluer_sbc.env import BLUER_SBC_ENV
6
6
 
7
- from bluer_ugv.swallow.session.classical.keyboard import ClassicalKeyboard
7
+ from bluer_ugv.swallow.session.classical.keyboard.classes import ClassicalKeyboard
8
8
  from bluer_ugv.swallow.session.classical.leds import ClassicalLeds
9
9
  from bluer_ugv.swallow.session.classical.setpoint.classes import ClassicalSetPoint
10
10
  from bluer_ugv.logger import logger
@@ -13,7 +13,7 @@ from bluer_algo.image_classifier.model.predictor import ImageClassifierPredictor
13
13
 
14
14
  from bluer_ugv import env
15
15
  from bluer_ugv.swallow.session.classical.camera.generic import ClassicalCamera
16
- from bluer_ugv.swallow.session.classical.keyboard import ClassicalKeyboard
16
+ from bluer_ugv.swallow.session.classical.keyboard.classes import ClassicalKeyboard
17
17
  from bluer_ugv.swallow.session.classical.leds import ClassicalLeds
18
18
  from bluer_ugv.swallow.session.classical.setpoint.classes import ClassicalSetPoint
19
19
  from bluer_ugv.swallow.session.classical.mode import OperationMode
@@ -10,7 +10,7 @@ from bluer_sbc.imager.camera import instance as camera
10
10
  from bluer_ugv import env
11
11
  from bluer_ugv.swallow.session.classical.camera.generic import ClassicalCamera
12
12
  from bluer_ugv.swallow.session.classical.camera.generic import ClassicalCamera
13
- from bluer_ugv.swallow.session.classical.keyboard import ClassicalKeyboard
13
+ from bluer_ugv.swallow.session.classical.keyboard.classes import ClassicalKeyboard
14
14
  from bluer_ugv.swallow.session.classical.leds import ClassicalLeds
15
15
  from bluer_ugv.swallow.session.classical.setpoint.classes import ClassicalSetPoint
16
16
  from bluer_ugv.swallow.session.classical.mode import OperationMode
@@ -13,7 +13,7 @@ from bluer_algo.yolo.model.predictor import YoloPredictor
13
13
 
14
14
  from bluer_ugv import env
15
15
  from bluer_ugv.swallow.session.classical.camera.generic import ClassicalCamera
16
- from bluer_ugv.swallow.session.classical.keyboard import ClassicalKeyboard
16
+ from bluer_ugv.swallow.session.classical.keyboard.classes import ClassicalKeyboard
17
17
  from bluer_ugv.swallow.session.classical.leds import ClassicalLeds
18
18
  from bluer_ugv.swallow.session.classical.setpoint.classes import ClassicalSetPoint
19
19
  from bluer_ugv.swallow.session.classical.mode import OperationMode
@@ -48,15 +48,18 @@ class ClassicalYoloCamera(ClassicalCamera):
48
48
 
49
49
  assert super().initialize()
50
50
 
51
- assert storage.download(
51
+ if not storage.download(
52
52
  env.BLUER_UGV_SWALLOW_YOLO_MODEL,
53
53
  policy=DownloadPolicy.DOESNT_EXIST,
54
- )
54
+ ):
55
+ logger.error("cannot download the model.")
56
+
55
57
  success, self.predictor = YoloPredictor.load(
56
58
  object_name=env.BLUER_UGV_SWALLOW_YOLO_MODEL,
57
59
  image_size=BLUER_SBC_CAMERA_WIDTH,
58
60
  )
59
- assert success
61
+ if not success:
62
+ logger.error("cannot create the predictor.")
60
63
 
61
64
  self.running = True
62
65
  self.thread = threading.Thread(target=self.loop, daemon=True)
@@ -78,9 +81,10 @@ class ClassicalYoloCamera(ClassicalCamera):
78
81
 
79
82
  super().cleanup()
80
83
 
81
- assert self.dataset.save(
84
+ if not self.dataset.save(
82
85
  verbose=True,
83
- )
86
+ ):
87
+ logger.error("cannot save the dataset.")
84
88
 
85
89
  if self.dataset.empty:
86
90
  return
@@ -156,12 +160,14 @@ class ClassicalYoloCamera(ClassicalCamera):
156
160
  what="steering",
157
161
  value=env.BLUER_UGV_SWALLOW_STEERING_SETPOINT,
158
162
  log=True,
163
+ steering_expires_in=env.BLUER_UGV_SWALLOW_STEERING_YOLO_EXPIRY,
159
164
  )
160
165
  else:
161
166
  self.setpoint.put(
162
167
  what="steering",
163
168
  value=-env.BLUER_UGV_SWALLOW_STEERING_SETPOINT,
164
169
  log=True,
170
+ steering_expires_in=env.BLUER_UGV_SWALLOW_STEERING_YOLO_EXPIRY,
165
171
  )
166
172
 
167
173
  return True
@@ -0,0 +1,31 @@
1
+ import argparse
2
+
3
+ from blueness import module
4
+ from blueness.argparse.generic import sys_exit
5
+
6
+ from bluer_ugv import NAME
7
+ from bluer_ugv.swallow.session.classical.keyboard.testing import test
8
+ from bluer_ugv.logger import logger
9
+
10
+ NAME = module.name(__file__, NAME)
11
+
12
+ parser = argparse.ArgumentParser(NAME)
13
+ parser.add_argument(
14
+ "task",
15
+ type=str,
16
+ help="test",
17
+ )
18
+ parser.add_argument(
19
+ "--keys",
20
+ type=str,
21
+ default=" ",
22
+ )
23
+ args = parser.parse_args()
24
+
25
+ success = False
26
+ if args.task == "test":
27
+ success = test(args.keys)
28
+ else:
29
+ success = None
30
+
31
+ sys_exit(logger, NAME, args.task, success)
@@ -5,19 +5,13 @@ from typing import Any, Dict
5
5
  from bluer_sbc.session.functions import reply_to_bash
6
6
  from bluer_algo.socket.classes import DEV_HOST
7
7
 
8
- from bluer_ugv.swallow.session.classical.setpoint.classes import ClassicalSetPoint
9
- from bluer_ugv.swallow.session.classical.mode import OperationMode
8
+ from bluer_ugv.swallow.session.classical.keyboard.keys import ControlKeys
10
9
  from bluer_ugv.swallow.session.classical.leds import ClassicalLeds
10
+ from bluer_ugv.swallow.session.classical.mode import OperationMode
11
+ from bluer_ugv.swallow.session.classical.setpoint.classes import ClassicalSetPoint
11
12
  from bluer_ugv import env
12
13
  from bluer_ugv.logger import logger
13
14
 
14
- bash_keys = {
15
- "i": "exit",
16
- "o": "shutdown",
17
- "p": "reboot",
18
- "u": "update",
19
- }
20
-
21
15
 
22
16
  class ClassicalKeyboard:
23
17
  def __init__(
@@ -25,14 +19,9 @@ class ClassicalKeyboard:
25
19
  leds: ClassicalLeds,
26
20
  setpoint: ClassicalSetPoint,
27
21
  ):
28
- logger.info(
29
- "{}: {}".format(
30
- self.__class__.__name__,
31
- ", ".join(
32
- [f"{key}:{action}" for key, action in bash_keys.items()],
33
- ),
34
- )
35
- )
22
+ logger.info(self.__class__.__name__)
23
+
24
+ self.keys = ControlKeys()
36
25
 
37
26
  self.leds = leds
38
27
 
@@ -62,20 +51,20 @@ class ClassicalKeyboard:
62
51
 
63
52
  # bash keys
64
53
  if self.special_key:
65
- for key, event in bash_keys.items():
54
+ for key, event in self.keys.special_keys.items():
66
55
  if keyboard.is_pressed(key):
67
56
  reply_to_bash(event)
68
57
  return False
69
58
 
70
59
  # other keys
71
60
  for key, func in {
72
- " ": self.setpoint.stop,
61
+ self.keys.get("stop"): self.setpoint.stop,
73
62
  "x": self.setpoint.start,
74
- "s": lambda: self.setpoint.put(
63
+ self.keys.get("speed backward"): lambda: self.setpoint.put(
75
64
  what="speed",
76
65
  value=self.setpoint.get(what="speed") - 10,
77
66
  ),
78
- "w": lambda: self.setpoint.put(
67
+ self.keys.get("speed forward"): lambda: self.setpoint.put(
79
68
  what="speed",
80
69
  value=self.setpoint.get(what="speed") + 10,
81
70
  ),
@@ -85,14 +74,14 @@ class ClassicalKeyboard:
85
74
  func()
86
75
 
87
76
  # steering
88
- if keyboard.is_pressed("a"):
77
+ if keyboard.is_pressed(self.keys.get("steer left")):
89
78
  self.special_key = False
90
79
  self.last_key = "a"
91
80
  self.setpoint.put(
92
81
  what="steering",
93
82
  value=env.BLUER_UGV_SWALLOW_STEERING_SETPOINT,
94
83
  )
95
- elif keyboard.is_pressed("d"):
84
+ elif keyboard.is_pressed(self.keys.get("steer right")):
96
85
  self.special_key = False
97
86
  self.last_key = "d"
98
87
  self.setpoint.put(
@@ -100,19 +89,15 @@ class ClassicalKeyboard:
100
89
  value=-env.BLUER_UGV_SWALLOW_STEERING_SETPOINT,
101
90
  )
102
91
  else:
103
- self.setpoint.put(
104
- what="steering",
105
- value=0,
106
- log=False,
107
- )
92
+ self.setpoint.check_steering_expiry()
108
93
 
109
94
  # debug mode
110
- if keyboard.is_pressed("b"):
95
+ if keyboard.is_pressed(self.keys.get("debug on")):
111
96
  self.special_key = False
112
97
  self.set("debug_mode", True)
113
98
  logger.info(f'debug enabled, run "@swallow debug" on {DEV_HOST}.')
114
99
 
115
- if keyboard.is_pressed("v"):
100
+ if keyboard.is_pressed(self.keys.get("debug off")):
116
101
  self.special_key = False
117
102
  self.set("debug_mode", False)
118
103
  logger.info("debug disabled.")
@@ -120,33 +105,33 @@ class ClassicalKeyboard:
120
105
  # mode
121
106
  mode = self.get("mode", OperationMode.NONE)
122
107
  updated_mode = mode
123
- if keyboard.is_pressed("y"):
108
+ if keyboard.is_pressed(self.keys.get("mode = none")):
124
109
  updated_mode = OperationMode.NONE
125
110
 
126
- if keyboard.is_pressed("t"):
127
- updated_mode = OperationMode.TRAINING
128
-
129
- if keyboard.is_pressed("g"):
111
+ if keyboard.is_pressed(self.keys.get("mode = action")):
130
112
  updated_mode = OperationMode.ACTION
131
113
 
114
+ if keyboard.is_pressed(self.keys.get("mode = training")):
115
+ updated_mode = OperationMode.TRAINING
116
+
132
117
  if mode != updated_mode:
133
118
  self.set("mode", updated_mode)
134
119
  logger.info("mode: {}.".format(updated_mode.name.lower()))
135
120
  self.special_key = False
136
121
 
137
122
  # ultrasound
138
- if keyboard.is_pressed("n"):
123
+ if keyboard.is_pressed(self.keys.get("ultrasonic off")):
139
124
  self.set("ultrasound_enabled", False)
140
- logger.info("ultrasound: disabled")
125
+ logger.info("ultrasound: off")
141
126
  self.special_key = False
142
127
 
143
- if keyboard.is_pressed("m"):
128
+ if keyboard.is_pressed(self.keys.get("ultrasonic on")):
144
129
  self.set("ultrasound_enabled", True)
145
- logger.info("ultrasound: enabled")
130
+ logger.info("ultrasound: on")
146
131
  self.special_key = False
147
132
 
148
133
  # special key
149
- if keyboard.is_pressed("z") and not self.special_key:
134
+ if keyboard.is_pressed(self.keys.get("special key")) and not self.special_key:
150
135
  self.special_key = True
151
136
  logger.info("🪄 special key enabled.")
152
137
 
@@ -0,0 +1,81 @@
1
+ from typing import Dict, Tuple
2
+
3
+ from bluer_sbc.env import BLUER_SBC_SWALLOW_HAS_FULL_KEYBOARD
4
+
5
+ from bluer_ugv.logger import logger
6
+
7
+
8
+ class ControlKeys:
9
+ def __init__(
10
+ self,
11
+ is_numpad: bool = BLUER_SBC_SWALLOW_HAS_FULL_KEYBOARD == 0,
12
+ ):
13
+ self.is_numpad = is_numpad
14
+ logger.info(
15
+ "{}: {}".format(
16
+ self.__class__.__name__,
17
+ "numpad" if self.is_numpad else "full",
18
+ )
19
+ )
20
+
21
+ self._keys: Dict[str, Tuple[str, str]] = {
22
+ "ultrasonic off": ("n", "-"),
23
+ "ultrasonic on": ("m", "+"),
24
+ "debug off": ("v", "9"),
25
+ "debug on": ("b", "7"),
26
+ "mode = none": ("y", "5"),
27
+ "mode = action": ("g", "1"),
28
+ "mode = training": ("t", "3"),
29
+ "special key": ("z", "."),
30
+ "speed backward": ("s", "2"),
31
+ "speed forward": ("w", "8"),
32
+ "steer left": ("a", "4"),
33
+ "steer right": ("d", "6"),
34
+ "stop": (" ", "0"),
35
+ }
36
+
37
+ @staticmethod
38
+ def as_table():
39
+ keys = ControlKeys()
40
+ table = keys._keys.copy() # pylint: disable=protected-access
41
+
42
+ for is_numpad in [False, True]:
43
+ keys.is_numpad = is_numpad
44
+
45
+ special_keys = keys.special_keys
46
+ for key, event in special_keys.items():
47
+ if event not in table:
48
+ table[event] = ["", ""]
49
+
50
+ table[event][int(is_numpad)] = f"*{key}"
51
+
52
+ return [
53
+ "| event | full keyboard | numpad |",
54
+ "|-|-|-|",
55
+ ] + sorted(
56
+ [
57
+ " | ".join(["", event] + list(keys) + [""])
58
+ for event, keys in table.items()
59
+ ]
60
+ )
61
+
62
+ def get(self, event: str) -> str:
63
+ return self._keys[event][int(self.is_numpad)]
64
+
65
+ @property
66
+ def special_keys(self) -> Dict[str, str]:
67
+ return (
68
+ {
69
+ "7": "exit",
70
+ "9": "shutdown",
71
+ "5": "reboot",
72
+ "1": "update",
73
+ }
74
+ if self.is_numpad
75
+ else {
76
+ "i": "exit",
77
+ "o": "shutdown",
78
+ "p": "reboot",
79
+ "u": "update",
80
+ }
81
+ )
@@ -0,0 +1,22 @@
1
+ import keyboard
2
+
3
+ from blueness import module
4
+
5
+ from bluer_ugv import NAME
6
+ from bluer_ugv.logger import logger
7
+
8
+ NAME = module.name(__file__, NAME)
9
+
10
+
11
+ def test(list_of_keys: str = "") -> bool:
12
+ logger.info("{}.testing({}): ^C to stop".format(NAME, list_of_keys))
13
+
14
+ try:
15
+ while True:
16
+ for key in list_of_keys:
17
+ if keyboard.is_pressed(key):
18
+ logger.info(f"{key} is pressed.")
19
+ except KeyboardInterrupt:
20
+ logger.info("^C detected.")
21
+
22
+ return True
@@ -13,7 +13,7 @@ from bluer_ugv.swallow.session.classical.camera import (
13
13
  ClassicalYoloCamera,
14
14
  )
15
15
  from bluer_ugv.swallow.session.classical.push_button import ClassicalPushButton
16
- from bluer_ugv.swallow.session.classical.keyboard import ClassicalKeyboard
16
+ from bluer_ugv.swallow.session.classical.keyboard.classes import ClassicalKeyboard
17
17
  from bluer_ugv.swallow.session.classical.leds import ClassicalLeds
18
18
  from bluer_ugv.swallow.session.classical.mousepad import ClassicalMousePad
19
19
  from bluer_ugv.swallow.session.classical.motor import (
@@ -1,5 +1,8 @@
1
1
  import threading
2
2
  from typing import Union, Dict
3
+ import time
4
+
5
+ from bluer_options import string
3
6
 
4
7
  from bluer_ugv.swallow.session.classical.leds import ClassicalLeds
5
8
  from bluer_ugv.swallow.session.classical.setpoint.steering import (
@@ -15,6 +18,9 @@ class ClassicalSetPoint:
15
18
  ):
16
19
  self.speed = 0
17
20
  self.steering = 0
21
+
22
+ self.steering_expiry = time.time()
23
+
18
24
  self.started = False
19
25
 
20
26
  self.leds = leds
@@ -51,17 +57,49 @@ class ClassicalSetPoint:
51
57
  logger.error(f"{self.__class__.__name__}.get: {what} not found.")
52
58
  return 0
53
59
 
60
+ def check_steering_expiry(
61
+ self,
62
+ log: bool = True,
63
+ ):
64
+ with self._lock:
65
+ if self.steering == 0:
66
+ return
67
+
68
+ if self.steering_expiry > time.time():
69
+ if log:
70
+ logger.info(
71
+ "setpoint will expire in {}.".format(
72
+ string.pretty_duration(
73
+ self.steering_expiry - time.time(),
74
+ largest=True,
75
+ short=True,
76
+ include_ms=True,
77
+ )
78
+ )
79
+ )
80
+ return
81
+
82
+ if log:
83
+ logger.info("setpoint expired.")
84
+
85
+ self.put(
86
+ what="steering",
87
+ value=0,
88
+ )
89
+
54
90
  def put(
55
91
  self,
56
92
  value: Union[int, bool, Dict[str, Union[int, bool]]],
57
93
  what: str = "all",
58
- log: bool = False,
94
+ log: bool = True,
95
+ steering_expires_in: float = 0,
59
96
  ):
60
97
  with self._lock:
61
98
  if what == "all":
62
99
  self.speed = min(100, max(-100, int(value["speed"])))
63
100
  self.started = bool(value["started"])
64
101
  self.steering = min(100, max(-100, int(value["steering"])))
102
+ self.steering_expiry = time.time() + steering_expires_in
65
103
  return
66
104
 
67
105
  if what == "speed":
@@ -88,11 +126,18 @@ class ClassicalSetPoint:
88
126
 
89
127
  if what == "steering":
90
128
  self.steering = min(100, max(-100, int(value)))
129
+ self.steering_expiry = time.time() + steering_expires_in
91
130
  if log:
92
131
  logger.info(
93
- "{}.put: steering={}".format(
132
+ "{}.put: steering={}, expires in {}".format(
94
133
  self.__class__.__name__,
95
134
  self.steering,
135
+ string.pretty_duration(
136
+ steering_expires_in,
137
+ largest=True,
138
+ short=True,
139
+ include_ms=True,
140
+ ),
96
141
  )
97
142
  )
98
143
  return
@@ -13,7 +13,7 @@ from bluer_ugv.swallow.session.classical.ultrasonic_sensor.detection import (
13
13
  from bluer_ugv.swallow.session.classical.ultrasonic_sensor.log import (
14
14
  UltrasonicSensorDetectionLog,
15
15
  )
16
- from bluer_ugv.swallow.session.classical.keyboard import ClassicalKeyboard
16
+ from bluer_ugv.swallow.session.classical.keyboard.classes import ClassicalKeyboard
17
17
  from bluer_ugv.swallow.session.classical.setpoint.classes import ClassicalSetPoint
18
18
  from bluer_ugv.logger import logger
19
19
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: bluer_ugv
3
- Version: 7.165.1
3
+ Version: 7.196.1
4
4
  Summary: 🐬 AI x UGV.
5
5
  Home-page: https://github.com/kamangir/bluer-ugv
6
6
  Author: Arash Abadpour (Kamangir)
@@ -64,7 +64,7 @@ pip install bluer_ugv
64
64
 
65
65
  [![pylint](https://github.com/kamangir/bluer-ugv/actions/workflows/pylint.yml/badge.svg)](https://github.com/kamangir/bluer-ugv/actions/workflows/pylint.yml) [![pytest](https://github.com/kamangir/bluer-ugv/actions/workflows/pytest.yml/badge.svg)](https://github.com/kamangir/bluer-ugv/actions/workflows/pytest.yml) [![bashtest](https://github.com/kamangir/bluer-ugv/actions/workflows/bashtest.yml/badge.svg)](https://github.com/kamangir/bluer-ugv/actions/workflows/bashtest.yml) [![PyPI version](https://img.shields.io/pypi/v/bluer-ugv.svg)](https://pypi.org/project/bluer-ugv/) [![PyPI - Downloads](https://img.shields.io/pypi/dd/bluer-ugv)](https://pypistats.org/packages/bluer-ugv)
66
66
 
67
- built by 🌀 [`bluer README`](https://github.com/kamangir/bluer-objects/tree/main/bluer_objects/README), based on 🐬 [`bluer_ugv-7.165.1`](https://github.com/kamangir/bluer-ugv).
67
+ built by 🌀 [`bluer README`](https://github.com/kamangir/bluer-objects/tree/main/bluer_objects/README), based on 🐬 [`bluer_ugv-7.196.1`](https://github.com/kamangir/bluer-ugv).
68
68
 
69
69
 
70
70
  built by 🌀 [`blueness-3.118.1`](https://github.com/kamangir/blueness).
@@ -1,7 +1,7 @@
1
- bluer_ugv/__init__.py,sha256=JJ0tVY2eOpqi0O3BbaKQN2lpYy4YaN-H_pd9Ip_wbFY,288
1
+ bluer_ugv/__init__.py,sha256=dlZ6KdgmjA40cFkgY0OcNNt-vfLvgx9fTB-WGQtQ2RI,288
2
2
  bluer_ugv/__main__.py,sha256=77TquqyMca7qHk0XtCixGVyzfW3_9ywnl5oXEPERlls,374
3
- bluer_ugv/config.env,sha256=hVPPKSdHWtbjLPWUKaMdFfuBgc8I2ThXgt8OOMhPNrQ,906
4
- bluer_ugv/env.py,sha256=gROxchvg4M-VpH8T_zIaVjV4xzoTzO77lVZXO_5YjzA,1649
3
+ bluer_ugv/config.env,sha256=psiLmasSe300nOPkLqMurFalZTvNE43zAsBQLEEDp-k,949
4
+ bluer_ugv/env.py,sha256=asv-2OByZzf1c4ta3CHMZQDEcY8cd2WDUOa-_OCNYvU,1757
5
5
  bluer_ugv/host.py,sha256=DpdJCvBpUfP9LkZgcH4BcdLGD-WZUvbTsjvMfPtS8uY,292
6
6
  bluer_ugv/logger.py,sha256=faY6GL6xfZAzlZ1aJ-MEHuPRJZNx8PYS4jMyY3xuxMw,98
7
7
  bluer_ugv/sample.env,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -15,6 +15,7 @@ bluer_ugv/.abcli/swallow.sh,sha256=hfgFLNtqePdH5kDuNJoIvOfyKpef26Qq3pXhgsSaLAs,3
15
15
  bluer_ugv/.abcli/swallow/dataset.sh,sha256=w-uuMLZEkfDbseLlCZu4xsg0veznj6ATU88Lzclh3xo,342
16
16
  bluer_ugv/.abcli/swallow/debug.sh,sha256=JVjExhotePW3gZG2MUS6IzbXVQwMAefKYJiSP88wqlk,559
17
17
  bluer_ugv/.abcli/swallow/env.sh,sha256=5rKCdZhrQa_9Lr96j1h7XrWBcf0YEeV3w3o0vLWGd0M,360
18
+ bluer_ugv/.abcli/swallow/keyboard.sh,sha256=RYR5vgV0C1SATqekQ_F6Lr6Ums0IAkH9THX2ZPcitoY,402
18
19
  bluer_ugv/.abcli/swallow/select_target.sh,sha256=fwHmKbVcn_OEW4q-cjNc8Eyi6hOi1pMAb6x5tW8_lb0,183
19
20
  bluer_ugv/.abcli/swallow/session.sh,sha256=mMSq2kl8q1v-6QRgz5iK9oJid0VC2AGjwK1dZCMUtLo,885
20
21
  bluer_ugv/.abcli/swallow/ultrasonic.sh,sha256=GqnVn4u-FFC8SVsCYHiwABBDkgALe4mgRMloitlfeP8,380
@@ -25,11 +26,12 @@ bluer_ugv/.abcli/swallow/dataset/list.sh,sha256=-hqgmThG2JfheFSYIe6Z3UH05X5hrSuI
25
26
  bluer_ugv/.abcli/swallow/dataset/upload.sh,sha256=KM33QM4rIQpltbd_V49wPWear9Wi8cJNo0bBBeCEENU,577
26
27
  bluer_ugv/.abcli/swallow/env/cp.sh,sha256=vWBlG9n4Q6m_lBWcot9nyN6kc7-uil5skCjfJWHCfrY,168
27
28
  bluer_ugv/.abcli/swallow/env/list.sh,sha256=pT-hRS0ZfmogAfAMfm-hh0raGoUAnl66U5VuqgyeIwE,173
28
- bluer_ugv/.abcli/swallow/env/set.sh,sha256=_FWlraNupKcOcmcyuJHFjsyUViS6L0NXV-aDtEMrF-I,450
29
+ bluer_ugv/.abcli/swallow/env/set.sh,sha256=TfRGz5mZ1ezGaJVZWPNf4yCpC2xOEk-Im5uKVvnLR00,555
30
+ bluer_ugv/.abcli/swallow/keyboard/test.sh,sha256=B04AO-Er3_utzULPziyKD0aybuN2bry7h9wrQBEJ0tA,218
29
31
  bluer_ugv/.abcli/swallow/ultrasonic/review.sh,sha256=XoKwUliTcH-yTHrIo1cc9RSxL3tYQsBfWf1XOJ6YtOI,717
30
32
  bluer_ugv/.abcli/swallow/ultrasonic/test.sh,sha256=WRq4jnm2lv6q7fAw-_6Xg7DD8kgki48t8ilwXA-SsBM,582
31
33
  bluer_ugv/.abcli/tests/README.sh,sha256=w1xjPWgCfWbLtON_LEn2cvSmPLulzm7kTBPEC3LJixs,142
32
- bluer_ugv/.abcli/tests/help.sh,sha256=Jz5S7PPedcA6mUvLMlZ6kiXDshWt0TkQuaMx8XUW9UQ,1108
34
+ bluer_ugv/.abcli/tests/help.sh,sha256=WOPID4QyuS57vpl5uEyYwytOF_pnMsbm4YgcZUcuvu8,1193
33
35
  bluer_ugv/.abcli/tests/swallow_dataset_combine.sh,sha256=tXjZj5iOOmCz3ito9lBDYjaAvR2odNzs2LRXsrM6d6c,291
34
36
  bluer_ugv/.abcli/tests/swallow_dataset_combine_explicit.sh,sha256=Ff4V7fi-h1myRT9ajjaKXesNrpaxLZMGDidBT8G31Kw,360
35
37
  bluer_ugv/.abcli/tests/swallow_dataset_combine_sequence.sh,sha256=N3Iq-zJV2OfEoft44D1BBLOlrkAbUDN_Rp_sAmjCEVk,311
@@ -75,7 +77,7 @@ bluer_ugv/README/swallow/digital/__init__.py,sha256=kyb46k4FsGZKgWW2QRM33pLUQl5t
75
77
  bluer_ugv/README/swallow/digital/algo/__init__.py,sha256=iHwEi_kwQUk0E3YtGKDrjTKV-PDRuDpAo69IMCE8uZ4,711
76
78
  bluer_ugv/README/swallow/digital/algo/navigation.py,sha256=Hg_tkGYnE8qbM37Go4KlAaO-sNAtOBmaNZlPda45BCc,1780
77
79
  bluer_ugv/README/swallow/digital/algo/yolo.py,sha256=NlDISZ9LOUmMAzdEYzVYOrIwbDGdM8euMURlBOGACUk,930
78
- bluer_ugv/README/swallow/digital/design/__init__.py,sha256=jc18icYAdDUdyAgfGVpziVCXTMbd_VjGX1cGhDyyKr0,2071
80
+ bluer_ugv/README/swallow/digital/design/__init__.py,sha256=RwH9vIDnocrKVt5WaBZq3Nxh2DygOLWelOsrvyEl1Aw,2324
79
81
  bluer_ugv/README/swallow/digital/design/mechanical.py,sha256=OwgMrFIpRA-RR9CwurXaif09GCd6_i3zGuAfkH0jtsM,983
80
82
  bluer_ugv/README/swallow/digital/design/ultrasonic_sensor.py,sha256=VefIdTUXnsxVj3rmjsguV7N2BD9tPRiiaHjjRl84QUM,1517
81
83
  bluer_ugv/designs/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -96,10 +98,11 @@ bluer_ugv/help/__init__.py,sha256=ajz1GSNU9xYVrFEDSz6Xwg7amWQ_yvW75tQa1ZvRIWc,3
96
98
  bluer_ugv/help/__main__.py,sha256=ww3p0cIRZm-SDODZ_fYAzPV_-nucxtidjK1IP2idW8g,229
97
99
  bluer_ugv/help/functions.py,sha256=_JcncL82A-6m9P9J6MX6Z_FtZ09k6HWuirozKl48xXY,367
98
100
  bluer_ugv/help/git.py,sha256=4CcaA8lHoplrrFgF5lolwVT79SLr3gE2iqXpAIfzH64,319
99
- bluer_ugv/help/swallow/__init__.py,sha256=lCi1OPBV-ZiTGhOiTW7E4x-LuokoV5lvR9qGHsXkuSI,543
101
+ bluer_ugv/help/swallow/__init__.py,sha256=LZRT9EhacDqXqTKgygmJ-LraGwqciP3Ahp3P4p5o7R8,650
100
102
  bluer_ugv/help/swallow/dataset.py,sha256=59D5XLQG1PRWfPwfM73Jz1-f0qh_cO0q18qLtsxXtj0,2495
101
103
  bluer_ugv/help/swallow/debug.py,sha256=70krqg-YtjxPjPwWnx4J1Fxlvw46hHyAYq7pA7yPt50,481
102
- bluer_ugv/help/swallow/env.py,sha256=kkpzILdOQxnfWlGMcHMUAfeijDR20dR_WrI9CSCk9co,1010
104
+ bluer_ugv/help/swallow/env.py,sha256=PUrh0CD-UPqpJQjzonndji9yZs8nRfYCa26M3MnctRM,1096
105
+ bluer_ugv/help/swallow/keyboard.py,sha256=YNkGWvE7tN3agCaL2R30FSIF2zw6oXa5ZJdnTJQA3Hk,518
103
106
  bluer_ugv/help/swallow/select_target.py,sha256=s1-v2IyT6thAncIzo4wKnU8hFJ-rDyi-IDzx2kMaJrs,390
104
107
  bluer_ugv/help/swallow/ultrasonic_sensor.py,sha256=rhxHQWDU7orCvqC_TeJWMCJFrm4qyJyHdiUIUIpZmhU,1223
105
108
  bluer_ugv/swallow/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -113,17 +116,21 @@ bluer_ugv/swallow/session/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJW
113
116
  bluer_ugv/swallow/session/__main__.py,sha256=QFOnflCI6tB_qoG0S4Dpy-L0pW20tFffPPOb96LtypM,636
114
117
  bluer_ugv/swallow/session/functions.py,sha256=Jfv7Ab6TEhZMtVv348imNg7JVgPNezFcuovq5r65rAo,666
115
118
  bluer_ugv/swallow/session/classical/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
116
- bluer_ugv/swallow/session/classical/keyboard.py,sha256=qC5GCV3sik3edcId88kTRpt4EAiTxnLTW03pZCdTxP0,4497
117
119
  bluer_ugv/swallow/session/classical/leds.py,sha256=ElhE08rm-KLbQ59lJzStLWeNsfoO7tV2fPBMBXCKX_E,2241
118
120
  bluer_ugv/swallow/session/classical/mode.py,sha256=6rFe1IIpfijuI7Xd-wcGKhYQ7EdQxG4mYGVliTjS118,117
119
121
  bluer_ugv/swallow/session/classical/mousepad.py,sha256=LI7yvmtrZZaGUgPGpxNU7zcPkW8D5ykHlY_O-4H2STs,1871
120
122
  bluer_ugv/swallow/session/classical/push_button.py,sha256=s8sPart_dECjLK-gfsJi0UorRYcFYf3ofLqjmG8PoA8,2397
121
- bluer_ugv/swallow/session/classical/session.py,sha256=pl-IWDywqPQgmsLhHSa24BkuAQ2mg82VqqbkxrDMP5M,5176
123
+ bluer_ugv/swallow/session/classical/session.py,sha256=mkWG1FfbU_lVAAf0MQRdOboMkg_jCozU_21BVex0Q2c,5184
122
124
  bluer_ugv/swallow/session/classical/camera/__init__.py,sha256=KOehn6qHKj3EMbV5uGXKIfN_v4D5-E2xH9aCWqbNlAI,375
123
- bluer_ugv/swallow/session/classical/camera/generic.py,sha256=ARcuj0Fm76pxu2bmiV2d89ZNNWBPaARn5-oxa_QcT3I,1193
124
- bluer_ugv/swallow/session/classical/camera/navigation.py,sha256=xSB-ExYjco5Hkpo_dgCLkD1c66il-KMamfsL_E9qXBA,6782
125
- bluer_ugv/swallow/session/classical/camera/tracking.py,sha256=PLwwH7MK8RudeDNYtzkxnPH9CTJAB6kDE4YI8g6aTzs,3643
126
- bluer_ugv/swallow/session/classical/camera/yolo.py,sha256=se26LWRlG25k_ZCmfoC9pbSPtwxzYpwJnIYvPMIIE2g,5882
125
+ bluer_ugv/swallow/session/classical/camera/generic.py,sha256=9xTXisNYoiNVtT0-2wW9DvD6viIPpRR7rIyAwnbyvWs,1201
126
+ bluer_ugv/swallow/session/classical/camera/navigation.py,sha256=HoeTlifGEfnedb6o8P-O0TcP1bNDRJ0M7vWupQh1pL4,6790
127
+ bluer_ugv/swallow/session/classical/camera/tracking.py,sha256=fXDCA7UCQT0I6_djk16AgRdulySVEjJSKOgD8bDpQng,3651
128
+ bluer_ugv/swallow/session/classical/camera/yolo.py,sha256=jKn3M_FKUIMVSvhwgQ6kaWxLCi-l_490Zbaytjwj5_I,6219
129
+ bluer_ugv/swallow/session/classical/keyboard/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
130
+ bluer_ugv/swallow/session/classical/keyboard/__main__.py,sha256=tdX-a8MC9ix6aQ9isZXfnIqa9SuiYGr73Yy05RwvdCs,603
131
+ bluer_ugv/swallow/session/classical/keyboard/classes.py,sha256=8_uLhtbgLcFge1pfenzwunJjLqBK_z6-j6lf4ztIE5A,4570
132
+ bluer_ugv/swallow/session/classical/keyboard/keys.py,sha256=p1VkrQs_oq4NkZfmNM4HMlf4FcDz8k7eQneJIvaM7_c,2272
133
+ bluer_ugv/swallow/session/classical/keyboard/testing.py,sha256=GFh-6-HkT1sYlGt-Y2traBFD8lle3C-HcvVrdzsITEo,511
127
134
  bluer_ugv/swallow/session/classical/motor/__init__.py,sha256=Ja9pVS6h5wnZiDvJ2IaibLcleQl3inIF_YRJg9VGKlw,323
128
135
  bluer_ugv/swallow/session/classical/motor/generic.py,sha256=VzCEqkuil-7ncyv2TxI7NMofIiLhuZGl61Ck3Yog55s,2860
129
136
  bluer_ugv/swallow/session/classical/motor/left.py,sha256=eKyEI8CqQiUTTmpNlJrXro90x2_la5KejVLgj_pXkQM,537
@@ -131,11 +138,11 @@ bluer_ugv/swallow/session/classical/motor/rear.py,sha256=mIBpUxBeiw1me5WY3jbtMya
131
138
  bluer_ugv/swallow/session/classical/motor/right.py,sha256=3BwCXA6VxxyRBG3rsnRXGviS5gIda14UCqaELGMOJNk,539
132
139
  bluer_ugv/swallow/session/classical/motor/steering.py,sha256=-_-6C9cGYFgt_WH3hwTSV8jL5I_qkxc2O45Ck8SlFCo,545
133
140
  bluer_ugv/swallow/session/classical/setpoint/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
134
- bluer_ugv/swallow/session/classical/setpoint/classes.py,sha256=X3v_kLyrtjdTRXUCSmf4vJhUHrfFGqhFqA9WZ3y0an0,3654
141
+ bluer_ugv/swallow/session/classical/setpoint/classes.py,sha256=a2ACbE4oEdguuOjtrP2bIyuEpl97TK_JCTGir05KZkg,5054
135
142
  bluer_ugv/swallow/session/classical/setpoint/steering.py,sha256=yuhW3u9YgZ756h4wyMWJYW9914d8oYRKLga67rTW-Tw,288
136
143
  bluer_ugv/swallow/session/classical/ultrasonic_sensor/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
137
144
  bluer_ugv/swallow/session/classical/ultrasonic_sensor/__main__.py,sha256=SHCwEk_K9L0BG1X7W1JnnhTnQBGJ--TiN-QuH2Je28E,1732
138
- bluer_ugv/swallow/session/classical/ultrasonic_sensor/classes.py,sha256=i7EfePznQqVjCM7P7vUtXKOj-bXQclTvv0iB4hURw7M,4078
145
+ bluer_ugv/swallow/session/classical/ultrasonic_sensor/classes.py,sha256=MIwfvni7DVLo3whxHnfnKiftbcksLhsoQI61wCH_hoU,4086
139
146
  bluer_ugv/swallow/session/classical/ultrasonic_sensor/consts.py,sha256=eP5Kb6aGqOAcOBBlhGvSWbUL_hKJZ8w5ggwkndzKBqo,227
140
147
  bluer_ugv/swallow/session/classical/ultrasonic_sensor/detection.py,sha256=v_yCBzg4uvnra4Yy_M3Ngaab80PBEbkp2SHfaWfXgb8,3720
141
148
  bluer_ugv/swallow/session/classical/ultrasonic_sensor/log.py,sha256=Ks_VqD6tV0Yw0lcSETOFcMwQaUedwLBwLlSblIrVs24,10202
@@ -143,8 +150,8 @@ bluer_ugv/swallow/session/classical/ultrasonic_sensor/pack.py,sha256=vMvmay2Gxg8
143
150
  bluer_ugv/swallow/session/classical/ultrasonic_sensor/review.py,sha256=_iQmec2VSq-ORkTVpXSNJg08hrSz2M1O8LzNZEtoT9U,959
144
151
  bluer_ugv/swallow/session/classical/ultrasonic_sensor/sensor.py,sha256=En-J8BRTiR8k9p2CBbW0cOUuw8nctD5DOXDm5uhCNO4,3987
145
152
  bluer_ugv/swallow/session/classical/ultrasonic_sensor/testing.py,sha256=RIMHXmLXe1zXLvCNU163ymLI8XM6te9LXuCMnLuulbA,1515
146
- bluer_ugv-7.165.1.dist-info/licenses/LICENSE,sha256=ogEPNDSH0_dhiv_lT3ifVIdgIzHAqNA_SemnxUfPBJk,7048
147
- bluer_ugv-7.165.1.dist-info/METADATA,sha256=dkZvtx7qSjx5t5lxjnjpKwTEhGseJEGKT02SMDkRZ8Q,5596
148
- bluer_ugv-7.165.1.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
149
- bluer_ugv-7.165.1.dist-info/top_level.txt,sha256=_MlDhFvIPpher9Zs7xyJTHgO2xJJTbfR1dzncz3LQnk,10
150
- bluer_ugv-7.165.1.dist-info/RECORD,,
153
+ bluer_ugv-7.196.1.dist-info/licenses/LICENSE,sha256=ogEPNDSH0_dhiv_lT3ifVIdgIzHAqNA_SemnxUfPBJk,7048
154
+ bluer_ugv-7.196.1.dist-info/METADATA,sha256=R3pyTxNAj-cE0OAy-YE1FmpHNwS75OsEM7qGfDI3u3Y,5596
155
+ bluer_ugv-7.196.1.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
156
+ bluer_ugv-7.196.1.dist-info/top_level.txt,sha256=_MlDhFvIPpher9Zs7xyJTHgO2xJJTbfR1dzncz3LQnk,10
157
+ bluer_ugv-7.196.1.dist-info/RECORD,,