miniworld-maze 1.0.0__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.
Potentially problematic release.
This version of miniworld-maze might be problematic. Click here for more details.
- miniworld_maze/__init__.py +37 -0
- miniworld_maze/core/__init__.py +8 -0
- miniworld_maze/core/constants.py +130 -0
- miniworld_maze/core/miniworld_gymnasium/README.md +1 -0
- miniworld_maze/core/miniworld_gymnasium/__init__.py +4 -0
- miniworld_maze/core/miniworld_gymnasium/base_env.py +52 -0
- miniworld_maze/core/miniworld_gymnasium/entities/__init__.py +7 -0
- miniworld_maze/core/miniworld_gymnasium/entities/agent.py +117 -0
- miniworld_maze/core/miniworld_gymnasium/entities/base_entity.py +135 -0
- miniworld_maze/core/miniworld_gymnasium/entities/objects.py +116 -0
- miniworld_maze/core/miniworld_gymnasium/entity_manager.py +358 -0
- miniworld_maze/core/miniworld_gymnasium/envs/__init__.py +3 -0
- miniworld_maze/core/miniworld_gymnasium/math.py +83 -0
- miniworld_maze/core/miniworld_gymnasium/objmesh.py +294 -0
- miniworld_maze/core/miniworld_gymnasium/occlusion_queries.py +97 -0
- miniworld_maze/core/miniworld_gymnasium/opengl.py +21 -0
- miniworld_maze/core/miniworld_gymnasium/params.py +128 -0
- miniworld_maze/core/miniworld_gymnasium/random.py +105 -0
- miniworld_maze/core/miniworld_gymnasium/rendering/__init__.py +7 -0
- miniworld_maze/core/miniworld_gymnasium/rendering/drawing.py +77 -0
- miniworld_maze/core/miniworld_gymnasium/rendering/framebuffer.py +260 -0
- miniworld_maze/core/miniworld_gymnasium/rendering/texture.py +101 -0
- miniworld_maze/core/miniworld_gymnasium/rendering_engine.py +293 -0
- miniworld_maze/core/miniworld_gymnasium/room.py +330 -0
- miniworld_maze/core/miniworld_gymnasium/texture_utils.py +64 -0
- miniworld_maze/core/miniworld_gymnasium/textures/airduct_grate_1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/asphalt_1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/beanpaste_1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/beige_1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/black_1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/blueberry_1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/brick_wall_1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/cardboard_1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/cardboard_2.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/cardboard_3.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/cardboard_4.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/ceiling_tile_noborder_1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/ceiling_tiles_1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/cinder_blocks_1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/cobaltgreen_1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/concrete_1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/concrete_2.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/concrete_3.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/concrete_4.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/concrete_tiles_1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/copperred_1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/crimson_1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/door_doom_1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/door_doom_2.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/door_garage_red.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/door_garage_white.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/door_steel_brown.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/door_steel_grey.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/door_steel_red.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/drywall_1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/floor_tiles_bw_1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/floor_tiles_white.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/grass_1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/grass_2.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/lava_1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/lava_2.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/lemongrass_1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/lightbeige_1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/lightcobaltgreen_1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/lightgray_1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/lightnavyblue_1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/lightskyblue_1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/lime_1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/logo_mila_1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/magenta_1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/marble_1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/marble_2.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/metal_grill_1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/metal_grill_2.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/morningglory_1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/navyblue_1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/oakbrown_1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/orange_1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/orchid_1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/picket_fence_1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/adelaide_hanscom1.license +2 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/adelaide_hanscom1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/alessandro_allori1.license +2 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/alessandro_allori1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/alessandro_allori2.license +2 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/alessandro_allori2.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/alexandre_cabanel1.license +2 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/alexandre_cabanel1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/alexei_harlamov1.license +2 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/alexei_harlamov1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/alexey_petrovich_antropov1.license +2 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/alexey_petrovich_antropov1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/alice_pike_barney1.license +2 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/alice_pike_barney1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/aman_theodor1.license +2 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/aman_theodor1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/antonello_messina1.license +2 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/antonello_messina1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/antonio_herrera_toro1.license +2 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/antonio_herrera_toro1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/benjamin-constant1.license +2 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/benjamin-constant1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/benoist_marie-guillemine1.license +2 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/benoist_marie-guillemine1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/bouguereau_william-adolphe1.license +2 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/bouguereau_william-adolphe1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/byron1.license +2 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/byron1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/carl_fredric_breda1.license +2 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/carl_fredric_breda1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/carl_fredric_breda2.license +2 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/carl_fredric_breda2.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/cramacj_lucas1.license +2 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/cramacj_lucas1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/cranach_lucas2.license +2 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/cranach_lucas2.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/cristobal_rojas1.license +2 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/cristobal_rojas1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/delacroix_eugene_ferdinand_victor1.license +2 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/delacroix_eugene_ferdinand_victor1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/domenikos_theotokopoulos1.license +2 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/domenikos_theotokopoulos1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/edmund_blair_leighton1.license +2 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/edmund_blair_leighton1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/edmund_blair_leighton2.license +2 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/edmund_blair_leighton2.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/edwin_longsden_long1.license +2 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/edwin_longsden_long1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/falero_luis_ricardo1.license +2 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/falero_luis_ricardo1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/felix_bonfils1.license +2 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/felix_bonfils1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/francesco_hayez1.license +2 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/francesco_hayez1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/francisco_goya_lucientes1.license +2 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/francisco_goya_lucientes1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/francisco_goya_lucientes2.license +2 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/francisco_goya_lucientes2.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/francisco_zurbaran1.license +2 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/francisco_zurbaran1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/franz_von_defregger1.license +2 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/franz_von_defregger1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/franz_von_defregger2.license +2 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/franz_von_defregger2.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/franz_von_defregger3.license +2 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/franz_von_defregger3.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/frederic_westin1.license +2 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/frederic_westin1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/frederic_yates1.license +2 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/frederic_yates1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/frederick_leighton1.license +2 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/frederick_leighton1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/gaston_bussiere1.license +2 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/gaston_bussiere1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/george_henry_hall1.license +2 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/george_henry_hall1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/giovanni_battista_tiepolo1.license +2 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/giovanni_battista_tiepolo1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/giovanni_bellini1.license +2 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/giovanni_bellini1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/hans_holbein1.license +2 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/hans_holbein1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/hayez_francesco1.license +2 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/hayez_francesco1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/henryk_siemiradzki1.license +2 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/henryk_siemiradzki1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/ilja_jefimowitsch_repin1.license +2 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/ilja_jefimowitsch_repin1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/james_carrol_beckwith1.license +2 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/james_carrol_beckwith1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/jean-baptiste-camille_corot1.license +2 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/jean-baptiste-camille_corot1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/jean-baptiste-camille_corot2.license +2 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/jean-baptiste-camille_corot2.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/jean-leon_gerome1.license +2 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/jean-leon_gerome1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/jean-leon_gerome2.license +2 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/jean-leon_gerome2.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/jean-leon_gerome3.license +2 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/jean-leon_gerome3.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/jean-leon_gerome4.license +2 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/jean-leon_gerome4.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/john_william_godward1.license +2 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/john_william_godward1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/john_william_godward2.license +2 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/john_william_godward2.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/john_william_godward3.license +2 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/john_william_godward3.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/julije_klovic1.license +2 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/julije_klovic1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/juriaen_streek1.license +2 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/juriaen_streek1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/kiprenskij_orest_adamovic1.license +2 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/kiprenskij_orest_adamovic1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/konstantin_makovsky1.license +2 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/konstantin_makovsky1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/lefebvre_jules_joseph1.license +2 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/lefebvre_jules_joseph1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/leon-francois_comerre1.license +2 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/leon-francois_comerre1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/leopold_loffler1.license +2 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/leopold_loffler1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/lewis_john_frederick1.license +2 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/lewis_john_frederick1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/madrazo_garreta_raimundo1.license +2 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/madrazo_garreta_raimundo1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/marie_bashkirtseff1.license +2 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/marie_bashkirtseff1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/moritz_kellerhoven1.license +2 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/moritz_kellerhoven1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/nathaniel_jocelyn1.license +2 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/nathaniel_jocelyn1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/nikolai_alexandrowitsch_jaroschenko1.license +2 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/nikolai_alexandrowitsch_jaroschenko1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/nils_johan_olsson_blommer1.license +2 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/nils_johan_olsson_blommer1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/paolo_veronese1.license +2 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/paolo_veronese1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/parmigianino1.license +2 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/parmigianino1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/paul_cesar_helleu1.license +2 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/paul_cesar_helleu1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/regnault_henri1.license +2 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/regnault_henri1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/richard_bergh1.license +2 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/richard_bergh1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/richard_bergh2.license +2 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/richard_bergh2.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/robert_dampier1.license +2 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/robert_dampier1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/robert_lefevre1.license +2 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/robert_lefevre1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/robert_leopold1.license +2 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/robert_leopold1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/sichel_nathanael1.license +2 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/sichel_nathanael1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/svetoslav_roerich1.license +2 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/svetoslav_roerich1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/velazquez_diego1.license +2 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/velazquez_diego1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/viktor_vasnetsov1.license +2 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/viktor_vasnetsov1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/william-adolphe_bouguereau1.license +2 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/william-adolphe_bouguereau1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/realblueberry_1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/redbean_1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/rock_1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/seablue_1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/silver_1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/skyblue_1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/slime_1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/stucco_1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/sunnyyellow_1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/turquoise_1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/violet_1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/water_1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/water_2.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/water_3.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/white_1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/wood_1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/wood_2.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/wood_planks_1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/unified_env.py +1364 -0
- miniworld_maze/core/miniworld_gymnasium/utils.py +37 -0
- miniworld_maze/core/miniworld_gymnasium/wrappers.py +2 -0
- miniworld_maze/core/observation_types.py +32 -0
- miniworld_maze/environments/__init__.py +16 -0
- miniworld_maze/environments/base_grid_rooms.py +204 -0
- miniworld_maze/environments/factory.py +155 -0
- miniworld_maze/environments/nine_rooms.py +74 -0
- miniworld_maze/environments/spiral_nine_rooms.py +70 -0
- miniworld_maze/environments/twenty_five_rooms.py +122 -0
- miniworld_maze/tools/__init__.py +5 -0
- miniworld_maze/tools/generate_observations.py +199 -0
- miniworld_maze/wrappers/__init__.py +5 -0
- miniworld_maze/wrappers/image_transforms.py +40 -0
- miniworld_maze-1.0.0.dist-info/METADATA +108 -0
- miniworld_maze-1.0.0.dist-info/RECORD +280 -0
- miniworld_maze-1.0.0.dist-info/WHEEL +4 -0
- miniworld_maze-1.0.0.dist-info/entry_points.txt +3 -0
|
@@ -0,0 +1,358 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Centralized entity management system for MiniWorld environments.
|
|
3
|
+
|
|
4
|
+
This module provides a comprehensive entity management architecture that handles
|
|
5
|
+
entity lifecycle, spatial organization, and optimized queries for rendering
|
|
6
|
+
and collision detection.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from typing import List, Optional, Tuple
|
|
10
|
+
|
|
11
|
+
import numpy as np
|
|
12
|
+
|
|
13
|
+
from .entities import Entity
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class EntityCollection:
|
|
17
|
+
"""Optimized entity collection with spatial indexing."""
|
|
18
|
+
|
|
19
|
+
def __init__(self, spatial_grid_size: float = 5.0):
|
|
20
|
+
"""Initialize entity collection with spatial grid indexing.
|
|
21
|
+
|
|
22
|
+
Args:
|
|
23
|
+
spatial_grid_size: Size of spatial grid cells for indexing (default: 5.0)
|
|
24
|
+
"""
|
|
25
|
+
self.entities: List[Entity] = []
|
|
26
|
+
self.spatial_grid_size = spatial_grid_size
|
|
27
|
+
self.spatial_grid: dict = {} # Grid cell -> list of entities
|
|
28
|
+
self._entity_to_cell: dict = {} # Entity -> current grid cell
|
|
29
|
+
|
|
30
|
+
def add(self, entity: Entity) -> None:
|
|
31
|
+
"""Add entity to collection with spatial indexing."""
|
|
32
|
+
if entity not in self.entities:
|
|
33
|
+
self.entities.append(entity)
|
|
34
|
+
self._update_spatial_index(entity)
|
|
35
|
+
|
|
36
|
+
def remove(self, entity: Entity) -> bool:
|
|
37
|
+
"""Remove entity from collection."""
|
|
38
|
+
if entity in self.entities:
|
|
39
|
+
self.entities.remove(entity)
|
|
40
|
+
self._remove_from_spatial_index(entity)
|
|
41
|
+
return True
|
|
42
|
+
return False
|
|
43
|
+
|
|
44
|
+
def update_position(self, entity: Entity) -> None:
|
|
45
|
+
"""Update entity position in spatial index."""
|
|
46
|
+
if entity in self.entities:
|
|
47
|
+
self._update_spatial_index(entity)
|
|
48
|
+
|
|
49
|
+
def get_all(self) -> List[Entity]:
|
|
50
|
+
"""Get all entities in collection."""
|
|
51
|
+
return self.entities.copy()
|
|
52
|
+
|
|
53
|
+
def get_in_radius(self, position: np.ndarray, radius: float) -> List[Entity]:
|
|
54
|
+
"""Get all entities within radius of position."""
|
|
55
|
+
candidates = self._get_spatial_candidates(position, radius)
|
|
56
|
+
|
|
57
|
+
result = []
|
|
58
|
+
for entity in candidates:
|
|
59
|
+
if hasattr(entity, "pos") and entity.pos is not None:
|
|
60
|
+
distance = np.linalg.norm(entity.pos - position)
|
|
61
|
+
if distance <= radius:
|
|
62
|
+
result.append(entity)
|
|
63
|
+
|
|
64
|
+
return result
|
|
65
|
+
|
|
66
|
+
def get_in_bounds(self, min_pos: np.ndarray, max_pos: np.ndarray) -> List[Entity]:
|
|
67
|
+
"""Get all entities within bounding box."""
|
|
68
|
+
result = []
|
|
69
|
+
for entity in self.entities:
|
|
70
|
+
if hasattr(entity, "pos") and entity.pos is not None:
|
|
71
|
+
pos = entity.pos
|
|
72
|
+
if (
|
|
73
|
+
min_pos[0] <= pos[0] <= max_pos[0]
|
|
74
|
+
and min_pos[2] <= pos[2] <= max_pos[2]
|
|
75
|
+
):
|
|
76
|
+
result.append(entity)
|
|
77
|
+
|
|
78
|
+
return result
|
|
79
|
+
|
|
80
|
+
def clear(self) -> None:
|
|
81
|
+
"""Remove all entities from collection."""
|
|
82
|
+
self.entities.clear()
|
|
83
|
+
self.spatial_grid.clear()
|
|
84
|
+
self._entity_to_cell.clear()
|
|
85
|
+
|
|
86
|
+
def _get_grid_cell(self, position: np.ndarray) -> Tuple[int, int]:
|
|
87
|
+
"""Get grid cell coordinates for position."""
|
|
88
|
+
x_cell = int(position[0] // self.spatial_grid_size)
|
|
89
|
+
z_cell = int(position[2] // self.spatial_grid_size)
|
|
90
|
+
return (x_cell, z_cell)
|
|
91
|
+
|
|
92
|
+
def _update_spatial_index(self, entity: Entity) -> None:
|
|
93
|
+
"""Update entity in spatial index."""
|
|
94
|
+
if not hasattr(entity, "pos") or entity.pos is None:
|
|
95
|
+
return
|
|
96
|
+
|
|
97
|
+
new_cell = self._get_grid_cell(entity.pos)
|
|
98
|
+
old_cell = self._entity_to_cell.get(entity)
|
|
99
|
+
|
|
100
|
+
if old_cell != new_cell:
|
|
101
|
+
# Remove from old cell
|
|
102
|
+
if old_cell is not None and old_cell in self.spatial_grid:
|
|
103
|
+
if entity in self.spatial_grid[old_cell]:
|
|
104
|
+
self.spatial_grid[old_cell].remove(entity)
|
|
105
|
+
if not self.spatial_grid[old_cell]:
|
|
106
|
+
del self.spatial_grid[old_cell]
|
|
107
|
+
|
|
108
|
+
# Add to new cell
|
|
109
|
+
if new_cell not in self.spatial_grid:
|
|
110
|
+
self.spatial_grid[new_cell] = []
|
|
111
|
+
if entity not in self.spatial_grid[new_cell]:
|
|
112
|
+
self.spatial_grid[new_cell].append(entity)
|
|
113
|
+
|
|
114
|
+
self._entity_to_cell[entity] = new_cell
|
|
115
|
+
|
|
116
|
+
def _remove_from_spatial_index(self, entity: Entity) -> None:
|
|
117
|
+
"""Remove entity from spatial index."""
|
|
118
|
+
old_cell = self._entity_to_cell.get(entity)
|
|
119
|
+
if old_cell is not None and old_cell in self.spatial_grid:
|
|
120
|
+
if entity in self.spatial_grid[old_cell]:
|
|
121
|
+
self.spatial_grid[old_cell].remove(entity)
|
|
122
|
+
if not self.spatial_grid[old_cell]:
|
|
123
|
+
del self.spatial_grid[old_cell]
|
|
124
|
+
|
|
125
|
+
if entity in self._entity_to_cell:
|
|
126
|
+
del self._entity_to_cell[entity]
|
|
127
|
+
|
|
128
|
+
def _get_spatial_candidates(
|
|
129
|
+
self, position: np.ndarray, radius: float
|
|
130
|
+
) -> List[Entity]:
|
|
131
|
+
"""Get entities from spatial grid cells that could be within radius."""
|
|
132
|
+
candidates = []
|
|
133
|
+
center_cell = self._get_grid_cell(position)
|
|
134
|
+
|
|
135
|
+
# Calculate how many grid cells to check based on radius
|
|
136
|
+
cell_range = int(np.ceil(radius / self.spatial_grid_size)) + 1
|
|
137
|
+
|
|
138
|
+
for dx in range(-cell_range, cell_range + 1):
|
|
139
|
+
for dz in range(-cell_range, cell_range + 1):
|
|
140
|
+
cell = (center_cell[0] + dx, center_cell[1] + dz)
|
|
141
|
+
if cell in self.spatial_grid:
|
|
142
|
+
candidates.extend(self.spatial_grid[cell])
|
|
143
|
+
|
|
144
|
+
return candidates
|
|
145
|
+
|
|
146
|
+
|
|
147
|
+
class EntityLifecycleManager:
|
|
148
|
+
"""Manages entity lifecycle events and state transitions."""
|
|
149
|
+
|
|
150
|
+
def __init__(self):
|
|
151
|
+
"""Initialize entity lifecycle manager with callback lists."""
|
|
152
|
+
self.creation_callbacks = []
|
|
153
|
+
self.removal_callbacks = []
|
|
154
|
+
self.position_update_callbacks = []
|
|
155
|
+
|
|
156
|
+
def register_creation_callback(self, callback):
|
|
157
|
+
"""Register callback for entity creation events."""
|
|
158
|
+
self.creation_callbacks.append(callback)
|
|
159
|
+
|
|
160
|
+
def register_removal_callback(self, callback):
|
|
161
|
+
"""Register callback for entity removal events."""
|
|
162
|
+
self.removal_callbacks.append(callback)
|
|
163
|
+
|
|
164
|
+
def register_position_update_callback(self, callback):
|
|
165
|
+
"""Register callback for entity position updates."""
|
|
166
|
+
self.position_update_callbacks.append(callback)
|
|
167
|
+
|
|
168
|
+
def on_entity_created(self, entity: Entity) -> None:
|
|
169
|
+
"""Handle entity creation event."""
|
|
170
|
+
for callback in self.creation_callbacks:
|
|
171
|
+
callback(entity)
|
|
172
|
+
|
|
173
|
+
def on_entity_removed(self, entity: Entity) -> None:
|
|
174
|
+
"""Handle entity removal event."""
|
|
175
|
+
for callback in self.removal_callbacks:
|
|
176
|
+
callback(entity)
|
|
177
|
+
|
|
178
|
+
def on_entity_position_updated(self, entity: Entity, old_pos: np.ndarray) -> None:
|
|
179
|
+
"""Handle entity position update event."""
|
|
180
|
+
for callback in self.position_update_callbacks:
|
|
181
|
+
callback(entity, old_pos)
|
|
182
|
+
|
|
183
|
+
|
|
184
|
+
class EntityManager:
|
|
185
|
+
"""Centralized entity management system."""
|
|
186
|
+
|
|
187
|
+
def __init__(self, spatial_grid_size: float = 5.0):
|
|
188
|
+
"""Initialize entity manager with spatial collections and lifecycle management.
|
|
189
|
+
|
|
190
|
+
Args:
|
|
191
|
+
spatial_grid_size: Size of spatial grid cells for indexing (default: 5.0)
|
|
192
|
+
"""
|
|
193
|
+
self.static_entities = EntityCollection(spatial_grid_size)
|
|
194
|
+
self.dynamic_entities = EntityCollection(spatial_grid_size)
|
|
195
|
+
self.agent: Optional[Entity] = None
|
|
196
|
+
self.lifecycle_manager = EntityLifecycleManager()
|
|
197
|
+
|
|
198
|
+
# Register internal callbacks for spatial index updates
|
|
199
|
+
self.lifecycle_manager.register_position_update_callback(
|
|
200
|
+
self._on_entity_position_updated
|
|
201
|
+
)
|
|
202
|
+
|
|
203
|
+
def set_agent(self, agent: Entity) -> None:
|
|
204
|
+
"""Set the agent entity."""
|
|
205
|
+
self.agent = agent
|
|
206
|
+
# Agent is typically dynamic
|
|
207
|
+
if agent not in self.dynamic_entities.entities:
|
|
208
|
+
self.add_entity(agent)
|
|
209
|
+
|
|
210
|
+
def add_entity(
|
|
211
|
+
self, entity: Entity, position: Optional[np.ndarray] = None, **kwargs
|
|
212
|
+
) -> None:
|
|
213
|
+
"""Add entity with automatic categorization."""
|
|
214
|
+
if position is not None and hasattr(entity, "pos"):
|
|
215
|
+
entity.pos = position.copy()
|
|
216
|
+
|
|
217
|
+
# Categorize entity
|
|
218
|
+
if self._is_static_entity(entity):
|
|
219
|
+
self.static_entities.add(entity)
|
|
220
|
+
else:
|
|
221
|
+
self.dynamic_entities.add(entity)
|
|
222
|
+
|
|
223
|
+
# Trigger lifecycle event
|
|
224
|
+
self.lifecycle_manager.on_entity_created(entity)
|
|
225
|
+
|
|
226
|
+
def remove_entity(self, entity: Entity) -> bool:
|
|
227
|
+
"""Remove entity from management."""
|
|
228
|
+
removed = self.static_entities.remove(entity) or self.dynamic_entities.remove(
|
|
229
|
+
entity
|
|
230
|
+
)
|
|
231
|
+
|
|
232
|
+
if removed:
|
|
233
|
+
self.lifecycle_manager.on_entity_removed(entity)
|
|
234
|
+
|
|
235
|
+
if entity is self.agent:
|
|
236
|
+
self.agent = None
|
|
237
|
+
|
|
238
|
+
return removed
|
|
239
|
+
|
|
240
|
+
def get_all_entities(self) -> List[Entity]:
|
|
241
|
+
"""Get all entities (static + dynamic)."""
|
|
242
|
+
return self.static_entities.get_all() + self.dynamic_entities.get_all()
|
|
243
|
+
|
|
244
|
+
def get_dynamic_entities(self) -> List[Entity]:
|
|
245
|
+
"""Get all dynamic entities."""
|
|
246
|
+
return self.dynamic_entities.get_all()
|
|
247
|
+
|
|
248
|
+
def get_static_entities(self) -> List[Entity]:
|
|
249
|
+
"""Get all static entities."""
|
|
250
|
+
return self.static_entities.get_all()
|
|
251
|
+
|
|
252
|
+
def get_entities_in_radius(
|
|
253
|
+
self,
|
|
254
|
+
position: np.ndarray,
|
|
255
|
+
radius: float,
|
|
256
|
+
include_static: bool = True,
|
|
257
|
+
include_dynamic: bool = True,
|
|
258
|
+
) -> List[Entity]:
|
|
259
|
+
"""Get entities within radius of position."""
|
|
260
|
+
result = []
|
|
261
|
+
|
|
262
|
+
if include_static:
|
|
263
|
+
result.extend(self.static_entities.get_in_radius(position, radius))
|
|
264
|
+
|
|
265
|
+
if include_dynamic:
|
|
266
|
+
result.extend(self.dynamic_entities.get_in_radius(position, radius))
|
|
267
|
+
|
|
268
|
+
return result
|
|
269
|
+
|
|
270
|
+
def get_visible_entities(self, camera_frustum: dict) -> List[Entity]:
|
|
271
|
+
"""Get entities within camera view frustum."""
|
|
272
|
+
# Simplified frustum culling - use bounding box for now
|
|
273
|
+
min_pos = np.array(
|
|
274
|
+
[
|
|
275
|
+
camera_frustum.get("min_x", -100),
|
|
276
|
+
camera_frustum.get("min_y", -100),
|
|
277
|
+
camera_frustum.get("min_z", -100),
|
|
278
|
+
]
|
|
279
|
+
)
|
|
280
|
+
max_pos = np.array(
|
|
281
|
+
[
|
|
282
|
+
camera_frustum.get("max_x", 100),
|
|
283
|
+
camera_frustum.get("max_y", 100),
|
|
284
|
+
camera_frustum.get("max_z", 100),
|
|
285
|
+
]
|
|
286
|
+
)
|
|
287
|
+
|
|
288
|
+
result = []
|
|
289
|
+
result.extend(self.static_entities.get_in_bounds(min_pos, max_pos))
|
|
290
|
+
result.extend(self.dynamic_entities.get_in_bounds(min_pos, max_pos))
|
|
291
|
+
|
|
292
|
+
return result
|
|
293
|
+
|
|
294
|
+
def update_entity_position(self, entity: Entity, new_position: np.ndarray) -> None:
|
|
295
|
+
"""Update entity position and spatial indices."""
|
|
296
|
+
if hasattr(entity, "pos"):
|
|
297
|
+
old_pos = entity.pos.copy() if entity.pos is not None else None
|
|
298
|
+
entity.pos = new_position.copy()
|
|
299
|
+
|
|
300
|
+
# Update spatial indices
|
|
301
|
+
if entity in self.static_entities.entities:
|
|
302
|
+
self.static_entities.update_position(entity)
|
|
303
|
+
elif entity in self.dynamic_entities.entities:
|
|
304
|
+
self.dynamic_entities.update_position(entity)
|
|
305
|
+
|
|
306
|
+
# Trigger lifecycle event
|
|
307
|
+
if old_pos is not None:
|
|
308
|
+
self.lifecycle_manager.on_entity_position_updated(entity, old_pos)
|
|
309
|
+
|
|
310
|
+
def find_entity_by_type(self, entity_type: type) -> List[Entity]:
|
|
311
|
+
"""Find all entities of specific type."""
|
|
312
|
+
result = []
|
|
313
|
+
for entity in self.get_all_entities():
|
|
314
|
+
if isinstance(entity, entity_type):
|
|
315
|
+
result.append(entity)
|
|
316
|
+
return result
|
|
317
|
+
|
|
318
|
+
def clear_all(self) -> None:
|
|
319
|
+
"""Remove all entities."""
|
|
320
|
+
entities_to_remove = self.get_all_entities()
|
|
321
|
+
for entity in entities_to_remove:
|
|
322
|
+
self.remove_entity(entity)
|
|
323
|
+
|
|
324
|
+
def get_collision_candidates(self, entity: Entity, radius: float) -> List[Entity]:
|
|
325
|
+
"""Get entities that could collide with given entity."""
|
|
326
|
+
if not hasattr(entity, "pos") or entity.pos is None:
|
|
327
|
+
return []
|
|
328
|
+
|
|
329
|
+
candidates = self.get_entities_in_radius(entity.pos, radius)
|
|
330
|
+
# Remove self from candidates
|
|
331
|
+
if entity in candidates:
|
|
332
|
+
candidates.remove(entity)
|
|
333
|
+
|
|
334
|
+
return candidates
|
|
335
|
+
|
|
336
|
+
def _is_static_entity(self, entity: Entity) -> bool:
|
|
337
|
+
"""Determine if entity should be categorized as static."""
|
|
338
|
+
return (hasattr(entity, "is_static") and entity.is_static) or (
|
|
339
|
+
hasattr(entity, "static") and entity.static
|
|
340
|
+
)
|
|
341
|
+
|
|
342
|
+
def _on_entity_position_updated(self, entity: Entity, old_pos: np.ndarray) -> None:
|
|
343
|
+
"""Internal callback for entity position updates."""
|
|
344
|
+
# Update spatial indices when entity positions change
|
|
345
|
+
if entity in self.static_entities.entities:
|
|
346
|
+
self.static_entities.update_position(entity)
|
|
347
|
+
elif entity in self.dynamic_entities.entities:
|
|
348
|
+
self.dynamic_entities.update_position(entity)
|
|
349
|
+
|
|
350
|
+
def get_statistics(self) -> dict:
|
|
351
|
+
"""Get entity management statistics."""
|
|
352
|
+
return {
|
|
353
|
+
"total_entities": len(self.get_all_entities()),
|
|
354
|
+
"static_entities": len(self.static_entities.entities),
|
|
355
|
+
"dynamic_entities": len(self.dynamic_entities.entities),
|
|
356
|
+
"spatial_grid_cells": len(self.static_entities.spatial_grid)
|
|
357
|
+
+ len(self.dynamic_entities.spatial_grid),
|
|
358
|
+
}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
"""Mathematical utility functions for 3D geometry and transformations."""
|
|
2
|
+
|
|
3
|
+
import math
|
|
4
|
+
|
|
5
|
+
import numpy as np
|
|
6
|
+
|
|
7
|
+
# Standard 3D coordinate system basis vectors
|
|
8
|
+
X_VEC = np.array([1, 0, 0]) # X-axis unit vector
|
|
9
|
+
Y_VEC = np.array([0, 1, 0]) # Y-axis unit vector (up)
|
|
10
|
+
Z_VEC = np.array([0, 0, 1]) # Z-axis unit vector
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def gen_rot_matrix(axis, angle):
|
|
14
|
+
"""
|
|
15
|
+
Generate a rotation matrix for counterclockwise rotation around an axis.
|
|
16
|
+
|
|
17
|
+
Uses Rodrigues' rotation formula to compute the rotation matrix.
|
|
18
|
+
|
|
19
|
+
Args:
|
|
20
|
+
axis: 3D vector representing the rotation axis (will be normalized)
|
|
21
|
+
angle: Rotation angle in radians
|
|
22
|
+
|
|
23
|
+
Returns:
|
|
24
|
+
3x3 numpy array representing the rotation matrix
|
|
25
|
+
"""
|
|
26
|
+
|
|
27
|
+
axis = axis / math.sqrt(np.dot(axis, axis))
|
|
28
|
+
a = math.cos(angle / 2.0)
|
|
29
|
+
b, c, d = -axis * math.sin(angle / 2.0)
|
|
30
|
+
|
|
31
|
+
return np.array(
|
|
32
|
+
[
|
|
33
|
+
[a * a + b * b - c * c - d * d, 2 * (b * c - a * d), 2 * (b * d + a * c)],
|
|
34
|
+
[2 * (b * c + a * d), a * a + c * c - b * b - d * d, 2 * (c * d - a * b)],
|
|
35
|
+
[2 * (b * d - a * c), 2 * (c * d + a * b), a * a + d * d - b * b - c * c],
|
|
36
|
+
]
|
|
37
|
+
)
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def intersect_circle_segs(point, radius, segs):
|
|
41
|
+
"""
|
|
42
|
+
Test if a circle intersects with any wall segments using 2D projection.
|
|
43
|
+
|
|
44
|
+
Projects the 3D problem onto the XZ plane (ignoring Y coordinate) and
|
|
45
|
+
performs efficient vectorized collision detection against multiple segments.
|
|
46
|
+
|
|
47
|
+
Args:
|
|
48
|
+
point: 3D position of circle center
|
|
49
|
+
radius: Radius of the circle
|
|
50
|
+
segs: Array of wall segments with shape (N, 2, 3) representing N segments
|
|
51
|
+
|
|
52
|
+
Returns:
|
|
53
|
+
Boolean indicating whether the circle intersects any segment
|
|
54
|
+
"""
|
|
55
|
+
|
|
56
|
+
# Ignore Y coordinate
|
|
57
|
+
px, _, pz = point
|
|
58
|
+
point = np.array([px, 0, pz])
|
|
59
|
+
|
|
60
|
+
a = segs[:, 0, :]
|
|
61
|
+
b = segs[:, 1, :]
|
|
62
|
+
ab = b - a
|
|
63
|
+
ap = point - a
|
|
64
|
+
|
|
65
|
+
dotAPAB = np.sum(ap * ab, axis=1)
|
|
66
|
+
dotABAB = np.sum(ab * ab, axis=1)
|
|
67
|
+
|
|
68
|
+
proj_dist = dotAPAB / dotABAB
|
|
69
|
+
proj_dist = np.clip(proj_dist, 0, 1)
|
|
70
|
+
proj_dist = np.expand_dims(proj_dist, axis=1)
|
|
71
|
+
|
|
72
|
+
# Compute the closest point on the segment
|
|
73
|
+
c = a + proj_dist * ab
|
|
74
|
+
|
|
75
|
+
# Check if any distances are within the radius
|
|
76
|
+
dist = np.linalg.norm(c - point, axis=1)
|
|
77
|
+
dist_lt_rad = np.less(dist, radius)
|
|
78
|
+
|
|
79
|
+
if np.any(dist_lt_rad):
|
|
80
|
+
return True
|
|
81
|
+
|
|
82
|
+
# No intersection
|
|
83
|
+
return None
|