feat: decode Q7 (B01) map geometry — dock, robot pose, path and rooms - #911
feat: decode Q7 (B01) map geometry — dock, robot pose, path and rooms#911andig wants to merge 6 commits into
Conversation
There was a problem hiding this comment.
Pull request overview
Adds support for decoding and rendering additional Q7 (B01) SCMap geometry by extending the protobuf schema and projecting decoded poses/path/rooms into the shared V1 MapData + renderer pipeline.
Changes:
- Extended
b01_scmap.protowith additional Q7/B01 map fields (poses, path history, areas, room matrix/outline) and regenerated the checked-in*_pb2.py. - Updated
B01MapParserto project charger pose, robot pose, and cleaning path intoMapData, and to derive room bounding boxes fromroomOutline. - Added unit tests covering world→pixel projection, placeholder-pose rejection, and room-outline extraction.
Reviewed changes
Copilot reviewed 3 out of 4 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
tests/map/test_b01_map_parser.py |
Adds unit tests for pose/path projection, placeholder pose handling, and room-outline extraction. |
roborock/map/proto/b01_scmap.proto |
Extends the B01/Q7 SCMap proto2 schema with newly decoded messages/fields. |
roborock/map/proto/b01_scmap_pb2.py |
Updates checked-in protobuf gencode to match the extended schema. |
roborock/map/b01_map_parser.py |
Projects decoded charger/robot/path/rooms into MapData and renders overlays using the shared V1 image generator. |
Files not reviewed (1)
- roborock/map/proto/b01_scmap_pb2.py: Generated file
Suppressed comments (2)
roborock/map/proto/b01_scmap_pb2.py:32
- The generated module name passed to BuildTopDescriptorsAndMessages is now 'b01_scmap_pb2', but this file is imported as roborock.map.proto.b01_scmap_pb2. This mismatch changes the generated message classes’ module and can break pickling / dynamic imports and some protobuf reflection use cases. Regenerate with the correct module path (or update this line) so it matches the actual import path.
roborock/map/proto/b01_scmap_pb2.py:19 - The runtime version validation call embeds the proto filename ('b01_scmap.proto'), which no longer matches the proto path used elsewhere in the repo/regeneration instructions. Keeping it consistent with the checked-in proto path makes it easier to trace where this descriptor came from when debugging descriptor collisions.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Decode the previously unmapped SCMap RobotMap fields, established empirically from live MQTT captures of a Q7 Series (roborock.vacuum.sc05): - 5 mapInfo: saved-map list (id + name) - 6 historyPose: cleaning path points (meters) - 7 chargeStation: dock pose - 8 currentPose: live robot pose with path index and activity flag - 9 areaInfo: zone polygons - 13 roomMatrix, 14 roomOutline: room boundary pixel chains and room-to-room border chains The parser now projects dock, robot position (falling back to the dock on saved maps, which carry a (1100, 1100) placeholder pose), cleaning path and room bounding boxes + label positions into MapData, and renders the shared V1 glyphs (charger, vacuum, path) through the common image generator, same as the Q10 renderer. Also corrects the occupancy value comment: 127 is floor and 128 is wall (verified against the rendered floor plan). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
379a4ed to
e16bd49
Compare
The occupancy grid carries no room ids, so each room is flood-filled from its label position, bounded by walls and the roomOutline boundary chains. Room colors come from the shared adjacency-aware V1 palette and room names are drawn through the standard ROOM_NAMES drawable. A fill that escapes a gapped outline would flood the whole floor, so fills larger than half the floor area are discarded and those pixels keep the plain floor color. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Use the shared V1 palette roles, matching the Q10 renderer and the app look: transparent outside, GREY_WALL for walls and interior obstacles, MAP_INSIDE for floor not assigned to any room. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Project areaInfo zone polygons into pixel space and draw them through the shared no-go drawable. Per-kind type mapping (no-go vs no-mop) is left for when more zone samples are available. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Carpets arrive as RobotMap field 20 (id, type, four vertices in meters, enabled flag), confirmed live by adding a carpet in the app and diffing map frames. Enabled carpet rectangles are stippled into the raster with a checkerboard texture like the V1 carpet look, and exposed as the same flat top-down carpet_map contract the Q10 parser uses. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
Seems this repo isn‘t very friendly to contributions. Giving up. |
|
andig@ You can see recent contributions here: https://github.com/Python-roborock/python-roborock/pulls?q=is%3Apr+is%3Aclosed I'll admit directly: i personally didn't prioritize this as I don't have this device and there were a massive number of q10 incoming reviews (a device I own). I would say your PR is still welcome here, just haven't had a chance to review yet. |
|
Thanks. It has been tested against device and still works on my Q7. |
|
OK thanks for understanding the review delay. There are currently some lint errors that need to be resolved on CI. Please have a look and mark ready for review. |
Confidence: high Scope-risk: narrow
|
Sorry, hadn't seen those- fixed. |
Summary
Decodes the previously unmapped SCMap
RobotMapprotobuf fields for Q7 (B01) devices and renders dock, robot position and cleaning path with the shared V1 glyphs — the top open item ("Map") of #739, and the Q7 side of #827.Field semantics were established empirically by diffing live MQTT captures from a Q7 Series (
roborock.vacuum.sc05, fw 03.01.80) while docked, cleaning and returning to dock:mapInfo(repeated)historyPosechargeStationcurrentPoseareaInfo(repeated)roomMatrixroomOutline(repeated)Changes
b01_scmap.protowith the messages above and regenerateb01_scmap_pb2.py(protoc gencode 6.31.1, matching the checked-in file).B01MapParserprojects intoMapData:chargerfromchargeStation;vacuum_positionfromcurrentPose— saved maps carry a(1100.0, 1100.0)placeholder pose, so out-of-map-bounds poses are rejected and the robot falls back to its dock;pathfromhistoryPose;rooms(bounding box + label position + name) fromroomOutline+roomDataInfo.ImageGenerator(same approach as the Q10 renderer); raster converted to RGBA for glyph compositing.127is floor,128is wall (verified against the rendered floor plan and pixel histogram: ~28k floor px ≈ 70 m² home vs ~2.6k wall px).Validation
test_web_api::test_url_cyclingfails on a clean checkout too);ruff check/formatclean.sc05: saved map renders dock + docked robot in the correct rooms; during a clean the robot marker and path track the actual movement.Companion PR (independent): live map pushes — the same capture showed Q7 devices stream these frames unsolicited during cleaning.
🤖 Generated with Claude Code