sim.world_gen.in_house_2026_node#

Attributes#

Classes#

Material

SDF <material> colours, each RGBA in 0-1.

BorderConfig

Red outline drawn around the shape spawn area.

TagConfig

AprilTag decal stamped on each spawned shape.

SizeConfig

Per-instance X/Y scale drawn for each spawned shape. Thickness is never scaled.

InHouse2026Config

Schema for world.config in simulations/in_house_2026/*.yaml

InHouse2026WorldNode

World generation node for the In House 2026 challenge.

Functions#

main([args])

Module Contents#

RGBA#
XY#
XYR#
SHAPE_MODELS#
SHAPE_RADII#
SCALED_XY_PATHS = ('./model/link/pose', './model/link/visual/geometry/mesh/scale', './model/link/collision/pose',...#
MAX_PLACEMENT_ATTEMPTS = 200#
TAG_FAMILY = 'tag36h11'#
TAG_MODEL = 'AprilTag36h11'#
TAG_CELLS = 8#
TAG_QUIET_CELLS = 1#
TAG_Z = 0.012#
OBJECT_STATE_SERVICE = 'publish_object_state'#
NO_TAG_ID = -1#
class Material(/, **data: Any)#

Bases: pydantic.BaseModel

SDF <material> colours, each RGBA in 0-1.

ambient: RGBA#
diffuse: RGBA#
specular: RGBA = (0.01, 0.01, 0.01, 1.0)#
emissive: RGBA = (0.0, 0.0, 0.0, 1.0)#
DEFAULT_PALETTE#
BORDER_MODEL = 'InHouse2026Border'#
DEFAULT_BORDER_MATERIAL#
class BorderConfig(/, **data: Any)#

Bases: pydantic.BaseModel

Red outline drawn around the shape spawn area.

enabled: bool = True#
margin: float = 0.5#
thickness: float = 0.15#
height: float = 0.02#
material: Material#
class TagConfig(/, **data: Any)#

Bases: pydantic.BaseModel

AprilTag decal stamped on each spawned shape.

enabled: bool = True#
size: float = 0.0254#
id_range: tuple[int, int] = (10, 586)#
class SizeConfig(/, **data: Any)#

Bases: pydantic.BaseModel

Per-instance X/Y scale drawn for each spawned shape. Thickness is never scaled.

enabled: bool = True#
min_scale: float#
max_scale: float#
class InHouse2026Config(/, **data: Any)#

Bases: pydantic.BaseModel

Schema for world.config in simulations/in_house_2026/*.yaml

seed: int | None = None#
num_patches: int#
area: tuple[XY, XY]#
counts: dict[str, int]#
min_spacing: float = 0.05#
min_patch_spacing: float = 2.0#
keep_out: list[tuple[float, float, float]]#
random_yaw: bool = True#
palette: dict[str, Material]#
border: BorderConfig#
tags: TagConfig#
size: SizeConfig#
class InHouse2026WorldNode#

Bases: sim.world_gen.world_node.WorldNode

World generation node for the In House 2026 challenge. Litters the ground with randomly placed, randomly coloured InHouse2027 shapes.

config#
spherical_coordinates#
entities#
controllables#
shapes: list[sim.entity.Entity] = []#
object_states: list[dict] = []#
generated_at = ''#
object_state_srv#
cached_templates: dict[str, str]#
keep_out: list[tuple[float, float, float]]#
search_locations: list[sim_interfaces.msg.SearchLocation] = []#
target_tag_id: int = -1#
query_search_locations_service#
patches_ready = False#
generation_started = False#
pending_spawns = 0#
spawn_failed = False#
get_patches_callback(request: sim_interfaces.srv.GetSearchLocations.Request, response: sim_interfaces.srv.GetSearchLocations.Response) → sim_interfaces.srv.GetSearchLocations.Response#
sample_position(placed: list[XY]) → XY | None#

Rejection-sample an xy inside area honouring keep_out and min_spacing.

random_shapes() → list[sim.entity.Entity]#

Generate the shape entities described by the config.

build_border_sdf() → str#

Return an SDF model outlining area in red.

border_entity() → sim.entity.Entity#

Border entity whose on-disk model.sdf is replaced by geometry matching area.

generate_sdf_string(template_path: str, material: Material) → str#

Return the model.sdf at template_path with its <material> colours replaced.

available_tag_ids() → list[int]#

Tag ids committed under $PENNAIR_GZ_MODELS_PATH/models/AprilTag36h11.

with_apriltag(sdf: str, tag_id: int) → str#

Return sdf with a tag plane appended to the shape’s link.

Must run AFTER generate_sdf_string, whose recolour regex is global and would otherwise repaint the tag’s <ambient>/<diffuse> the shape’s colour.

with_scale(sdf: str, scale: float) → str#

Return sdf with the shape’s X/Y footprint multiplied by scale.

Z is deliberately untouched, so every shape stays 1 cm thick and TAG_Z / the collision <pose> z stay correct at any size. Must run BEFORE with_apriltag so the tag reads the zeroed link <pose> and lands on the visual centre, and so the tag’s own plane <size> is not scaled with the shape.

object_state_req(request, response)#

Serve the tag, colour and pose of every spawned shape so runs can be graded.

load_world_coordinates() → gz.math7.SphericalCoordinates#

Read the world’s geographic reference once when the node starts.

world_xy_to_gps(center_xy: XY) → tuple[float, float]#

Convert a ground point (world z=0) to latitude/longitude in degrees.

sample_patch_center(radius_m: float, placed: list[XY]) → XY#

Samples patch locations and rejecting overlaps

sample_patch_position(center_xy: XY, radius_m: float, placed: list[XYR], own_radius: float) → XY#

Sample a shape center inside the circle, respecting spacing and keep-out zones.

generate_patch(center_xy: XY, radius_m: float, contains_target: bool, target_tag_id: int, name_prefix: str = 'patch_0') → list[sim.entity.Entity]#

Generate four gold stars and twelve random shapes; reserve the target tag.

spawn_next_entity() → bool#

Send one request at a time so the bridge is not flooded with spawns.

_log_spawn_result(name: str, future) → None#

Keep the existing spawn logging and mark ready only after all replies succeed.

generate_world()#
main(args=None)#