A Python utility that converts Sweet Home 3D (.sh3d) models into the map configuration YAML required by ESPresense Companion.
This script extracts floor plan geometry and specific "node" locations from your 3D model, handles coordinate system transformations, and simplifies complex polygon shapes for cleaner maps.
- Coordinate Normalization: Automatically translates your home's layout so the bottom-left corner is
(0,0), converts units from centimeters to meters, and flips the Y-axis to match ESPresense's coordinate system. - Geometry Simplification: Uses the Ramer-Douglas-Peucker algorithm to smooth out "noisy" room perimeters (e.g., complex door jambs or wall recesses), resulting in cleaner YAML.
- 3D Bounding Boxes: Calculates accurate 3D bounds for each floor based on room coordinates and floor elevation/height.
- Node Extraction: Automatically finds furniture named
node: [name], calculates their absolute 3D position, and generates the required node configuration. - Formatted Output: Produces human-readable YAML with inline coordinate lists (e.g.,
[x, y]) and section headers.
This script bridges the difference between Sweet Home 3D's file data and ESPresense's mapping coordinates.
Sweet Home 3D stores coordinates in centimeters, often with an arbitrary origin point (like the center of the drawing area) and a Y-axis that points downwards. ESPresence requests coordinates in meters, with 0, 0, 0 being at the bottom left corner of the plan. To achieve this translation cleanly, this script:
- Scans the entire model to find the absolute "bottom-left" limits of your plan's footprint.
- Normalizes the Origin: Shifts every point so that the bottom-left corner of your house becomes exactly
(0,0). - Flips the Y-Axis: Reverses the vertical axis so that coordinates increase as you move "North" or "Up" the plan (matching standard Cartesian maps).
- Scales Units: Converts all measurements from centimeters to meters.
- Python 3.x
- PyYAML
- Clone the repository:
git clone https://github.com/sirkus7/sh3d2espres.git
cd sh3d2espres
- Install dependencies:
pip install pyyaml
- Make the script executable :
chmod +x sh3d2espres.py
Overview:
- Create your Sweet Home 3D floor layout and place nodes within the plan (see tips below). Save the file.
- From the command line, run
sh3d2espres.py, using your saved file as input. - Copy the output of the script, and paste it into the ESPresence
config.yamlfile, replacing only the section of the config file that contains the coordinates for the map and nodes.
python3 sh3d2espres.py [INPUT_FILE] [OPTIONS]
Arguments:
input: Path to your Sweet Home 3D file (.sh3d). Required-o,--output: The filename for the generated YAML. (Default:espresense_map.yaml)-e,--epsilon: The simplification threshold in meters. Higher values = simpler shapes. Lower values = more detail. Set to0to turn off all simplification. (Default:0.15, 15cm)
1. Standard Conversion Uses default settings. Simplifies walls closer than 15cm (removes most door frames).
python3 sh3d2espres.py ./my_home.sh3d
2. Custom Output File
python3 sh3d2espres.py ./my_home.sh3d -o /config/espresense/map.yaml
3. Aggressive Simplification If your map looks too jagged or has too many points, increase the epsilon (e.g., to 30cm).
python3 sh3d2espres.py ./my_home.sh3d -e 0.30
4. No Simplification Get the exact geometry from Sweet Home 3D (including every vertex).
python3 sh3d2espres.py ./my_home.sh3d -e 0
The generated YAML will look like this:
# === FLOORS ===
floors:
# Floor: First Floor
- id: floor_1
name: floor_1
bounds: [[0.0, 0.0, 0.0], [15.2, 12.5, 2.5]]
rooms:
- name: Kitchen
points:
- [5.5, 2.1]
- [8.2, 2.1]
- [8.2, 5.5]
- [5.5, 5.5]
# === NODES ===
nodes:
- name: living_room
point: [4.5, 6.2, 0.8]
floors: [floor_1, Second_Floor]
- name: bedroom_1
point: [2.1, 8.5, 3.2]
floors: [floor_2, floor_1]By default, the output of the script is saved in a file called espresense_map.yaml, which now contains the correctly formatted coordinates for the map and nodes to place in the the ESPresence config.yaml file.
NOTE: The espresense_map.yaml file does NOT include everything that needs to be in the ESPresence config.yaml file, so DO NOT OVERWRITE the full YAML file with the contents of your new espresense_map.yaml file.
Copy the contents of espresense_map.yaml, find the section of the ESPresence config.yaml file where the map coordinates and node coordinates are, and paste your new coordinates, overwriting the old coordinates for the map and nodes.
Below are a few tips for using Sweet Home 3D to reach a clean ESPresence map using sh3d2espres.py.
The script marks out the "room" definitions in your plan, not walls. With that in mind, I recommend the following:
- Use thin walls (e.g. .05m) when laying out your floorplan. This is completely optional, but I find this makes it easier for your rooms to cover the floorplan area with less dead/unknown space in between rooms.
- Define your "rooms" with simple polygons that match the walls. I ended up preferring to mark my rooms manually with the room tool, rather than the auto-room feature (double clicking in the middle of walls.) While the auto feature is quick and handy, it traces all the details around any doors/windows. This can have a negative effect of singificanly increasing the number of points to represent a simple room, adding complexity to both editing the yaml and to rendering the rooms. The script's built-in simplification can often compensate for this, so in some cases this may not make a big difference. But in my case, it significantly complicated my map to use the auto-trace feature so I just added the rooms manually.
Name your floors (called "Levels" in Sweet Home 3D) exactly what you want them named in your ESPresence YAML file. To avoid potential issues, I name all my floors (as well as rooms and nodes) with no spaces. (e.g. first, second, basement or floor_1, floor_2)
You can place your ESPresence nodes directly in your Sweet Home 3D map.
- Add a small, simple "furniture" object to your map (I used the "cube", made it bright red, and .1 meter in size)
- Double click on it and set:
- Name: In the "Name" field, enter
node:followed by the actual name of the ESPresence node. (e.g.node: bedroom_1, ornode: family_room. Again, I recommend avoiding spaces in the names.) - Position "Elevation" value: This is critically important. While the X and Y position values are easily set by moving the object around your floor plan, ESPresence must have an accurate representation of the height (Z value) of the node. In Sweet Home 3D, this is set by double clicking on the object, finding the "Position" values, and setting the "Elevation" value (which is the Z value) in meters. This value will be directly represented in the translated ESPresence map coordinates.
- Name: In the "Name" field, enter
