valetudo-map-parser 0.1.9b55__py3-none-any.whl → 0.1.9b57__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 +6 -2
- valetudo_map_parser/config/auto_crop.py +150 -20
- valetudo_map_parser/config/shared.py +47 -1
- valetudo_map_parser/config/types.py +2 -1
- valetudo_map_parser/config/utils.py +91 -2
- valetudo_map_parser/hypfer_draw.py +104 -49
- valetudo_map_parser/hypfer_handler.py +69 -19
- valetudo_map_parser/map_data.py +26 -2
- valetudo_map_parser/{rand25_handler.py → rand256_handler.py} +301 -100
- valetudo_map_parser/rooms_handler.py +6 -2
- {valetudo_map_parser-0.1.9b55.dist-info → valetudo_map_parser-0.1.9b57.dist-info}/METADATA +1 -1
- valetudo_map_parser-0.1.9b57.dist-info/RECORD +26 -0
- valetudo_map_parser/config/room_outline.py +0 -148
- valetudo_map_parser-0.1.9b55.dist-info/RECORD +0 -27
- {valetudo_map_parser-0.1.9b55.dist-info → valetudo_map_parser-0.1.9b57.dist-info}/LICENSE +0 -0
- {valetudo_map_parser-0.1.9b55.dist-info → valetudo_map_parser-0.1.9b57.dist-info}/NOTICE.txt +0 -0
- {valetudo_map_parser-0.1.9b55.dist-info → valetudo_map_parser-0.1.9b57.dist-info}/WHEEL +0 -0
@@ -2,7 +2,7 @@
|
|
2
2
|
Image Handler Module for Valetudo Re Vacuums.
|
3
3
|
It returns the PIL PNG image frame relative to the Map Data extrapolated from the vacuum json.
|
4
4
|
It also returns calibration, rooms data to the card and other images information to the camera.
|
5
|
-
Version: 0.1.9.
|
5
|
+
Version: 0.1.9.a6
|
6
6
|
"""
|
7
7
|
|
8
8
|
from __future__ import annotations
|
@@ -26,12 +26,13 @@ from .config.types import (
|
|
26
26
|
RobotPosition,
|
27
27
|
RoomsProperties,
|
28
28
|
RoomStore,
|
29
|
+
WebPBytes,
|
29
30
|
)
|
30
31
|
from .config.utils import (
|
31
32
|
BaseHandler,
|
32
|
-
# async_extract_room_outline,
|
33
33
|
initialize_drawing_config,
|
34
34
|
manage_drawable_elements,
|
35
|
+
numpy_to_webp_bytes,
|
35
36
|
prepare_resize_params,
|
36
37
|
)
|
37
38
|
from .map_data import RandImageData
|
@@ -69,39 +70,15 @@ class ReImageHandler(BaseHandler, AutoCrop):
|
|
69
70
|
self.active_zones = None # Active zones
|
70
71
|
self.file_name = self.shared.file_name # File name
|
71
72
|
self.imd = ImageDraw(self) # Image Draw
|
72
|
-
self.rooms_handler = RandRoomsHandler(
|
73
|
-
|
74
|
-
|
75
|
-
"""Extract the outline of a room using the pixel data and element map.
|
76
|
-
|
77
|
-
Args:
|
78
|
-
room_id_int: The room ID as an integer
|
79
|
-
pixels: List of pixel coordinates in the format [[x, y, z], ...]
|
80
|
-
|
81
|
-
Returns:
|
82
|
-
List of points forming the outline of the room
|
83
|
-
"""
|
84
|
-
# Calculate x and y min/max from compressed pixels for rectangular fallback
|
85
|
-
x_values = []
|
86
|
-
y_values = []
|
87
|
-
for x, y, _ in pixels:
|
88
|
-
x_values.append(x)
|
89
|
-
y_values.append(y)
|
90
|
-
|
91
|
-
if not x_values or not y_values:
|
92
|
-
return []
|
93
|
-
|
94
|
-
min_x, max_x = min(x_values), max(x_values)
|
95
|
-
min_y, max_y = min(y_values), max(y_values)
|
96
|
-
|
97
|
-
# Always return a rectangular outline since element_map is removed
|
98
|
-
return [(min_x, min_y), (max_x, min_y), (max_x, max_y), (min_x, max_y)]
|
73
|
+
self.rooms_handler = RandRoomsHandler(
|
74
|
+
self.file_name, self.drawing_config
|
75
|
+
) # Room data handler
|
99
76
|
|
100
77
|
async def extract_room_properties(
|
101
78
|
self, json_data: JsonType, destinations: JsonType
|
102
79
|
) -> RoomsProperties:
|
103
80
|
"""Extract the room properties."""
|
104
|
-
unsorted_id = RandImageData.get_rrm_segments_ids(json_data)
|
81
|
+
# unsorted_id = RandImageData.get_rrm_segments_ids(json_data)
|
105
82
|
size_x, size_y = RandImageData.get_rrm_image_size(json_data)
|
106
83
|
top, left = RandImageData.get_rrm_image_position(json_data)
|
107
84
|
try:
|
@@ -124,11 +101,17 @@ class ReImageHandler(BaseHandler, AutoCrop):
|
|
124
101
|
|
125
102
|
# Update self.rooms_pos from room_properties for compatibility with other methods
|
126
103
|
self.rooms_pos = []
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
"
|
131
|
-
|
104
|
+
room_ids = [] # Collect room IDs for shared.map_rooms
|
105
|
+
for room_id, room_data in room_properties.items():
|
106
|
+
self.rooms_pos.append(
|
107
|
+
{"name": room_data["name"], "outline": room_data["outline"]}
|
108
|
+
)
|
109
|
+
# Store the room number (segment ID) for MQTT active zone mapping
|
110
|
+
room_ids.append(room_data["number"])
|
111
|
+
|
112
|
+
# Update shared.map_rooms with the room IDs for MQTT active zone mapping
|
113
|
+
self.shared.map_rooms = room_ids
|
114
|
+
_LOGGER.debug("Updated shared.map_rooms with room IDs: %s", room_ids)
|
132
115
|
|
133
116
|
# get the zones and points data
|
134
117
|
zone_properties = await self.async_zone_propriety(zones_data)
|
@@ -144,9 +127,7 @@ class ReImageHandler(BaseHandler, AutoCrop):
|
|
144
127
|
_LOGGER.debug("Extracted data: %s", extracted_data)
|
145
128
|
else:
|
146
129
|
self.rooms_pos = None
|
147
|
-
_LOGGER.debug(
|
148
|
-
"%s: Rooms and Zones data not available!", self.file_name
|
149
|
-
)
|
130
|
+
_LOGGER.debug("%s: Rooms and Zones data not available!", self.file_name)
|
150
131
|
|
151
132
|
rooms = RoomStore(self.file_name, room_properties)
|
152
133
|
_LOGGER.debug("Rooms Data: %s", rooms.get_rooms())
|
@@ -163,8 +144,14 @@ class ReImageHandler(BaseHandler, AutoCrop):
|
|
163
144
|
self,
|
164
145
|
m_json: JsonType, # json data
|
165
146
|
destinations: None = None, # MQTT destinations for labels
|
166
|
-
|
167
|
-
|
147
|
+
return_webp: bool = False,
|
148
|
+
) -> WebPBytes | Image.Image | None:
|
149
|
+
"""Generate Images from the json data.
|
150
|
+
@param m_json: The JSON data to use to draw the image.
|
151
|
+
@param destinations: MQTT destinations for labels (unused).
|
152
|
+
@param return_webp: If True, return WebP bytes; if False, return PIL Image (default).
|
153
|
+
@return WebPBytes | Image.Image: WebP bytes or PIL Image depending on return_webp parameter.
|
154
|
+
"""
|
168
155
|
colors: Colors = {
|
169
156
|
name: self.shared.user_colors[idx] for idx, name in enumerate(COLORS)
|
170
157
|
}
|
@@ -201,11 +188,21 @@ class ReImageHandler(BaseHandler, AutoCrop):
|
|
201
188
|
img_np_array, m_json, colors, robot_position, robot_position_angle
|
202
189
|
)
|
203
190
|
|
204
|
-
#
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
191
|
+
# Return WebP bytes or PIL Image based on parameter
|
192
|
+
if return_webp:
|
193
|
+
# Convert directly to WebP bytes for better performance
|
194
|
+
webp_bytes = await numpy_to_webp_bytes(
|
195
|
+
img_np_array,
|
196
|
+
quality=90, # High quality for vacuum maps
|
197
|
+
lossless=False # Use lossy compression for smaller size
|
198
|
+
)
|
199
|
+
del img_np_array # free memory
|
200
|
+
return webp_bytes
|
201
|
+
else:
|
202
|
+
# Convert to PIL Image (original behavior)
|
203
|
+
pil_img = Image.fromarray(img_np_array, mode="RGBA")
|
204
|
+
del img_np_array # free memory
|
205
|
+
return await self._finalize_image(pil_img)
|
209
206
|
|
210
207
|
except (RuntimeError, RuntimeWarning) as e:
|
211
208
|
_LOGGER.warning(
|
@@ -254,12 +251,18 @@ class ReImageHandler(BaseHandler, AutoCrop):
|
|
254
251
|
|
255
252
|
if room_id > 0 and not self.room_propriety:
|
256
253
|
self.room_propriety = await self.get_rooms_attributes(destinations)
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
254
|
+
|
255
|
+
# Ensure room data is available for robot room detection (even if not extracted above)
|
256
|
+
if not self.rooms_pos and not self.room_propriety:
|
257
|
+
self.room_propriety = await self.get_rooms_attributes(destinations)
|
258
|
+
|
259
|
+
# Always check robot position for zooming (fallback)
|
260
|
+
if self.rooms_pos and robot_position and not hasattr(self, "robot_pos"):
|
261
|
+
self.robot_pos = await self.async_get_robot_in_room(
|
262
|
+
(robot_position[0] * 10),
|
263
|
+
(robot_position[1] * 10),
|
264
|
+
robot_position_angle,
|
265
|
+
)
|
263
266
|
self.img_base_layer = await self.async_copy_array(img_np_array)
|
264
267
|
else:
|
265
268
|
# If floor is disabled, create an empty image
|
@@ -270,6 +273,60 @@ class ReImageHandler(BaseHandler, AutoCrop):
|
|
270
273
|
size_x, size_y, background_color
|
271
274
|
)
|
272
275
|
self.img_base_layer = await self.async_copy_array(img_np_array)
|
276
|
+
|
277
|
+
# Check active zones BEFORE auto-crop to enable proper zoom functionality
|
278
|
+
# This needs to run on every frame, not just frame 0
|
279
|
+
if (
|
280
|
+
self.shared.image_auto_zoom
|
281
|
+
and self.shared.vacuum_state == "cleaning"
|
282
|
+
and robot_position
|
283
|
+
and destinations # Check if we have destinations data for room extraction
|
284
|
+
):
|
285
|
+
# Extract room data early if we have destinations
|
286
|
+
try:
|
287
|
+
temp_room_properties = (
|
288
|
+
await self.rooms_handler.async_extract_room_properties(
|
289
|
+
m_json, destinations
|
290
|
+
)
|
291
|
+
)
|
292
|
+
if temp_room_properties:
|
293
|
+
# Create temporary rooms_pos for robot room detection
|
294
|
+
temp_rooms_pos = []
|
295
|
+
for room_id, room_data in temp_room_properties.items():
|
296
|
+
temp_rooms_pos.append(
|
297
|
+
{"name": room_data["name"], "outline": room_data["outline"]}
|
298
|
+
)
|
299
|
+
|
300
|
+
# Store original rooms_pos and temporarily use the new one
|
301
|
+
original_rooms_pos = self.rooms_pos
|
302
|
+
self.rooms_pos = temp_rooms_pos
|
303
|
+
|
304
|
+
# Perform robot room detection to check active zones
|
305
|
+
robot_room_result = await self.async_get_robot_in_room(
|
306
|
+
robot_position[0], robot_position[1], robot_position_angle
|
307
|
+
)
|
308
|
+
|
309
|
+
# Restore original rooms_pos
|
310
|
+
self.rooms_pos = original_rooms_pos
|
311
|
+
|
312
|
+
except Exception as e:
|
313
|
+
_LOGGER.debug(
|
314
|
+
"%s: Early room extraction failed: %s, falling back to robot-position zoom",
|
315
|
+
self.file_name,
|
316
|
+
e,
|
317
|
+
)
|
318
|
+
# Fallback to robot-position-based zoom if room extraction fails
|
319
|
+
if (
|
320
|
+
self.shared.image_auto_zoom
|
321
|
+
and self.shared.vacuum_state == "cleaning"
|
322
|
+
and robot_position
|
323
|
+
):
|
324
|
+
self.zooming = True
|
325
|
+
_LOGGER.debug(
|
326
|
+
"%s: Enabling fallback robot-position-based zoom",
|
327
|
+
self.file_name,
|
328
|
+
)
|
329
|
+
|
273
330
|
return self.img_base_layer, robot_position, robot_position_angle
|
274
331
|
|
275
332
|
async def _draw_map_elements(
|
@@ -316,6 +373,33 @@ class ReImageHandler(BaseHandler, AutoCrop):
|
|
316
373
|
img_np_array, robot_position, robot_position_angle, robot_color
|
317
374
|
)
|
318
375
|
|
376
|
+
# Store robot position for potential zoom function use
|
377
|
+
if robot_position:
|
378
|
+
self.robot_position = robot_position
|
379
|
+
|
380
|
+
# Check if Zoom should be enabled based on active zones
|
381
|
+
if (
|
382
|
+
self.shared.image_auto_zoom
|
383
|
+
and self.shared.vacuum_state == "cleaning"
|
384
|
+
and robot_position
|
385
|
+
):
|
386
|
+
# For Rand256, we need to check active zones differently since room data is not available yet
|
387
|
+
# Use a simplified approach: enable zoom if any active zones are set
|
388
|
+
active_zones = self.shared.rand256_active_zone
|
389
|
+
if active_zones and any(zone for zone in active_zones):
|
390
|
+
self.zooming = True
|
391
|
+
_LOGGER.debug(
|
392
|
+
"%s: Enabling zoom for Rand256 - active zones detected: %s",
|
393
|
+
self.file_name,
|
394
|
+
active_zones,
|
395
|
+
)
|
396
|
+
else:
|
397
|
+
self.zooming = False
|
398
|
+
_LOGGER.debug(
|
399
|
+
"%s: Zoom disabled for Rand256 - no active zones set",
|
400
|
+
self.file_name,
|
401
|
+
)
|
402
|
+
|
319
403
|
img_np_array = await self.async_auto_trim_and_zoom_image(
|
320
404
|
img_np_array,
|
321
405
|
detect_colour=colors["background"],
|
@@ -353,79 +437,196 @@ class ReImageHandler(BaseHandler, AutoCrop):
|
|
353
437
|
_LOGGER.debug("Got Rooms Attributes.")
|
354
438
|
return self.room_propriety
|
355
439
|
|
440
|
+
@staticmethod
|
441
|
+
def point_in_polygon(x: int, y: int, polygon: list) -> bool:
|
442
|
+
"""
|
443
|
+
Check if a point is inside a polygon using ray casting algorithm.
|
444
|
+
Enhanced version with better handling of edge cases.
|
445
|
+
|
446
|
+
Args:
|
447
|
+
x: X coordinate of the point
|
448
|
+
y: Y coordinate of the point
|
449
|
+
polygon: List of (x, y) tuples forming the polygon
|
450
|
+
|
451
|
+
Returns:
|
452
|
+
True if the point is inside the polygon, False otherwise
|
453
|
+
"""
|
454
|
+
# Ensure we have a valid polygon with at least 3 points
|
455
|
+
if len(polygon) < 3:
|
456
|
+
return False
|
457
|
+
|
458
|
+
# Make sure the polygon is closed (last point equals first point)
|
459
|
+
if polygon[0] != polygon[-1]:
|
460
|
+
polygon = polygon + [polygon[0]]
|
461
|
+
|
462
|
+
# Use winding number algorithm for better accuracy
|
463
|
+
wn = 0 # Winding number counter
|
464
|
+
|
465
|
+
# Loop through all edges of the polygon
|
466
|
+
for i in range(len(polygon) - 1): # Last vertex is first vertex
|
467
|
+
p1x, p1y = polygon[i]
|
468
|
+
p2x, p2y = polygon[i + 1]
|
469
|
+
|
470
|
+
# Test if a point is left/right/on the edge defined by two vertices
|
471
|
+
if p1y <= y: # Start y <= P.y
|
472
|
+
if p2y > y: # End y > P.y (upward crossing)
|
473
|
+
# Point left of edge
|
474
|
+
if ((p2x - p1x) * (y - p1y) - (x - p1x) * (p2y - p1y)) > 0:
|
475
|
+
wn += 1 # Valid up intersect
|
476
|
+
else: # Start y > P.y
|
477
|
+
if p2y <= y: # End y <= P.y (downward crossing)
|
478
|
+
# Point right of edge
|
479
|
+
if ((p2x - p1x) * (y - p1y) - (x - p1x) * (p2y - p1y)) < 0:
|
480
|
+
wn -= 1 # Valid down intersect
|
481
|
+
|
482
|
+
# If winding number is not 0, the point is inside the polygon
|
483
|
+
return wn != 0
|
484
|
+
|
356
485
|
async def async_get_robot_in_room(
|
357
486
|
self, robot_x: int, robot_y: int, angle: float
|
358
487
|
) -> RobotPosition:
|
359
488
|
"""Get the robot position and return in what room is."""
|
489
|
+
# First check if we already have a cached room and if the robot is still in it
|
490
|
+
if self.robot_in_room:
|
491
|
+
# If we have outline data, use point_in_polygon for accurate detection
|
492
|
+
if "outline" in self.robot_in_room:
|
493
|
+
outline = self.robot_in_room["outline"]
|
494
|
+
if self.point_in_polygon(int(robot_x), int(robot_y), outline):
|
495
|
+
temp = {
|
496
|
+
"x": robot_x,
|
497
|
+
"y": robot_y,
|
498
|
+
"angle": angle,
|
499
|
+
"in_room": self.robot_in_room["room"],
|
500
|
+
}
|
501
|
+
# Handle active zones
|
502
|
+
self.active_zones = self.shared.rand256_active_zone
|
503
|
+
self.zooming = False
|
504
|
+
if self.active_zones and (
|
505
|
+
self.robot_in_room["id"] in range(len(self.active_zones))
|
506
|
+
):
|
507
|
+
self.zooming = bool(self.active_zones[self.robot_in_room["id"]])
|
508
|
+
else:
|
509
|
+
self.zooming = False
|
510
|
+
return temp
|
511
|
+
# Fallback to bounding box check if no outline data
|
512
|
+
elif all(k in self.robot_in_room for k in ["left", "right", "up", "down"]):
|
513
|
+
if (
|
514
|
+
self.robot_in_room["right"]
|
515
|
+
<= int(robot_x)
|
516
|
+
<= self.robot_in_room["left"]
|
517
|
+
) and (
|
518
|
+
self.robot_in_room["up"]
|
519
|
+
<= int(robot_y)
|
520
|
+
<= self.robot_in_room["down"]
|
521
|
+
):
|
522
|
+
temp = {
|
523
|
+
"x": robot_x,
|
524
|
+
"y": robot_y,
|
525
|
+
"angle": angle,
|
526
|
+
"in_room": self.robot_in_room["room"],
|
527
|
+
}
|
528
|
+
# Handle active zones
|
529
|
+
self.active_zones = self.shared.rand256_active_zone
|
530
|
+
self.zooming = False
|
531
|
+
if self.active_zones and (
|
532
|
+
self.robot_in_room["id"] in range(len(self.active_zones))
|
533
|
+
):
|
534
|
+
self.zooming = bool(self.active_zones[self.robot_in_room["id"]])
|
535
|
+
else:
|
536
|
+
self.zooming = False
|
537
|
+
return temp
|
538
|
+
|
539
|
+
# If we don't have a cached room or the robot is not in it, search all rooms
|
540
|
+
last_room = None
|
541
|
+
room_count = 0
|
542
|
+
if self.robot_in_room:
|
543
|
+
last_room = self.robot_in_room
|
360
544
|
|
361
|
-
|
362
|
-
|
363
|
-
|
364
|
-
|
365
|
-
|
545
|
+
# Check if the robot is far outside the normal map boundaries
|
546
|
+
# This helps prevent false positives for points very far from any room
|
547
|
+
map_boundary = 50000 # Typical map size is around 25000-30000 units for Rand25
|
548
|
+
if abs(robot_x) > map_boundary or abs(robot_y) > map_boundary:
|
549
|
+
_LOGGER.debug(
|
550
|
+
"%s robot position (%s, %s) is far outside map boundaries.",
|
551
|
+
self.file_name,
|
552
|
+
robot_x,
|
553
|
+
robot_y,
|
366
554
|
)
|
367
|
-
|
368
|
-
|
369
|
-
if self.robot_in_room and _check_robot_position(robot_x, robot_y):
|
555
|
+
self.robot_in_room = last_room
|
556
|
+
self.zooming = False
|
370
557
|
temp = {
|
371
558
|
"x": robot_x,
|
372
559
|
"y": robot_y,
|
373
560
|
"angle": angle,
|
374
|
-
"in_room":
|
561
|
+
"in_room": last_room["room"] if last_room else "unknown",
|
375
562
|
}
|
376
|
-
self.active_zones = self.shared.rand256_active_zone
|
377
|
-
self.zooming = False
|
378
|
-
if self.active_zones and (
|
379
|
-
(self.robot_in_room["id"]) in range(len(self.active_zones))
|
380
|
-
): # issue #100 Index out of range
|
381
|
-
self.zooming = bool(self.active_zones[self.robot_in_room["id"]])
|
382
563
|
return temp
|
383
|
-
# else we need to search and use the async method
|
384
|
-
_LOGGER.debug("%s Changed room.. searching..", self.file_name)
|
385
|
-
room_count = -1
|
386
|
-
last_room = None
|
387
564
|
|
388
|
-
#
|
565
|
+
# Search through all rooms to find which one contains the robot
|
389
566
|
if not self.rooms_pos:
|
390
|
-
_LOGGER.debug(
|
391
|
-
|
567
|
+
_LOGGER.debug(
|
568
|
+
"%s: No rooms data available for robot position detection.",
|
569
|
+
self.file_name,
|
570
|
+
)
|
571
|
+
self.robot_in_room = last_room
|
572
|
+
self.zooming = False
|
573
|
+
temp = {
|
574
|
+
"x": robot_x,
|
575
|
+
"y": robot_y,
|
576
|
+
"angle": angle,
|
577
|
+
"in_room": last_room["room"] if last_room else "unknown",
|
578
|
+
}
|
579
|
+
return temp
|
392
580
|
|
393
|
-
|
394
|
-
if self.robot_in_room:
|
395
|
-
last_room = self.robot_in_room
|
581
|
+
_LOGGER.debug("%s: Searching for robot in rooms...", self.file_name)
|
396
582
|
for room in self.rooms_pos:
|
397
|
-
|
583
|
+
# Check if the room has an outline (polygon points)
|
584
|
+
if "outline" in room:
|
585
|
+
outline = room["outline"]
|
586
|
+
# Use point_in_polygon for accurate detection with complex shapes
|
587
|
+
if self.point_in_polygon(int(robot_x), int(robot_y), outline):
|
588
|
+
# Robot is in this room
|
589
|
+
self.robot_in_room = {
|
590
|
+
"id": room_count,
|
591
|
+
"room": str(room["name"]),
|
592
|
+
"outline": outline,
|
593
|
+
}
|
594
|
+
temp = {
|
595
|
+
"x": robot_x,
|
596
|
+
"y": robot_y,
|
597
|
+
"angle": angle,
|
598
|
+
"in_room": self.robot_in_room["room"],
|
599
|
+
}
|
600
|
+
|
601
|
+
# Handle active zones - Set zooming based on active zones
|
602
|
+
self.active_zones = self.shared.rand256_active_zone
|
603
|
+
if self.active_zones and (
|
604
|
+
self.robot_in_room["id"] in range(len(self.active_zones))
|
605
|
+
):
|
606
|
+
self.zooming = bool(self.active_zones[self.robot_in_room["id"]])
|
607
|
+
else:
|
608
|
+
self.zooming = False
|
609
|
+
|
610
|
+
_LOGGER.debug(
|
611
|
+
"%s is in %s room (polygon detection).",
|
612
|
+
self.file_name,
|
613
|
+
self.robot_in_room["room"],
|
614
|
+
)
|
615
|
+
return temp
|
398
616
|
room_count += 1
|
399
|
-
|
400
|
-
|
401
|
-
"left": corners[0][0],
|
402
|
-
"right": corners[2][0],
|
403
|
-
"up": corners[0][1],
|
404
|
-
"down": corners[2][1],
|
405
|
-
"room": room["name"],
|
406
|
-
}
|
407
|
-
# Check if the robot coordinates are inside the room's corners
|
408
|
-
if _check_robot_position(robot_x, robot_y):
|
409
|
-
temp = {
|
410
|
-
"x": robot_x,
|
411
|
-
"y": robot_y,
|
412
|
-
"angle": angle,
|
413
|
-
"in_room": self.robot_in_room["room"],
|
414
|
-
}
|
415
|
-
_LOGGER.debug("%s is in %s", self.file_name, self.robot_in_room["room"])
|
416
|
-
del room, corners, robot_x, robot_y # free memory.
|
417
|
-
return temp
|
418
|
-
# After checking all rooms and not finding a match
|
617
|
+
|
618
|
+
# Robot not found in any room
|
419
619
|
_LOGGER.debug(
|
420
|
-
"%s
|
620
|
+
"%s not located within any room coordinates.",
|
621
|
+
self.file_name,
|
421
622
|
)
|
422
|
-
self.zooming = False
|
423
623
|
self.robot_in_room = last_room
|
624
|
+
self.zooming = False
|
424
625
|
temp = {
|
425
626
|
"x": robot_x,
|
426
627
|
"y": robot_y,
|
427
628
|
"angle": angle,
|
428
|
-
"in_room":
|
629
|
+
"in_room": last_room["room"] if last_room else "unknown",
|
429
630
|
}
|
430
631
|
return temp
|
431
632
|
|
@@ -19,6 +19,7 @@ from .config.types import LOGGER, RoomsProperties
|
|
19
19
|
|
20
20
|
from .map_data import RandImageData, ImageData
|
21
21
|
|
22
|
+
|
22
23
|
class RoomsHandler:
|
23
24
|
"""
|
24
25
|
Handler for extracting and managing room data from Hipfer vacuum maps.
|
@@ -225,6 +226,7 @@ class RoomsHandler:
|
|
225
226
|
LOGGER.debug("Room extraction Total time: %.3fs", total_time)
|
226
227
|
return room_properties
|
227
228
|
|
229
|
+
|
228
230
|
class RandRoomsHandler:
|
229
231
|
"""
|
230
232
|
Handler for extracting and managing room data from Rand25 vacuum maps.
|
@@ -247,7 +249,9 @@ class RandRoomsHandler:
|
|
247
249
|
"""
|
248
250
|
self.vacuum_id = vacuum_id
|
249
251
|
self.drawing_config = drawing_config
|
250
|
-
self.current_json_data =
|
252
|
+
self.current_json_data = (
|
253
|
+
None # Will store the current JSON data being processed
|
254
|
+
)
|
251
255
|
self.segment_data = None # Segment data
|
252
256
|
self.outlines = None # Outlines data
|
253
257
|
|
@@ -467,4 +471,4 @@ class RandRoomsHandler:
|
|
467
471
|
total_time = time.time() - start_total
|
468
472
|
LOGGER.debug("Room extraction Total time: %.3fs", total_time)
|
469
473
|
|
470
|
-
return room_properties
|
474
|
+
return room_properties
|
@@ -0,0 +1,26 @@
|
|
1
|
+
valetudo_map_parser/__init__.py,sha256=XO_eJwFDyU7hXJ4tAa2zY-n-SM2_kmIGMWDKY3GcauY,1163
|
2
|
+
valetudo_map_parser/config/__init__.py,sha256=DQ9plV3ZF_K25Dp5ZQHPDoG-40dQoJNdNi-dfNeR3Zc,48
|
3
|
+
valetudo_map_parser/config/auto_crop.py,sha256=1TGjUSbVHV15_sx1iFsEBWwD5BnWHPjgGIuPAJB6aiY,19142
|
4
|
+
valetudo_map_parser/config/color_utils.py,sha256=nXD6WeNmdFdoMxPDW-JFpjnxJSaZR1jX-ouNfrx6zvE,4502
|
5
|
+
valetudo_map_parser/config/colors.py,sha256=DG-oPQoN5gsnwDbEsuFr8a0hRCxmbFHObWa4_5pr-70,29910
|
6
|
+
valetudo_map_parser/config/drawable.py,sha256=2MeVHXqZuVuJk3eerMJYGwo25rVetHx3xB_vxecEFOQ,34168
|
7
|
+
valetudo_map_parser/config/drawable_elements.py,sha256=o-5oiXmfqPwNQLzKIhkEcZD_A47rIU9E0CqKgWipxgc,11516
|
8
|
+
valetudo_map_parser/config/enhanced_drawable.py,sha256=QlGxlUMVgECUXPtFwIslyjubWxQuhIixsRymWV3lEvk,12586
|
9
|
+
valetudo_map_parser/config/optimized_element_map.py,sha256=52BCnkvVv9bre52LeVIfT8nhnEIpc0TuWTv1xcNu0Rk,15744
|
10
|
+
valetudo_map_parser/config/rand25_parser.py,sha256=kIayyqVZBfQfAMkiArzqrrj9vqZB3pkgT0Y5ufrQmGA,16448
|
11
|
+
valetudo_map_parser/config/shared.py,sha256=ogXR5qC2HuLJ3KgYc9KDozXzDQptd8nhvNc-CepN6S0,12301
|
12
|
+
valetudo_map_parser/config/types.py,sha256=HO5fowAjbGmS2rEOFbFe7eFljvpfBr0fsvhcVRTByhI,17540
|
13
|
+
valetudo_map_parser/config/utils.py,sha256=w8r53KcCgYNq7CoIziQ3ktJu8ESFit5TYza-7g8ndhE,31203
|
14
|
+
valetudo_map_parser/hypfer_draw.py,sha256=Bi03FiYdxw2Kp8BwkggAkdKABNoNf-j7v7J-rER8tnQ,28953
|
15
|
+
valetudo_map_parser/hypfer_handler.py,sha256=-tMYd1lMH6_l8ufQH1A95uAgbt2P-1YYTfNkl9NXAc8,22269
|
16
|
+
valetudo_map_parser/hypfer_rooms_handler.py,sha256=NkpOA6Gdq-2D3lLAxvtNuuWMvPXHxeMY2TO5RZLSHlU,22652
|
17
|
+
valetudo_map_parser/map_data.py,sha256=5DDT5ABJCMSaWd8YrMY9SG4uhD3Rga_F0DEBNNNPipc,18618
|
18
|
+
valetudo_map_parser/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
19
|
+
valetudo_map_parser/rand256_handler.py,sha256=kLurqSQvmrweCrOpLT9oIuVKkQ_SmCXcRuSL4dDddO8,27893
|
20
|
+
valetudo_map_parser/reimg_draw.py,sha256=1q8LkNTPHEA9Tsapc_JnVw51kpPYNhaBU-KmHkefCQY,12507
|
21
|
+
valetudo_map_parser/rooms_handler.py,sha256=ovqQtAjauAqwUNPR0aX27P2zhheQmqfaFhDE3_AwYWk,17821
|
22
|
+
valetudo_map_parser-0.1.9b57.dist-info/LICENSE,sha256=Lh-qBbuRV0-jiCIBhfV7NgdwFxQFOXH3BKOzK865hRs,10480
|
23
|
+
valetudo_map_parser-0.1.9b57.dist-info/METADATA,sha256=f2DJy0uFpMdGp1e0gsdG2OdpGzkB1A429ZKf2c49MOE,3321
|
24
|
+
valetudo_map_parser-0.1.9b57.dist-info/NOTICE.txt,sha256=5lTOuWiU9aiEnJ2go8sc7lTJ7ntMBx0g0GFnNrswCY4,2533
|
25
|
+
valetudo_map_parser-0.1.9b57.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
|
26
|
+
valetudo_map_parser-0.1.9b57.dist-info/RECORD,,
|