1919 LAYER_BACKGROUND ,
2020 LAYER_FLOOR ,
2121 LAYER_WALL ,
22- GridCalibration ,
2322 GridLayers ,
2423 decompose_grid ,
2524)
3231# the raster -- room ids/names live in the protobuf metadata, not the pixels).
3332_Q7_WALL_VALUE = 127
3433_Q7_FLOOR_VALUE = 128
34+ _Q7_RENDER_INTENSITY = {
35+ LAYER_BACKGROUND : 0 ,
36+ LAYER_WALL : 180 ,
37+ LAYER_FLOOR : 255 ,
38+ }
3539
3640
3741def classify_q7_cell (value : int ) -> str :
@@ -43,39 +47,6 @@ def classify_q7_cell(value: int) -> str:
4347 return LAYER_BACKGROUND # 0 = outside / unknown
4448
4549
46- def decompose_q7_layers (payload : bytes ) -> GridLayers :
47- """Split an inflated Q7 SCMap into background / wall / floor layers.
48-
49- Q7 has no per-room raster, so ``GridLayers.rooms`` is empty; room ids/names
50- are available separately via the map metadata. Reuses the same device-agnostic
51- decomposition as the Q10.
52- """
53- parsed = _parse_scmap_payload (payload )
54- size_x , size_y , grid = _extract_grid (parsed )
55- return decompose_grid (size_x , size_y , grid , [], classify_q7_cell )
56-
57-
58- def q7_calibration (payload : bytes ) -> GridCalibration | None :
59- """Build a world<->pixel calibration straight from the Q7 ``mapHead``.
60-
61- Unlike the Q10 (whose packet carries no calibration), the Q7 SCMap header
62- provides ``minX``/``minY``/``resolution`` directly, so no path fitting is
63- needed. World coordinates are in metres; resolution is metres-per-pixel.
64- """
65- head = _parse_scmap_payload (payload ).mapHead
66- if not head .HasField ("resolution" ) or head .resolution <= 0 or not head .HasField ("sizeY" ):
67- return None
68- resolution = head .resolution
69- min_x = head .minX if head .HasField ("minX" ) else 0.0
70- min_y = head .minY if head .HasField ("minY" ) else 0.0
71- return GridCalibration (
72- resolution = resolution ,
73- origin_x = - min_x / resolution ,
74- origin_y = (head .sizeY - 1 ) + min_y / resolution ,
75- y_sign = 1 ,
76- )
77-
78-
7950@dataclass
8051class B01MapParserConfig :
8152 """Configuration for the B01/Q7 map parser."""
@@ -95,8 +66,9 @@ def parse(self, payload: bytes) -> ParsedMapData:
9566 parsed = _parse_scmap_payload (payload )
9667 size_x , size_y , grid = _extract_grid (parsed )
9768 room_names = _extract_room_names (parsed )
69+ layers = decompose_grid (size_x , size_y , grid , [], classify_q7_cell )
9870
99- image = _render_occupancy_image (grid , size_x = size_x , size_y = size_y , scale = self ._config .map_scale )
71+ image = _render_occupancy_image (layers , scale = self ._config .map_scale )
10072
10173 map_data = MapData ()
10274 map_data .image = ImageData (
@@ -158,23 +130,15 @@ def _extract_room_names(parsed: RobotMap) -> dict[int, str]:
158130 return room_names
159131
160132
161- def _render_occupancy_image (grid : bytes , * , size_x : int , size_y : int , scale : int ) -> Image .Image :
162- """Render the B01 occupancy grid into a simple image."""
163-
164- # The observed occupancy grid contains only:
165- # - 0: outside/unknown
166- # - 127: wall/obstacle
167- # - 128: floor/free
168- table = bytearray (range (256 ))
169- table [0 ] = 0
170- table [127 ] = 180
171- table [128 ] = 255
172-
173- mapped = grid .translate (bytes (table ))
174- img = Image .frombytes ("L" , (size_x , size_y ), mapped )
175- img = img .transpose (Image .Transpose .FLIP_TOP_BOTTOM ).convert ("RGB" )
133+ def _render_occupancy_image (layers : GridLayers , * , scale : int ) -> Image .Image :
134+ """Render canonical Q7 grid classes into the composed map image."""
135+ mapped = bytes (_Q7_RENDER_INTENSITY [layers .cell_class (value )] for value in layers .grid )
136+ img = Image .frombytes ("L" , (layers .width , layers .height ), mapped )
137+ if layers .flip :
138+ img = img .transpose (Image .Transpose .FLIP_TOP_BOTTOM )
139+ img = img .convert ("RGB" )
176140
177141 if scale > 1 :
178- img = img .resize ((size_x * scale , size_y * scale ), resample = Image .Resampling .NEAREST )
142+ img = img .resize ((layers . width * scale , layers . height * scale ), resample = Image .Resampling .NEAREST )
179143
180144 return img
0 commit comments