valetudo-map-parser 0.1.11b1__py3-none-any.whl → 0.1.12b0__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.
- valetudo_map_parser/__init__.py +124 -15
- valetudo_map_parser/config/async_utils.py +1 -1
- valetudo_map_parser/config/colors.py +2 -419
- valetudo_map_parser/config/drawable.py +10 -73
- valetudo_map_parser/config/rand256_parser.py +129 -111
- valetudo_map_parser/config/shared.py +27 -8
- valetudo_map_parser/config/status_text/__init__.py +6 -0
- valetudo_map_parser/config/status_text/status_text.py +74 -49
- valetudo_map_parser/config/types.py +74 -408
- valetudo_map_parser/config/utils.py +99 -75
- valetudo_map_parser/const.py +288 -0
- valetudo_map_parser/hypfer_draw.py +121 -150
- valetudo_map_parser/hypfer_handler.py +210 -183
- valetudo_map_parser/map_data.py +31 -0
- valetudo_map_parser/rand256_handler.py +207 -218
- valetudo_map_parser/rooms_handler.py +4 -5
- {valetudo_map_parser-0.1.11b1.dist-info → valetudo_map_parser-0.1.12b0.dist-info}/METADATA +1 -1
- valetudo_map_parser-0.1.12b0.dist-info/RECORD +34 -0
- valetudo_map_parser-0.1.11b1.dist-info/RECORD +0 -32
- {valetudo_map_parser-0.1.11b1.dist-info → valetudo_map_parser-0.1.12b0.dist-info}/WHEEL +0 -0
- {valetudo_map_parser-0.1.11b1.dist-info → valetudo_map_parser-0.1.12b0.dist-info}/licenses/LICENSE +0 -0
- {valetudo_map_parser-0.1.11b1.dist-info → valetudo_map_parser-0.1.12b0.dist-info}/licenses/NOTICE.txt +0 -0
|
@@ -15,10 +15,8 @@ from mvcrender.autocrop import AutoCrop
|
|
|
15
15
|
|
|
16
16
|
from .config.async_utils import AsyncPIL
|
|
17
17
|
from .config.drawable_elements import DrawableElement
|
|
18
|
+
from .const import COLORS, DEFAULT_IMAGE_SIZE, DEFAULT_PIXEL_SIZE
|
|
18
19
|
from .config.types import (
|
|
19
|
-
COLORS,
|
|
20
|
-
DEFAULT_IMAGE_SIZE,
|
|
21
|
-
DEFAULT_PIXEL_SIZE,
|
|
22
20
|
LOGGER,
|
|
23
21
|
Colors,
|
|
24
22
|
Destinations,
|
|
@@ -50,6 +48,8 @@ class ReImageHandler(BaseHandler, AutoCrop):
|
|
|
50
48
|
AutoCrop.__init__(self, self)
|
|
51
49
|
self.auto_crop = None # Auto crop flag
|
|
52
50
|
self.segment_data = None # Segment data
|
|
51
|
+
self.element_map = None # Element map for tracking drawable elements
|
|
52
|
+
self.robot_position = None # Robot position for zoom functionality
|
|
53
53
|
self.outlines = None # Outlines data
|
|
54
54
|
self.calibration_data = None # Calibration data
|
|
55
55
|
self.data = RandImageData # Image Data
|
|
@@ -86,7 +86,6 @@ class ReImageHandler(BaseHandler, AutoCrop):
|
|
|
86
86
|
json_data, size_x, size_y, top, left, True
|
|
87
87
|
)
|
|
88
88
|
|
|
89
|
-
|
|
90
89
|
dest_json = destinations if destinations else {}
|
|
91
90
|
zones_data = dest_json.get("zones", [])
|
|
92
91
|
points_data = dest_json.get("spots", [])
|
|
@@ -98,7 +97,7 @@ class ReImageHandler(BaseHandler, AutoCrop):
|
|
|
98
97
|
|
|
99
98
|
# Update self.rooms_pos from room_properties for compatibility with other methods
|
|
100
99
|
self.rooms_pos = []
|
|
101
|
-
for
|
|
100
|
+
for _, room_data in room_properties.items():
|
|
102
101
|
self.rooms_pos.append(
|
|
103
102
|
{"name": room_data["name"], "outline": room_data["outline"]}
|
|
104
103
|
)
|
|
@@ -197,6 +196,94 @@ class ReImageHandler(BaseHandler, AutoCrop):
|
|
|
197
196
|
# If we reach here without returning, return None
|
|
198
197
|
return None
|
|
199
198
|
|
|
199
|
+
async def _initialize_base_layer(
|
|
200
|
+
self,
|
|
201
|
+
m_json,
|
|
202
|
+
size_x,
|
|
203
|
+
size_y,
|
|
204
|
+
colors,
|
|
205
|
+
destinations,
|
|
206
|
+
robot_position,
|
|
207
|
+
robot_position_angle,
|
|
208
|
+
):
|
|
209
|
+
"""Initialize the base layer on first frame."""
|
|
210
|
+
self.element_map = np.zeros((size_y, size_x), dtype=np.int32)
|
|
211
|
+
self.element_map[:] = DrawableElement.FLOOR
|
|
212
|
+
|
|
213
|
+
if self.drawing_config.is_enabled(DrawableElement.FLOOR):
|
|
214
|
+
room_id, img_np_array = await self.imd.async_draw_base_layer(
|
|
215
|
+
m_json,
|
|
216
|
+
size_x,
|
|
217
|
+
size_y,
|
|
218
|
+
colors["wall"],
|
|
219
|
+
colors["zone_clean"],
|
|
220
|
+
colors["background"],
|
|
221
|
+
DEFAULT_PIXEL_SIZE,
|
|
222
|
+
)
|
|
223
|
+
LOGGER.info("%s: Completed base Layers", self.file_name)
|
|
224
|
+
|
|
225
|
+
if room_id > 0 and not self.room_propriety:
|
|
226
|
+
self.room_propriety = await self.get_rooms_attributes(destinations)
|
|
227
|
+
|
|
228
|
+
if not self.rooms_pos and not self.room_propriety:
|
|
229
|
+
self.room_propriety = await self.get_rooms_attributes(destinations)
|
|
230
|
+
|
|
231
|
+
if (
|
|
232
|
+
self.rooms_pos
|
|
233
|
+
and robot_position
|
|
234
|
+
and (self.robot_pos is None or "in_room" not in self.robot_pos)
|
|
235
|
+
):
|
|
236
|
+
self.robot_pos = await self.async_get_robot_in_room(
|
|
237
|
+
(robot_position[0] * 10),
|
|
238
|
+
(robot_position[1] * 10),
|
|
239
|
+
robot_position_angle,
|
|
240
|
+
)
|
|
241
|
+
else:
|
|
242
|
+
background_color = self.drawing_config.get_property(
|
|
243
|
+
DrawableElement.FLOOR, "color", colors["background"]
|
|
244
|
+
)
|
|
245
|
+
img_np_array = await self.draw.create_empty_image(
|
|
246
|
+
size_x, size_y, background_color
|
|
247
|
+
)
|
|
248
|
+
|
|
249
|
+
if self.img_base_layer is not None:
|
|
250
|
+
del self.img_base_layer
|
|
251
|
+
self.img_base_layer = await self.async_copy_array(img_np_array)
|
|
252
|
+
del img_np_array
|
|
253
|
+
|
|
254
|
+
async def _check_zoom_conditions(self, m_json, robot_position, destinations):
|
|
255
|
+
"""Check and set zoom conditions based on active zones."""
|
|
256
|
+
if not (
|
|
257
|
+
self.shared.image_auto_zoom
|
|
258
|
+
and self.shared.vacuum_state == "cleaning"
|
|
259
|
+
and robot_position
|
|
260
|
+
and destinations
|
|
261
|
+
):
|
|
262
|
+
return
|
|
263
|
+
|
|
264
|
+
try:
|
|
265
|
+
temp_room_properties = (
|
|
266
|
+
await self.rooms_handler.async_extract_room_properties(
|
|
267
|
+
m_json, destinations
|
|
268
|
+
)
|
|
269
|
+
)
|
|
270
|
+
if temp_room_properties:
|
|
271
|
+
temp_rooms_pos = []
|
|
272
|
+
for _, room_data in temp_room_properties.items():
|
|
273
|
+
temp_rooms_pos.append(
|
|
274
|
+
{"name": room_data["name"], "outline": room_data["outline"]}
|
|
275
|
+
)
|
|
276
|
+
original_rooms_pos = self.rooms_pos
|
|
277
|
+
self.rooms_pos = temp_rooms_pos
|
|
278
|
+
self.rooms_pos = original_rooms_pos
|
|
279
|
+
except (ValueError, KeyError, TypeError):
|
|
280
|
+
if (
|
|
281
|
+
self.shared.image_auto_zoom
|
|
282
|
+
and self.shared.vacuum_state == "cleaning"
|
|
283
|
+
and robot_position
|
|
284
|
+
):
|
|
285
|
+
self.zooming = True
|
|
286
|
+
|
|
200
287
|
async def _setup_robot_and_image(
|
|
201
288
|
self, m_json, size_x, size_y, colors, destinations
|
|
202
289
|
):
|
|
@@ -208,100 +295,17 @@ class ReImageHandler(BaseHandler, AutoCrop):
|
|
|
208
295
|
) = await self.imd.async_get_robot_position(m_json)
|
|
209
296
|
|
|
210
297
|
if self.frame_number == 0:
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
size_y,
|
|
221
|
-
colors["wall"],
|
|
222
|
-
colors["zone_clean"],
|
|
223
|
-
colors["background"],
|
|
224
|
-
DEFAULT_PIXEL_SIZE,
|
|
225
|
-
)
|
|
226
|
-
LOGGER.info("%s: Completed base Layers", self.file_name)
|
|
227
|
-
|
|
228
|
-
if room_id > 0 and not self.room_propriety:
|
|
229
|
-
self.room_propriety = await self.get_rooms_attributes(destinations)
|
|
298
|
+
await self._initialize_base_layer(
|
|
299
|
+
m_json,
|
|
300
|
+
size_x,
|
|
301
|
+
size_y,
|
|
302
|
+
colors,
|
|
303
|
+
destinations,
|
|
304
|
+
robot_position,
|
|
305
|
+
robot_position_angle,
|
|
306
|
+
)
|
|
230
307
|
|
|
231
|
-
|
|
232
|
-
if not self.rooms_pos and not self.room_propriety:
|
|
233
|
-
self.room_propriety = await self.get_rooms_attributes(destinations)
|
|
234
|
-
|
|
235
|
-
# Always check robot position for zooming (update if room info is missing)
|
|
236
|
-
if (
|
|
237
|
-
self.rooms_pos
|
|
238
|
-
and robot_position
|
|
239
|
-
and (self.robot_pos is None or "in_room" not in self.robot_pos)
|
|
240
|
-
):
|
|
241
|
-
self.robot_pos = await self.async_get_robot_in_room(
|
|
242
|
-
(robot_position[0] * 10),
|
|
243
|
-
(robot_position[1] * 10),
|
|
244
|
-
robot_position_angle,
|
|
245
|
-
)
|
|
246
|
-
# Delete old base layer before creating new one to free memory
|
|
247
|
-
if self.img_base_layer is not None:
|
|
248
|
-
del self.img_base_layer
|
|
249
|
-
self.img_base_layer = await self.async_copy_array(img_np_array)
|
|
250
|
-
# Delete source array after copying to free memory
|
|
251
|
-
del img_np_array
|
|
252
|
-
else:
|
|
253
|
-
# If floor is disabled, create an empty image
|
|
254
|
-
background_color = self.drawing_config.get_property(
|
|
255
|
-
DrawableElement.FLOOR, "color", colors["background"]
|
|
256
|
-
)
|
|
257
|
-
img_np_array = await self.draw.create_empty_image(
|
|
258
|
-
size_x, size_y, background_color
|
|
259
|
-
)
|
|
260
|
-
# Delete old base layer before creating new one to free memory
|
|
261
|
-
if self.img_base_layer is not None:
|
|
262
|
-
del self.img_base_layer
|
|
263
|
-
self.img_base_layer = await self.async_copy_array(img_np_array)
|
|
264
|
-
# Delete source array after copying to free memory
|
|
265
|
-
del img_np_array
|
|
266
|
-
|
|
267
|
-
# Check active zones BEFORE auto-crop to enable proper zoom functionality
|
|
268
|
-
# This needs to run on every frame, not just frame 0
|
|
269
|
-
if (
|
|
270
|
-
self.shared.image_auto_zoom
|
|
271
|
-
and self.shared.vacuum_state == "cleaning"
|
|
272
|
-
and robot_position
|
|
273
|
-
and destinations # Check if we have destinations data for room extraction
|
|
274
|
-
):
|
|
275
|
-
# Extract room data early if we have destinations
|
|
276
|
-
try:
|
|
277
|
-
temp_room_properties = (
|
|
278
|
-
await self.rooms_handler.async_extract_room_properties(
|
|
279
|
-
m_json, destinations
|
|
280
|
-
)
|
|
281
|
-
)
|
|
282
|
-
if temp_room_properties:
|
|
283
|
-
# Create temporary rooms_pos for robot room detection
|
|
284
|
-
temp_rooms_pos = []
|
|
285
|
-
for room_id, room_data in temp_room_properties.items():
|
|
286
|
-
temp_rooms_pos.append(
|
|
287
|
-
{"name": room_data["name"], "outline": room_data["outline"]}
|
|
288
|
-
)
|
|
289
|
-
|
|
290
|
-
# Store original rooms_pos and temporarily use the new one
|
|
291
|
-
original_rooms_pos = self.rooms_pos
|
|
292
|
-
self.rooms_pos = temp_rooms_pos
|
|
293
|
-
|
|
294
|
-
# Restore original rooms_pos
|
|
295
|
-
self.rooms_pos = original_rooms_pos
|
|
296
|
-
|
|
297
|
-
except (ValueError, KeyError, TypeError):
|
|
298
|
-
# Fallback to robot-position-based zoom if room extraction fails
|
|
299
|
-
if (
|
|
300
|
-
self.shared.image_auto_zoom
|
|
301
|
-
and self.shared.vacuum_state == "cleaning"
|
|
302
|
-
and robot_position
|
|
303
|
-
):
|
|
304
|
-
self.zooming = True
|
|
308
|
+
await self._check_zoom_conditions(m_json, robot_position, destinations)
|
|
305
309
|
|
|
306
310
|
return self.img_base_layer, robot_position, robot_position_angle
|
|
307
311
|
|
|
@@ -403,139 +407,124 @@ class ReImageHandler(BaseHandler, AutoCrop):
|
|
|
403
407
|
)
|
|
404
408
|
return self.room_propriety
|
|
405
409
|
|
|
410
|
+
def _create_robot_position_dict(
|
|
411
|
+
self, robot_x: int, robot_y: int, angle: float, room_name: str
|
|
412
|
+
) -> RobotPosition:
|
|
413
|
+
"""Create a robot position dictionary."""
|
|
414
|
+
return {
|
|
415
|
+
"x": robot_x,
|
|
416
|
+
"y": robot_y,
|
|
417
|
+
"angle": angle,
|
|
418
|
+
"in_room": room_name,
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
def _set_zooming_from_active_zones(self) -> None:
|
|
422
|
+
"""Set zooming based on active zones."""
|
|
423
|
+
self.active_zones = self.shared.rand256_active_zone
|
|
424
|
+
self.zooming = False
|
|
425
|
+
if self.active_zones and (
|
|
426
|
+
self.robot_in_room["id"] in range(len(self.active_zones))
|
|
427
|
+
):
|
|
428
|
+
self.zooming = bool(self.active_zones[self.robot_in_room["id"]])
|
|
429
|
+
|
|
430
|
+
def _check_cached_room_outline_rand(
|
|
431
|
+
self, robot_x: int, robot_y: int, angle: float
|
|
432
|
+
) -> RobotPosition | None:
|
|
433
|
+
"""Check if robot is still in cached room using outline."""
|
|
434
|
+
if "outline" in self.robot_in_room:
|
|
435
|
+
outline = self.robot_in_room["outline"]
|
|
436
|
+
if point_in_polygon(int(robot_x), int(robot_y), outline):
|
|
437
|
+
self._set_zooming_from_active_zones()
|
|
438
|
+
LOGGER.debug(
|
|
439
|
+
"%s: Robot is in %s room (polygon detection). %s",
|
|
440
|
+
self.file_name,
|
|
441
|
+
self.robot_in_room["room"],
|
|
442
|
+
self.active_zones,
|
|
443
|
+
)
|
|
444
|
+
return self._create_robot_position_dict(
|
|
445
|
+
robot_x, robot_y, angle, self.robot_in_room["room"]
|
|
446
|
+
)
|
|
447
|
+
return None
|
|
448
|
+
|
|
449
|
+
def _check_cached_room_bbox_rand(
|
|
450
|
+
self, robot_x: int, robot_y: int, angle: float
|
|
451
|
+
) -> RobotPosition | None:
|
|
452
|
+
"""Check if robot is still in cached room using bounding box."""
|
|
453
|
+
if all(k in self.robot_in_room for k in ["left", "right", "up", "down"]):
|
|
454
|
+
if (
|
|
455
|
+
self.robot_in_room["right"]
|
|
456
|
+
<= int(robot_x)
|
|
457
|
+
<= self.robot_in_room["left"]
|
|
458
|
+
) and (
|
|
459
|
+
self.robot_in_room["up"] <= int(robot_y) <= self.robot_in_room["down"]
|
|
460
|
+
):
|
|
461
|
+
self._set_zooming_from_active_zones()
|
|
462
|
+
return self._create_robot_position_dict(
|
|
463
|
+
robot_x, robot_y, angle, self.robot_in_room["room"]
|
|
464
|
+
)
|
|
465
|
+
return None
|
|
466
|
+
|
|
467
|
+
def _check_room_with_outline_rand(
|
|
468
|
+
self, room: dict, room_count: int, robot_x: int, robot_y: int, angle: float
|
|
469
|
+
) -> RobotPosition | None:
|
|
470
|
+
"""Check if robot is in room using outline polygon."""
|
|
471
|
+
outline = room["outline"]
|
|
472
|
+
if point_in_polygon(int(robot_x), int(robot_y), outline):
|
|
473
|
+
self.robot_in_room = {
|
|
474
|
+
"id": room_count,
|
|
475
|
+
"room": str(room["name"]),
|
|
476
|
+
"outline": outline,
|
|
477
|
+
}
|
|
478
|
+
self._set_zooming_from_active_zones()
|
|
479
|
+
return self._create_robot_position_dict(
|
|
480
|
+
robot_x, robot_y, angle, self.robot_in_room["room"]
|
|
481
|
+
)
|
|
482
|
+
return None
|
|
483
|
+
|
|
406
484
|
async def async_get_robot_in_room(
|
|
407
485
|
self, robot_x: int, robot_y: int, angle: float
|
|
408
486
|
) -> RobotPosition:
|
|
409
487
|
"""Get the robot position and return in what room is."""
|
|
410
|
-
#
|
|
411
|
-
if self.robot_in_room:
|
|
412
|
-
# If we have outline data, use point_in_polygon for accurate detection
|
|
413
|
-
if "outline" in self.robot_in_room:
|
|
414
|
-
outline = self.robot_in_room["outline"]
|
|
415
|
-
if point_in_polygon(int(robot_x), int(robot_y), outline):
|
|
416
|
-
temp = {
|
|
417
|
-
"x": robot_x,
|
|
418
|
-
"y": robot_y,
|
|
419
|
-
"angle": angle,
|
|
420
|
-
"in_room": self.robot_in_room["room"],
|
|
421
|
-
}
|
|
422
|
-
# Handle active zones
|
|
423
|
-
self.active_zones = self.shared.rand256_active_zone
|
|
424
|
-
LOGGER.debug(
|
|
425
|
-
"%s: Robot is in %s room (polygon detection). %s",
|
|
426
|
-
self.file_name,
|
|
427
|
-
self.robot_in_room["room"],
|
|
428
|
-
self.active_zones,
|
|
429
|
-
)
|
|
430
|
-
self.zooming = False
|
|
431
|
-
if self.active_zones and (
|
|
432
|
-
self.robot_in_room["id"] in range(len(self.active_zones))
|
|
433
|
-
):
|
|
434
|
-
self.zooming = bool(self.active_zones[self.robot_in_room["id"]])
|
|
435
|
-
else:
|
|
436
|
-
self.zooming = False
|
|
437
|
-
return temp
|
|
438
|
-
# Fallback to bounding box check if no outline data
|
|
439
|
-
elif all(k in self.robot_in_room for k in ["left", "right", "up", "down"]):
|
|
440
|
-
if (
|
|
441
|
-
self.robot_in_room["right"]
|
|
442
|
-
<= int(robot_x)
|
|
443
|
-
<= self.robot_in_room["left"]
|
|
444
|
-
) and (
|
|
445
|
-
self.robot_in_room["up"]
|
|
446
|
-
<= int(robot_y)
|
|
447
|
-
<= self.robot_in_room["down"]
|
|
448
|
-
):
|
|
449
|
-
temp = {
|
|
450
|
-
"x": robot_x,
|
|
451
|
-
"y": robot_y,
|
|
452
|
-
"angle": angle,
|
|
453
|
-
"in_room": self.robot_in_room["room"],
|
|
454
|
-
}
|
|
455
|
-
# Handle active zones
|
|
456
|
-
self.active_zones = self.shared.rand256_active_zone
|
|
457
|
-
self.zooming = False
|
|
458
|
-
if self.active_zones and (
|
|
459
|
-
self.robot_in_room["id"] in range(len(self.active_zones))
|
|
460
|
-
):
|
|
461
|
-
self.zooming = bool(self.active_zones[self.robot_in_room["id"]])
|
|
462
|
-
else:
|
|
463
|
-
self.zooming = False
|
|
464
|
-
return temp
|
|
465
|
-
|
|
466
|
-
# If we don't have a cached room or the robot is not in it, search all rooms
|
|
467
|
-
last_room = None
|
|
468
|
-
room_count = 0
|
|
488
|
+
# Check cached room first
|
|
469
489
|
if self.robot_in_room:
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
if not self.rooms_pos:
|
|
490
|
+
result = self._check_cached_room_outline_rand(robot_x, robot_y, angle)
|
|
491
|
+
if result:
|
|
492
|
+
return result
|
|
493
|
+
result = self._check_cached_room_bbox_rand(robot_x, robot_y, angle)
|
|
494
|
+
if result:
|
|
495
|
+
return result
|
|
496
|
+
|
|
497
|
+
# Prepare for room search
|
|
498
|
+
last_room = self.robot_in_room
|
|
499
|
+
map_boundary = 50000
|
|
500
|
+
|
|
501
|
+
# Check boundary conditions or missing room data
|
|
502
|
+
if (
|
|
503
|
+
abs(robot_x) > map_boundary
|
|
504
|
+
or abs(robot_y) > map_boundary
|
|
505
|
+
or not self.rooms_pos
|
|
506
|
+
):
|
|
488
507
|
self.robot_in_room = last_room
|
|
489
508
|
self.zooming = False
|
|
490
|
-
|
|
491
|
-
"
|
|
492
|
-
|
|
493
|
-
"angle": angle,
|
|
494
|
-
"in_room": last_room["room"] if last_room else "unknown",
|
|
495
|
-
}
|
|
496
|
-
return temp
|
|
509
|
+
return self._create_robot_position_dict(
|
|
510
|
+
robot_x, robot_y, angle, last_room["room"] if last_room else "unknown"
|
|
511
|
+
)
|
|
497
512
|
|
|
498
|
-
|
|
499
|
-
|
|
513
|
+
# Search through all rooms
|
|
514
|
+
for room_count, room in enumerate(self.rooms_pos):
|
|
500
515
|
if "outline" in room:
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
"id": room_count,
|
|
507
|
-
"room": str(room["name"]),
|
|
508
|
-
"outline": outline,
|
|
509
|
-
}
|
|
510
|
-
temp = {
|
|
511
|
-
"x": robot_x,
|
|
512
|
-
"y": robot_y,
|
|
513
|
-
"angle": angle,
|
|
514
|
-
"in_room": self.robot_in_room["room"],
|
|
515
|
-
}
|
|
516
|
-
|
|
517
|
-
# Handle active zones - Set zooming based on active zones
|
|
518
|
-
self.active_zones = self.shared.rand256_active_zone
|
|
519
|
-
if self.active_zones and (
|
|
520
|
-
self.robot_in_room["id"] in range(len(self.active_zones))
|
|
521
|
-
):
|
|
522
|
-
self.zooming = bool(self.active_zones[self.robot_in_room["id"]])
|
|
523
|
-
else:
|
|
524
|
-
self.zooming = False
|
|
525
|
-
|
|
526
|
-
return temp
|
|
527
|
-
room_count += 1
|
|
516
|
+
result = self._check_room_with_outline_rand(
|
|
517
|
+
room, room_count, robot_x, robot_y, angle
|
|
518
|
+
)
|
|
519
|
+
if result:
|
|
520
|
+
return result
|
|
528
521
|
|
|
529
522
|
# Robot not found in any room
|
|
530
523
|
self.robot_in_room = last_room
|
|
531
524
|
self.zooming = False
|
|
532
|
-
|
|
533
|
-
"
|
|
534
|
-
|
|
535
|
-
"angle": angle,
|
|
536
|
-
"in_room": last_room["room"] if last_room else "unknown",
|
|
537
|
-
}
|
|
538
|
-
return temp
|
|
525
|
+
return self._create_robot_position_dict(
|
|
526
|
+
robot_x, robot_y, angle, last_room["room"] if last_room else "unknown"
|
|
527
|
+
)
|
|
539
528
|
|
|
540
529
|
def get_calibration_data(self, rotation_angle: int = 0) -> Any:
|
|
541
530
|
"""Return the map calibration data."""
|
|
@@ -11,7 +11,7 @@ from typing import Any, Dict, List, Optional, Tuple
|
|
|
11
11
|
|
|
12
12
|
import numpy as np
|
|
13
13
|
from scipy.ndimage import binary_dilation, binary_erosion
|
|
14
|
-
from scipy.spatial import ConvexHull
|
|
14
|
+
from scipy.spatial import ConvexHull # pylint: disable=no-name-in-module
|
|
15
15
|
|
|
16
16
|
from .config.drawable_elements import DrawableElement, DrawingConfig
|
|
17
17
|
from .config.types import LOGGER, RoomsProperties
|
|
@@ -83,7 +83,7 @@ class RoomsHandler:
|
|
|
83
83
|
"""
|
|
84
84
|
meta_data = layer.get("metaData", {})
|
|
85
85
|
segment_id = meta_data.get("segmentId")
|
|
86
|
-
name = meta_data.get("name", "Room {}"
|
|
86
|
+
name = meta_data.get("name", f"Room {segment_id}")
|
|
87
87
|
compressed_pixels = layer.get("compressedPixels", [])
|
|
88
88
|
pixels = self.sublist(compressed_pixels, 3)
|
|
89
89
|
|
|
@@ -296,8 +296,8 @@ class RandRoomsHandler:
|
|
|
296
296
|
|
|
297
297
|
return hull_points
|
|
298
298
|
|
|
299
|
-
except
|
|
300
|
-
LOGGER.warning(
|
|
299
|
+
except (ValueError, RuntimeError) as e:
|
|
300
|
+
LOGGER.warning("Error calculating convex hull: %s", e)
|
|
301
301
|
|
|
302
302
|
# Fallback to bounding box if convex hull fails
|
|
303
303
|
x_min, y_min = np.min(points_array, axis=0)
|
|
@@ -342,7 +342,6 @@ class RandRoomsHandler:
|
|
|
342
342
|
except (ValueError, TypeError):
|
|
343
343
|
# If segment_id is not a valid integer, we can't map it to a room element
|
|
344
344
|
# In this case, we'll include the room (fail open)
|
|
345
|
-
pass
|
|
346
345
|
LOGGER.debug(
|
|
347
346
|
"Could not convert segment_id %s to room element", segment_id
|
|
348
347
|
)
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
valetudo_map_parser/__init__.py,sha256=hyQGLItlggmWjeUCey8pDm5EthPtRd8NBu7A3z5NJ-o,4297
|
|
2
|
+
valetudo_map_parser/config/__init__.py,sha256=DQ9plV3ZF_K25Dp5ZQHPDoG-40dQoJNdNi-dfNeR3Zc,48
|
|
3
|
+
valetudo_map_parser/config/async_utils.py,sha256=j1QnPvNQ3IkAeHRqDmbfibhminztWUvf5CW_d44P0mE,3215
|
|
4
|
+
valetudo_map_parser/config/colors.py,sha256=XDjLRbbp9wbIB_9keRZ8x1KJVdmq724x1IpLFhIP9Jc,13589
|
|
5
|
+
valetudo_map_parser/config/drawable.py,sha256=WbXvpHj713mQtuT3ZUS53sZip83j9jP9AtiGo31QUaI,21510
|
|
6
|
+
valetudo_map_parser/config/drawable_elements.py,sha256=_iHdAuzbAoIOeT8JEZrvSu5fVojIdhAyH5ABUVi-x3Y,11496
|
|
7
|
+
valetudo_map_parser/config/fonts/FiraSans.ttf,sha256=Pavz1Iv0WZ-Vz_2S-Z6kJqAU1TEfUqXrXsOvJl6XzZc,440984
|
|
8
|
+
valetudo_map_parser/config/fonts/Inter-VF.ttf,sha256=zzy0OwNm4txt9g4RMrHJpMFXd_DNjlpT4MFRJAA-ntQ,804612
|
|
9
|
+
valetudo_map_parser/config/fonts/Lato-Regular.ttf,sha256=6CVCrtgpP0n8g8Sq6lZrH2tPx6mrXaEeb7m8CXO1Mks,75152
|
|
10
|
+
valetudo_map_parser/config/fonts/MPLUSRegular.ttf,sha256=IGdcNSRP4dDxQskbE3Ybuwz7T0flhCBuzwfhLMcPt9s,3380812
|
|
11
|
+
valetudo_map_parser/config/fonts/NotoKufiArabic-VF.ttf,sha256=NaIy40eLx7d3ts0kuenp0GjWd-YN24J6DpSvX2L3vLA,433800
|
|
12
|
+
valetudo_map_parser/config/fonts/NotoSansCJKhk-VF.ttf,sha256=xIXXLKCJzmWoPEg8HdvxeRgotMjjxF6l6ugGP-IWRJU,36135040
|
|
13
|
+
valetudo_map_parser/config/fonts/NotoSansKhojki.ttf,sha256=XJWzSmpN-Ql6jTfTvFojP_JkCHOztQvixQc1_7hPWrc,107388
|
|
14
|
+
valetudo_map_parser/config/optimized_element_map.py,sha256=52BCnkvVv9bre52LeVIfT8nhnEIpc0TuWTv1xcNu0Rk,15744
|
|
15
|
+
valetudo_map_parser/config/rand256_parser.py,sha256=u9JmYa3_ZJXhHV_vPNRLcR1myGHW132oMwhNkb633t8,21099
|
|
16
|
+
valetudo_map_parser/config/shared.py,sha256=6r0s0jOuz1LBjgMVicI17IE6wA8pEnNQl3jdFHS-_lM,12542
|
|
17
|
+
valetudo_map_parser/config/status_text/__init__.py,sha256=iG45LWQ5HCkQOT56eG_S4Eii_DAnQB-CqhYc66eN-BU,164
|
|
18
|
+
valetudo_map_parser/config/status_text/status_text.py,sha256=2ZGTPWL4Dc9TVAE8dVrPkqAgFSVoa7BD55DdewzEO_Q,4920
|
|
19
|
+
valetudo_map_parser/config/status_text/translations.py,sha256=mmPbJkl_2A59w49wnesQf3ocXqwZxBsrqNX-yt5FSCQ,9132
|
|
20
|
+
valetudo_map_parser/config/types.py,sha256=BSHCVXYXCDS6WkKXeJgmFJ2aXppgABqZKAc9-DgkwOU,10158
|
|
21
|
+
valetudo_map_parser/config/utils.py,sha256=_SKSJZQC4uE5UlHrfKfaKUwsk2nSe_fI6zSbOooL2tY,36381
|
|
22
|
+
valetudo_map_parser/const.py,sha256=-0jl5ZLMgjgU6sHmPkWJE2pYgj_z0LbWE91hQ-aW5Sk,7798
|
|
23
|
+
valetudo_map_parser/hypfer_draw.py,sha256=ngt4p46XbfhciDQpeB1sShXrrjyJpeKMf0McnIsqfY0,20755
|
|
24
|
+
valetudo_map_parser/hypfer_handler.py,sha256=EdOuXnq6ZSJMtWEM2R6CbGuXyPZW-QmFTItlXLuHR8k,18979
|
|
25
|
+
valetudo_map_parser/map_data.py,sha256=MrQ1uSFz6g9trn_NHsLu1INxvaE6NOXhpdeYM-U4p0c,28393
|
|
26
|
+
valetudo_map_parser/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
27
|
+
valetudo_map_parser/rand256_handler.py,sha256=ayq8MLMo59_sQuXKakhlyQd98ww2GudVTBLrdS-uWYo,21270
|
|
28
|
+
valetudo_map_parser/reimg_draw.py,sha256=Pwm_QUHiJd4o657qr-mlsWQ_TtGCBB-ucsA84t-IwOg,12474
|
|
29
|
+
valetudo_map_parser/rooms_handler.py,sha256=8xd2W5Q_Na3ei9vozm_V-NANOYuytYJBGDHRhb8OSZw,17390
|
|
30
|
+
valetudo_map_parser-0.1.12b0.dist-info/METADATA,sha256=IGtbKi15q5nncHNOx71CT-SKGu2wMkuDtb7JkiBaSYQ,3403
|
|
31
|
+
valetudo_map_parser-0.1.12b0.dist-info/WHEEL,sha256=zp0Cn7JsFoX2ATtOhtaFYIiE2rmFAD4OcMhtUki8W3U,88
|
|
32
|
+
valetudo_map_parser-0.1.12b0.dist-info/licenses/LICENSE,sha256=Lh-qBbuRV0-jiCIBhfV7NgdwFxQFOXH3BKOzK865hRs,10480
|
|
33
|
+
valetudo_map_parser-0.1.12b0.dist-info/licenses/NOTICE.txt,sha256=5lTOuWiU9aiEnJ2go8sc7lTJ7ntMBx0g0GFnNrswCY4,2533
|
|
34
|
+
valetudo_map_parser-0.1.12b0.dist-info/RECORD,,
|
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
valetudo_map_parser/__init__.py,sha256=l_O2iyvj49KkUtuW7lMIZJcEaV_6_-YFaVZkiVeSh9g,1743
|
|
2
|
-
valetudo_map_parser/config/__init__.py,sha256=DQ9plV3ZF_K25Dp5ZQHPDoG-40dQoJNdNi-dfNeR3Zc,48
|
|
3
|
-
valetudo_map_parser/config/async_utils.py,sha256=e1j9uTtg4dhPVWvB2_XgqaH4aeSjRAPz-puRMbGoOs8,3204
|
|
4
|
-
valetudo_map_parser/config/colors.py,sha256=DMY5aHDS-alW2CZ2j8U7QVGHK_H8M0fBDX2OGuryirc,29914
|
|
5
|
-
valetudo_map_parser/config/drawable.py,sha256=s0bA3yeIXgultFbDD_BXDbzDPMpkGVHzq5IyXnH_sW8,23984
|
|
6
|
-
valetudo_map_parser/config/drawable_elements.py,sha256=_iHdAuzbAoIOeT8JEZrvSu5fVojIdhAyH5ABUVi-x3Y,11496
|
|
7
|
-
valetudo_map_parser/config/fonts/FiraSans.ttf,sha256=Pavz1Iv0WZ-Vz_2S-Z6kJqAU1TEfUqXrXsOvJl6XzZc,440984
|
|
8
|
-
valetudo_map_parser/config/fonts/Inter-VF.ttf,sha256=zzy0OwNm4txt9g4RMrHJpMFXd_DNjlpT4MFRJAA-ntQ,804612
|
|
9
|
-
valetudo_map_parser/config/fonts/Lato-Regular.ttf,sha256=6CVCrtgpP0n8g8Sq6lZrH2tPx6mrXaEeb7m8CXO1Mks,75152
|
|
10
|
-
valetudo_map_parser/config/fonts/MPLUSRegular.ttf,sha256=IGdcNSRP4dDxQskbE3Ybuwz7T0flhCBuzwfhLMcPt9s,3380812
|
|
11
|
-
valetudo_map_parser/config/fonts/NotoKufiArabic-VF.ttf,sha256=NaIy40eLx7d3ts0kuenp0GjWd-YN24J6DpSvX2L3vLA,433800
|
|
12
|
-
valetudo_map_parser/config/fonts/NotoSansCJKhk-VF.ttf,sha256=xIXXLKCJzmWoPEg8HdvxeRgotMjjxF6l6ugGP-IWRJU,36135040
|
|
13
|
-
valetudo_map_parser/config/fonts/NotoSansKhojki.ttf,sha256=XJWzSmpN-Ql6jTfTvFojP_JkCHOztQvixQc1_7hPWrc,107388
|
|
14
|
-
valetudo_map_parser/config/optimized_element_map.py,sha256=52BCnkvVv9bre52LeVIfT8nhnEIpc0TuWTv1xcNu0Rk,15744
|
|
15
|
-
valetudo_map_parser/config/rand256_parser.py,sha256=UZ0UlcNIjDhMpImA_2jSei0HeLftpb9fLDwzliJJpz8,21161
|
|
16
|
-
valetudo_map_parser/config/shared.py,sha256=PyP3IpgrztOM9B-qjNDHKcQL1_No_rAbPhvfuQJXOBE,11829
|
|
17
|
-
valetudo_map_parser/config/status_text/status_text.py,sha256=29E8b3adl_Rr_BH8-J35ia2cOS716sPzVk_cezFiWQ4,4053
|
|
18
|
-
valetudo_map_parser/config/status_text/translations.py,sha256=mmPbJkl_2A59w49wnesQf3ocXqwZxBsrqNX-yt5FSCQ,9132
|
|
19
|
-
valetudo_map_parser/config/types.py,sha256=rYdqOsUX9dtre8M7s8o1S5Ag8Ixvab13Stpk3Hfw_54,18027
|
|
20
|
-
valetudo_map_parser/config/utils.py,sha256=IP64VqYW_oWGAxSXexGHtLGaHTn7r4eICd0JGZDqG9A,35696
|
|
21
|
-
valetudo_map_parser/hypfer_draw.py,sha256=0-ZBCZw9H7G5Mu2cukTdOfbu83tZPL2cTdzPjRXzZsQ,22422
|
|
22
|
-
valetudo_map_parser/hypfer_handler.py,sha256=O2eR4nNbmEkcDc-5EcWCKHLMOQGeQBMAdpClEM1fGnI,20446
|
|
23
|
-
valetudo_map_parser/map_data.py,sha256=1-kxE82o8BfaJojYrD0LXoUAgCNpD6d50yLGc4w7ZWc,27433
|
|
24
|
-
valetudo_map_parser/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
25
|
-
valetudo_map_parser/rand256_handler.py,sha256=z7ofWheIy7UvC120rvhP1nNjWdW9JqCIqnGV3T5OoNs,23048
|
|
26
|
-
valetudo_map_parser/reimg_draw.py,sha256=Pwm_QUHiJd4o657qr-mlsWQ_TtGCBB-ucsA84t-IwOg,12474
|
|
27
|
-
valetudo_map_parser/rooms_handler.py,sha256=ZbSdxG-uwoskYBbzN5zzAqK_lTtrNrcpjZmCVmxFWpw,17364
|
|
28
|
-
valetudo_map_parser-0.1.11b1.dist-info/METADATA,sha256=YyvgIGxYawa9mD6hJ0wWOoChSED2xO3Dh8W4VJmrS2I,3403
|
|
29
|
-
valetudo_map_parser-0.1.11b1.dist-info/WHEEL,sha256=zp0Cn7JsFoX2ATtOhtaFYIiE2rmFAD4OcMhtUki8W3U,88
|
|
30
|
-
valetudo_map_parser-0.1.11b1.dist-info/licenses/LICENSE,sha256=Lh-qBbuRV0-jiCIBhfV7NgdwFxQFOXH3BKOzK865hRs,10480
|
|
31
|
-
valetudo_map_parser-0.1.11b1.dist-info/licenses/NOTICE.txt,sha256=5lTOuWiU9aiEnJ2go8sc7lTJ7ntMBx0g0GFnNrswCY4,2533
|
|
32
|
-
valetudo_map_parser-0.1.11b1.dist-info/RECORD,,
|
|
File without changes
|
{valetudo_map_parser-0.1.11b1.dist-info → valetudo_map_parser-0.1.12b0.dist-info}/licenses/LICENSE
RENAMED
|
File without changes
|
|
File without changes
|