diff --git a/src/iiwa_experement/test/test_package_layout.py b/src/iiwa_experement/test/test_package_layout.py index 8ebe394..8848fa6 100644 --- a/src/iiwa_experement/test/test_package_layout.py +++ b/src/iiwa_experement/test/test_package_layout.py @@ -42,6 +42,7 @@ def test_expected_resources_are_installed(): 'package.xml', 'doc/experements.md', 'doc/experiment-scenes.md', + 'worlds/grant/iiwa-grant.wbt', ): path = share / relative assert path.is_file(), path diff --git a/src/iiwa_experement/test/test_world.py b/src/iiwa_experement/test/test_world.py new file mode 100644 index 0000000..c0004e9 --- /dev/null +++ b/src/iiwa_experement/test/test_world.py @@ -0,0 +1,52 @@ +"""The world template contains only the shared table, fences and lighting.""" +import re +from pathlib import Path + + +PACKAGE = Path(__file__).resolve().parents[1] +WORLD = PACKAGE / 'worlds' / 'grant' / 'iiwa-grant.wbt' + + +def test_world_matches_base_layout(): + text = WORLD.read_text(encoding='utf-8') + assert '#VRML_SIM R2025a utf8' in text + assert 'basicTimeStep 32' in text + assert re.search(r'CollaborativeRobotTable \{\s+translation 0 0 -0\.007', text) + assert text.count('WorkspaceLimiter {') == 2 + assert 'WorkspaceLimiter_back' in text + assert 'WorkspaceLimiter_right' in text + assert 'coulombFriction [ 0.6 ]' in text + assert 'Object.proto' not in text + + +def test_world_has_no_preplaced_experiment_objects_or_robot(): + text = WORLD.read_text(encoding='utf-8') + for asset in ( + 'stapel.obj', + 'base-detail.obj', + 'cap.obj', + 'lotok.obj', + 'vint.obj', + 'tool-magizine.obj', + 'vacum-tool.obj', + 'magnit-tool.obj', + 'germetic-tool.obj', + 'wranch-tool.obj', + ): + assert asset not in text + assert 'Kuka' not in text + assert 'Robot {' not in text + assert 'GrantToolRack' not in text + + +def test_world_only_references_two_local_protos(): + text = WORLD.read_text(encoding='utf-8') + externprotos = re.findall(r'EXTERNPROTO "([^"]+)"', text) + local = [url for url in externprotos if not url.startswith(('http://', 'https://'))] + assert local == [ + '../../../iiwa_description/resource/protos/CollaborativeRobotTable.proto', + '../../../iiwa_description/resource/protos/WorkspaceLimiter.proto', + ] + for url in externprotos: + if url.startswith(('http://', 'https://')): + assert '/webots/R2025a/' in url diff --git a/src/iiwa_experement/worlds/grant/iiwa-grant.wbt b/src/iiwa_experement/worlds/grant/iiwa-grant.wbt new file mode 100644 index 0000000..562d236 --- /dev/null +++ b/src/iiwa_experement/worlds/grant/iiwa-grant.wbt @@ -0,0 +1,88 @@ +#VRML_SIM R2025a utf8 + +# Universal grant experiment world. The robot, cameras and experiment objects +# are added at run time: iiwa_bringup spawns the iiwa 7 and +# iiwa_experement/scene_spawner adds the deterministic scenario. The two local +# EXTERNPROTO paths are valid from this source tree; runtime_config.py rewrites +# them to absolute paths from the installed iiwa_description share before +# Webots opens the temporary copy of this world. + +EXTERNPROTO "https://raw.githubusercontent.com/cyberbotics/webots/R2025a/projects/objects/backgrounds/protos/TexturedBackground.proto" +EXTERNPROTO "https://raw.githubusercontent.com/cyberbotics/webots/R2025a/projects/objects/backgrounds/protos/TexturedBackgroundLight.proto" +EXTERNPROTO "https://raw.githubusercontent.com/cyberbotics/webots/R2025a/projects/objects/floors/protos/RectangleArena.proto" +EXTERNPROTO "../../../iiwa_description/resource/protos/CollaborativeRobotTable.proto" +EXTERNPROTO "../../../iiwa_description/resource/protos/WorkspaceLimiter.proto" + + +WorldInfo { + title "KUKA iiwa grant experiments" + basicTimeStep 32 + optimalThreadCount 4 + contactProperties [ + ContactProperties { + material1 "TableMaterial" + coulombFriction [ 0.6 ] + bounce 0 + bounceVelocity 0 + softERP 1 + softCFM 0.0001 + } + ContactProperties { + material1 "tool" + material2 "TableMaterial" + bounce 0 + softCFM 0.002 + maxContactJoints 100 + } + ContactProperties { + material1 "default" + material2 "default" + maxContactJoints 20 + bounce 0 + softCFM 0.001 + } + ] +} +Viewpoint { + orientation 0.19663259328507318 -0.09057124279298501 -0.9762850368805829 3.9867817928674034 + position 1.75 -1.85 1.77 + followType "Mounted Shot" + ambientOcclusionRadius 3 +} +TexturedBackground { +} +TexturedBackgroundLight { + texture "noon_sunny_empty" + luminosity 2 +} +RectangleArena { + name "Arena" + floorSize 12 12 + wallHeight 2 +} +CollaborativeRobotTable { + translation 0 0 -0.007 + locked TRUE + showCabinet TRUE +} +DEF limiter Group { + children [ + WorkspaceLimiter { + translation -1.56 -0.219999 1.01 + rotation 0 0 1 1.5708 + name "WorkspaceLimiter_back" + locked TRUE + scale 2.32 1 2 + } + WorkspaceLimiter { + translation -0.04 1.18 1.01 + name "WorkspaceLimiter_right" + locked TRUE + scale 2.43 1 2 + } + ] +} +DirectionalLight { + direction -0.1 0.1 0 + intensity 2 +}