simview 5.1.1__tar.gz → 6.0.0__tar.gz
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.
- {simview-5.1.1/simview.egg-info → simview-6.0.0}/PKG-INFO +3 -3
- {simview-5.1.1 → simview-6.0.0}/README.md +2 -2
- {simview-5.1.1 → simview-6.0.0}/pyproject.toml +1 -1
- {simview-5.1.1 → simview-6.0.0}/simview/__init__.py +3 -2
- {simview-5.1.1 → simview-6.0.0}/simview/__main__.py +40 -81
- {simview-5.1.1 → simview-6.0.0}/simview/columnar.py +9 -4
- {simview-5.1.1 → simview-6.0.0}/simview/diff.py +42 -76
- {simview-5.1.1 → simview-6.0.0}/simview/info.py +4 -4
- {simview-5.1.1 → simview-6.0.0}/simview/launcher.py +3 -14
- {simview-5.1.1 → simview-6.0.0}/simview/live.py +4 -119
- {simview-5.1.1 → simview-6.0.0}/simview/merge.py +48 -124
- {simview-5.1.1 → simview-6.0.0}/simview/model.py +14 -213
- {simview-5.1.1 → simview-6.0.0}/simview/remote.py +1 -3
- {simview-5.1.1 → simview-6.0.0}/simview/render.py +13 -54
- {simview-5.1.1 → simview-6.0.0}/simview/scene.py +121 -132
- {simview-5.1.1 → simview-6.0.0}/simview/server.py +126 -87
- {simview-5.1.1 → simview-6.0.0}/simview/state.py +15 -33
- {simview-5.1.1 → simview-6.0.0}/simview/static/css/controls.css +85 -165
- {simview-5.1.1 → simview-6.0.0}/simview/static/js/SimView.js +9 -50
- {simview-5.1.1 → simview-6.0.0}/simview/static/js/components/AnimationController.js +24 -74
- {simview-5.1.1 → simview-6.0.0}/simview/static/js/components/BatchManager.js +3 -29
- {simview-5.1.1 → simview-6.0.0}/simview/static/js/components/Scene.js +13 -16
- {simview-5.1.1 → simview-6.0.0}/simview/static/js/components/WindowedField.js +1 -2
- {simview-5.1.1 → simview-6.0.0}/simview/static/js/config.js +0 -4
- {simview-5.1.1 → simview-6.0.0}/simview/static/js/objects/Body.js +1 -26
- {simview-5.1.1 → simview-6.0.0}/simview/static/js/objects/StaticObject.js +9 -19
- {simview-5.1.1 → simview-6.0.0}/simview/static/js/objects/Terrain.js +6 -14
- {simview-5.1.1 → simview-6.0.0}/simview/static/js/objects/colormap.js +0 -6
- {simview-5.1.1 → simview-6.0.0}/simview/static/js/objects/utils.js +68 -20
- simview-6.0.0/simview/static/js/ui/AnalysisPanel.js +88 -0
- {simview-5.1.1 → simview-6.0.0}/simview/static/js/ui/BatchLegend.js +7 -22
- {simview-5.1.1 → simview-6.0.0}/simview/static/js/ui/BodyStateWindow.js +37 -67
- {simview-5.1.1 → simview-6.0.0}/simview/static/js/ui/Controls.js +61 -69
- {simview-5.1.1 → simview-6.0.0}/simview/static/js/ui/ErrorMetrics.js +90 -184
- {simview-5.1.1 → simview-6.0.0}/simview/static/js/ui/Legend.js +3 -1
- {simview-5.1.1 → simview-6.0.0}/simview/static/js/ui/PlaybackControls.js +31 -58
- {simview-5.1.1 → simview-6.0.0}/simview/static/js/ui/ScalarPlotter.js +20 -130
- {simview-5.1.1 → simview-6.0.0}/simview/static/js/ui/TerrainProfile.js +19 -138
- simview-6.0.0/simview/static/js/ui/chartControls.js +72 -0
- simview-6.0.0/simview/static/js/utils/blobCodec.js +42 -0
- {simview-5.1.1 → simview-6.0.0}/simview/static/js/utils/csv.js +17 -13
- simview-6.0.0/simview/static/js/utils/uplot.js +118 -0
- {simview-5.1.1 → simview-6.0.0}/simview/static/js/utils/viewState.js +32 -93
- simview-6.0.0/simview/static/lib/js-colormaps.js +3226 -0
- {simview-5.1.1 → simview-6.0.0}/simview/templates/index.html +2 -3
- {simview-5.1.1 → simview-6.0.0}/simview/terrain.py +67 -135
- {simview-5.1.1 → simview-6.0.0}/simview/utils.py +84 -24
- {simview-5.1.1 → simview-6.0.0/simview.egg-info}/PKG-INFO +3 -3
- simview-6.0.0/simview.egg-info/SOURCES.txt +98 -0
- {simview-5.1.1 → simview-6.0.0}/tests/test_columnar_ondisk.py +1 -1
- {simview-5.1.1 → simview-6.0.0}/tests/test_roundtrip.py +4 -9
- {simview-5.1.1 → simview-6.0.0}/tests/test_scene.py +3 -3
- {simview-5.1.1 → simview-6.0.0}/tests/test_show.py +2 -2
- simview-5.1.1/simview/static/js/components/InteractionControls.js +0 -63
- simview-5.1.1/simview/static/js/ui/AnalysisPanel.js +0 -159
- simview-5.1.1/simview/static/js/utils/blobCodec.js +0 -75
- simview-5.1.1/simview/static/js/utils/uplot.js +0 -59
- simview-5.1.1/simview/static/lib/chroma-js-3.1.2/index.min.js +0 -8
- simview-5.1.1/simview/static/lib/chroma-js-3.1.2/src/Color.js +0 -49
- simview-5.1.1/simview/static/lib/chroma-js-3.1.2/src/chroma.js +0 -10
- simview-5.1.1/simview/static/lib/chroma-js-3.1.2/src/colors/colorbrewer.js +0 -81
- simview-5.1.1/simview/static/lib/chroma-js-3.1.2/src/colors/w3cx11.js +0 -164
- simview-5.1.1/simview/static/lib/chroma-js-3.1.2/src/generator/average.js +0 -88
- simview-5.1.1/simview/static/lib/chroma-js-3.1.2/src/generator/bezier.js +0 -86
- simview-5.1.1/simview/static/lib/chroma-js-3.1.2/src/generator/blend.js +0 -57
- simview-5.1.1/simview/static/lib/chroma-js-3.1.2/src/generator/cubehelix.js +0 -87
- simview-5.1.1/simview/static/lib/chroma-js-3.1.2/src/generator/mix.js +0 -19
- simview-5.1.1/simview/static/lib/chroma-js-3.1.2/src/generator/random.js +0 -12
- simview-5.1.1/simview/static/lib/chroma-js-3.1.2/src/generator/scale.js +0 -394
- simview-5.1.1/simview/static/lib/chroma-js-3.1.2/src/interpolator/_hsx.js +0 -59
- simview-5.1.1/simview/static/lib/chroma-js-3.1.2/src/interpolator/hcg.js +0 -12
- simview-5.1.1/simview/static/lib/chroma-js-3.1.2/src/interpolator/hsi.js +0 -12
- simview-5.1.1/simview/static/lib/chroma-js-3.1.2/src/interpolator/hsl.js +0 -12
- simview-5.1.1/simview/static/lib/chroma-js-3.1.2/src/interpolator/hsv.js +0 -12
- simview-5.1.1/simview/static/lib/chroma-js-3.1.2/src/interpolator/index.js +0 -1
- simview-5.1.1/simview/static/lib/chroma-js-3.1.2/src/interpolator/lab.js +0 -19
- simview-5.1.1/simview/static/lib/chroma-js-3.1.2/src/interpolator/lch.js +0 -13
- simview-5.1.1/simview/static/lib/chroma-js-3.1.2/src/interpolator/lrgb.js +0 -19
- simview-5.1.1/simview/static/lib/chroma-js-3.1.2/src/interpolator/num.js +0 -15
- simview-5.1.1/simview/static/lib/chroma-js-3.1.2/src/interpolator/oklab.js +0 -19
- simview-5.1.1/simview/static/lib/chroma-js-3.1.2/src/interpolator/oklch.js +0 -12
- simview-5.1.1/simview/static/lib/chroma-js-3.1.2/src/interpolator/rgb.js +0 -18
- simview-5.1.1/simview/static/lib/chroma-js-3.1.2/src/io/cmyk/cmyk2rgb.js +0 -16
- simview-5.1.1/simview/static/lib/chroma-js-3.1.2/src/io/cmyk/index.js +0 -27
- simview-5.1.1/simview/static/lib/chroma-js-3.1.2/src/io/cmyk/rgb2cmyk.js +0 -17
- simview-5.1.1/simview/static/lib/chroma-js-3.1.2/src/io/css/css2rgb.js +0 -238
- simview-5.1.1/simview/static/lib/chroma-js-3.1.2/src/io/css/hsl2css.js +0 -26
- simview-5.1.1/simview/static/lib/chroma-js-3.1.2/src/io/css/index.js +0 -27
- simview-5.1.1/simview/static/lib/chroma-js-3.1.2/src/io/css/lab2css.js +0 -24
- simview-5.1.1/simview/static/lib/chroma-js-3.1.2/src/io/css/lch2css.js +0 -24
- simview-5.1.1/simview/static/lib/chroma-js-3.1.2/src/io/css/oklab2css.js +0 -16
- simview-5.1.1/simview/static/lib/chroma-js-3.1.2/src/io/css/oklch2css.js +0 -16
- simview-5.1.1/simview/static/lib/chroma-js-3.1.2/src/io/css/rgb2css.js +0 -61
- simview-5.1.1/simview/static/lib/chroma-js-3.1.2/src/io/gl/index.js +0 -22
- simview-5.1.1/simview/static/lib/chroma-js-3.1.2/src/io/hcg/hcg2rgb.js +0 -55
- simview-5.1.1/simview/static/lib/chroma-js-3.1.2/src/io/hcg/index.js +0 -27
- simview-5.1.1/simview/static/lib/chroma-js-3.1.2/src/io/hcg/rgb2hcg.js +0 -23
- simview-5.1.1/simview/static/lib/chroma-js-3.1.2/src/io/hex/hex2rgb.js +0 -56
- simview-5.1.1/simview/static/lib/chroma-js-3.1.2/src/io/hex/index.js +0 -29
- simview-5.1.1/simview/static/lib/chroma-js-3.1.2/src/io/hex/rgb2hex.js +0 -29
- simview-5.1.1/simview/static/lib/chroma-js-3.1.2/src/io/hsi/hsi2rgb.js +0 -45
- simview-5.1.1/simview/static/lib/chroma-js-3.1.2/src/io/hsi/index.js +0 -27
- simview-5.1.1/simview/static/lib/chroma-js-3.1.2/src/io/hsi/rgb2hsi.js +0 -31
- simview-5.1.1/simview/static/lib/chroma-js-3.1.2/src/io/hsl/hsl2rgb.js +0 -35
- simview-5.1.1/simview/static/lib/chroma-js-3.1.2/src/io/hsl/index.js +0 -27
- simview-5.1.1/simview/static/lib/chroma-js-3.1.2/src/io/hsl/rgb2hsl.js +0 -45
- simview-5.1.1/simview/static/lib/chroma-js-3.1.2/src/io/hsv/hsv2rgb.js +0 -47
- simview-5.1.1/simview/static/lib/chroma-js-3.1.2/src/io/hsv/index.js +0 -27
- simview-5.1.1/simview/static/lib/chroma-js-3.1.2/src/io/hsv/rgb2hsv.js +0 -32
- simview-5.1.1/simview/static/lib/chroma-js-3.1.2/src/io/input.js +0 -4
- simview-5.1.1/simview/static/lib/chroma-js-3.1.2/src/io/lab/index.js +0 -28
- simview-5.1.1/simview/static/lib/chroma-js-3.1.2/src/io/lab/lab-constants.js +0 -120
- simview-5.1.1/simview/static/lib/chroma-js-3.1.2/src/io/lab/lab2rgb.js +0 -101
- simview-5.1.1/simview/static/lib/chroma-js-3.1.2/src/io/lab/rgb2lab.js +0 -67
- simview-5.1.1/simview/static/lib/chroma-js-3.1.2/src/io/lch/hcl2rgb.js +0 -9
- simview-5.1.1/simview/static/lib/chroma-js-3.1.2/src/io/lch/index.js +0 -35
- simview-5.1.1/simview/static/lib/chroma-js-3.1.2/src/io/lch/lab2lch.js +0 -12
- simview-5.1.1/simview/static/lib/chroma-js-3.1.2/src/io/lch/lch2lab.js +0 -18
- simview-5.1.1/simview/static/lib/chroma-js-3.1.2/src/io/lch/lch2rgb.js +0 -13
- simview-5.1.1/simview/static/lib/chroma-js-3.1.2/src/io/lch/rgb2lch.js +0 -12
- simview-5.1.1/simview/static/lib/chroma-js-3.1.2/src/io/named/index.js +0 -30
- simview-5.1.1/simview/static/lib/chroma-js-3.1.2/src/io/num/index.js +0 -32
- simview-5.1.1/simview/static/lib/chroma-js-3.1.2/src/io/num/num2rgb.js +0 -13
- simview-5.1.1/simview/static/lib/chroma-js-3.1.2/src/io/num/rgb2num.js +0 -8
- simview-5.1.1/simview/static/lib/chroma-js-3.1.2/src/io/oklab/index.js +0 -27
- simview-5.1.1/simview/static/lib/chroma-js-3.1.2/src/io/oklab/oklab2rgb.js +0 -34
- simview-5.1.1/simview/static/lib/chroma-js-3.1.2/src/io/oklab/rgb2oklab.js +0 -37
- simview-5.1.1/simview/static/lib/chroma-js-3.1.2/src/io/oklch/index.js +0 -27
- simview-5.1.1/simview/static/lib/chroma-js-3.1.2/src/io/oklch/oklch2rgb.js +0 -13
- simview-5.1.1/simview/static/lib/chroma-js-3.1.2/src/io/oklch/rgb2oklch.js +0 -12
- simview-5.1.1/simview/static/lib/chroma-js-3.1.2/src/io/rgb/index.js +0 -44
- simview-5.1.1/simview/static/lib/chroma-js-3.1.2/src/io/temp/index.js +0 -22
- simview-5.1.1/simview/static/lib/chroma-js-3.1.2/src/io/temp/rgb2temperature.js +0 -30
- simview-5.1.1/simview/static/lib/chroma-js-3.1.2/src/io/temp/temperature2rgb.js +0 -39
- simview-5.1.1/simview/static/lib/chroma-js-3.1.2/src/ops/alpha.js +0 -13
- simview-5.1.1/simview/static/lib/chroma-js-3.1.2/src/ops/clipped.js +0 -5
- simview-5.1.1/simview/static/lib/chroma-js-3.1.2/src/ops/darken.js +0 -17
- simview-5.1.1/simview/static/lib/chroma-js-3.1.2/src/ops/get.js +0 -13
- simview-5.1.1/simview/static/lib/chroma-js-3.1.2/src/ops/luminance.js +0 -54
- simview-5.1.1/simview/static/lib/chroma-js-3.1.2/src/ops/mix.js +0 -10
- simview-5.1.1/simview/static/lib/chroma-js-3.1.2/src/ops/premultiply.js +0 -12
- simview-5.1.1/simview/static/lib/chroma-js-3.1.2/src/ops/saturate.js +0 -15
- simview-5.1.1/simview/static/lib/chroma-js-3.1.2/src/ops/set.js +0 -43
- simview-5.1.1/simview/static/lib/chroma-js-3.1.2/src/ops/shade.js +0 -11
- simview-5.1.1/simview/static/lib/chroma-js-3.1.2/src/utils/analyze.js +0 -191
- simview-5.1.1/simview/static/lib/chroma-js-3.1.2/src/utils/clip_rgb.js +0 -15
- simview-5.1.1/simview/static/lib/chroma-js-3.1.2/src/utils/contrast.js +0 -12
- simview-5.1.1/simview/static/lib/chroma-js-3.1.2/src/utils/contrastAPCA.js +0 -68
- simview-5.1.1/simview/static/lib/chroma-js-3.1.2/src/utils/delta-e.js +0 -62
- simview-5.1.1/simview/static/lib/chroma-js-3.1.2/src/utils/distance.js +0 -17
- simview-5.1.1/simview/static/lib/chroma-js-3.1.2/src/utils/index.js +0 -27
- simview-5.1.1/simview/static/lib/chroma-js-3.1.2/src/utils/last.js +0 -8
- simview-5.1.1/simview/static/lib/chroma-js-3.1.2/src/utils/limit.js +0 -5
- simview-5.1.1/simview/static/lib/chroma-js-3.1.2/src/utils/multiply-matrices.js +0 -36
- simview-5.1.1/simview/static/lib/chroma-js-3.1.2/src/utils/scales.js +0 -15
- simview-5.1.1/simview/static/lib/chroma-js-3.1.2/src/utils/type.js +0 -18
- simview-5.1.1/simview/static/lib/chroma-js-3.1.2/src/utils/unpack.js +0 -17
- simview-5.1.1/simview/static/lib/chroma-js-3.1.2/src/utils/valid.js +0 -11
- simview-5.1.1/simview/static/lib/chroma-js-3.1.2/src/version.js +0 -2
- simview-5.1.1/simview/static/lib/js-colormaps.js +0 -19335
- simview-5.1.1/simview.egg-info/SOURCES.txt +0 -200
- {simview-5.1.1 → simview-6.0.0}/LICENSE +0 -0
- {simview-5.1.1 → simview-6.0.0}/MANIFEST.in +0 -0
- {simview-5.1.1 → simview-6.0.0}/setup.cfg +0 -0
- {simview-5.1.1 → simview-6.0.0}/simview/py.typed +0 -0
- {simview-5.1.1 → simview-6.0.0}/simview/static/js/components/InteractionController.js +0 -0
- {simview-5.1.1 → simview-6.0.0}/simview/static/js/components/StateStore.js +0 -0
- {simview-5.1.1 → simview-6.0.0}/simview/static/js/main.js +0 -0
- {simview-5.1.1 → simview-6.0.0}/simview/static/js/objects/similarity.js +0 -0
- {simview-5.1.1 → simview-6.0.0}/simview/static/js/utils/batchPresets.js +0 -0
- {simview-5.1.1 → simview-6.0.0}/simview/static/js/utils/batchVisibility.js +0 -0
- {simview-5.1.1 → simview-6.0.0}/simview/static/js/utils/blobWindow.js +0 -0
- {simview-5.1.1 → simview-6.0.0}/simview/static/js/utils/bodyTransforms.js +0 -0
- {simview-5.1.1 → simview-6.0.0}/simview/static/js/utils/cameraRange.js +0 -0
- {simview-5.1.1 → simview-6.0.0}/simview/static/js/utils/episodes.js +0 -0
- {simview-5.1.1 → simview-6.0.0}/simview/static/js/utils/errorMath.js +0 -0
- {simview-5.1.1 → simview-6.0.0}/simview/static/js/utils/interpolate.js +0 -0
- {simview-5.1.1 → simview-6.0.0}/simview/static/js/utils/liveFollow.js +0 -0
- {simview-5.1.1 → simview-6.0.0}/simview/static/js/utils/terrainSample.js +0 -0
- {simview-5.1.1 → simview-6.0.0}/simview/static/lib/three-0.174.0/addons/controls/OrbitControls.js +0 -0
- {simview-5.1.1 → simview-6.0.0}/simview/static/lib/three-0.174.0/addons/libs/lil-gui.module.min.js +0 -0
- {simview-5.1.1 → simview-6.0.0}/simview/static/lib/three-0.174.0/three.core.js +0 -0
- {simview-5.1.1 → simview-6.0.0}/simview/static/lib/three-0.174.0/three.module.js +0 -0
- {simview-5.1.1 → simview-6.0.0}/simview/static/lib/uPlot.esm.js +0 -0
- {simview-5.1.1 → simview-6.0.0}/simview/static/lib/uPlot.min.css +0 -0
- {simview-5.1.1 → simview-6.0.0}/simview/static/textures/contacts/red-cross0.png +0 -0
- {simview-5.1.1 → simview-6.0.0}/simview/static/textures/points/ball1.png +0 -0
- {simview-5.1.1 → simview-6.0.0}/simview.egg-info/dependency_links.txt +0 -0
- {simview-5.1.1 → simview-6.0.0}/simview.egg-info/entry_points.txt +0 -0
- {simview-5.1.1 → simview-6.0.0}/simview.egg-info/requires.txt +0 -0
- {simview-5.1.1 → simview-6.0.0}/simview.egg-info/top_level.txt +0 -0
- {simview-5.1.1 → simview-6.0.0}/tests/test_batch_selection.py +0 -0
- {simview-5.1.1 → simview-6.0.0}/tests/test_cli.py +0 -0
- {simview-5.1.1 → simview-6.0.0}/tests/test_columnar_states.py +0 -0
- {simview-5.1.1 → simview-6.0.0}/tests/test_contacts.py +0 -0
- {simview-5.1.1 → simview-6.0.0}/tests/test_diff.py +0 -0
- {simview-5.1.1 → simview-6.0.0}/tests/test_episodes.py +0 -0
- {simview-5.1.1 → simview-6.0.0}/tests/test_info.py +0 -0
- {simview-5.1.1 → simview-6.0.0}/tests/test_launcher.py +0 -0
- {simview-5.1.1 → simview-6.0.0}/tests/test_live.py +0 -0
- {simview-5.1.1 → simview-6.0.0}/tests/test_merge.py +0 -0
- {simview-5.1.1 → simview-6.0.0}/tests/test_pointcloud_features.py +0 -0
- {simview-5.1.1 → simview-6.0.0}/tests/test_remote.py +0 -0
- {simview-5.1.1 → simview-6.0.0}/tests/test_server.py +0 -0
- {simview-5.1.1 → simview-6.0.0}/tests/test_terrain.py +0 -0
- {simview-5.1.1 → simview-6.0.0}/tests/test_terrain_query.py +0 -0
- {simview-5.1.1 → simview-6.0.0}/tests/test_trajectory.py +0 -0
- {simview-5.1.1 → simview-6.0.0}/tests/test_utils.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: simview
|
|
3
|
-
Version:
|
|
3
|
+
Version: 6.0.0
|
|
4
4
|
Summary: THREE.js-based simulation visualization tool
|
|
5
5
|
Author-email: Jan Vlk <vlkjan6@fel.cvut.cz>, Ales Kucera <kuceral4@fel.cvut.cz>, David Korcak <david.korcak@gmail.com>
|
|
6
6
|
License-Expression: BSD-3-Clause
|
|
@@ -128,8 +128,8 @@ source .venv/bin/activate
|
|
|
128
128
|
## License
|
|
129
129
|
|
|
130
130
|
SimView is distributed under the [BSD 3-Clause License](LICENSE). The web interface
|
|
131
|
-
vendors [uPlot](https://github.com/leeoniya/uPlot)
|
|
132
|
-
|
|
131
|
+
vendors [uPlot](https://github.com/leeoniya/uPlot) and [three.js](https://github.com/mrdoob/three.js)
|
|
132
|
+
(both MIT licensed) under
|
|
133
133
|
`simview/static/lib/` so the viewer works fully offline — see the
|
|
134
134
|
[documentation](https://vlk-jan.github.io/simview/dev/architecture/#vendored-third-party-libraries)
|
|
135
135
|
for details. All third-party libraries used by SimView are permissively licensed
|
|
@@ -97,8 +97,8 @@ source .venv/bin/activate
|
|
|
97
97
|
## License
|
|
98
98
|
|
|
99
99
|
SimView is distributed under the [BSD 3-Clause License](LICENSE). The web interface
|
|
100
|
-
vendors [uPlot](https://github.com/leeoniya/uPlot)
|
|
101
|
-
|
|
100
|
+
vendors [uPlot](https://github.com/leeoniya/uPlot) and [three.js](https://github.com/mrdoob/three.js)
|
|
101
|
+
(both MIT licensed) under
|
|
102
102
|
`simview/static/lib/` so the viewer works fully offline — see the
|
|
103
103
|
[documentation](https://vlk-jan.github.io/simview/dev/architecture/#vendored-third-party-libraries)
|
|
104
104
|
for details. All third-party libraries used by SimView are permissively licensed
|
|
@@ -24,7 +24,7 @@ logging.getLogger(__name__).addHandler(logging.NullHandler())
|
|
|
24
24
|
# the import cost (and dependency requirement) when an authoring symbol is used.
|
|
25
25
|
_LAZY_EXPORTS = {
|
|
26
26
|
"SimulationScene": "simview.scene",
|
|
27
|
-
"ViewerHandle": "simview.
|
|
27
|
+
"ViewerHandle": "simview.server",
|
|
28
28
|
"SimViewBody": "simview.model",
|
|
29
29
|
"SimViewStaticObject": "simview.model",
|
|
30
30
|
"SimViewTerrain": "simview.model",
|
|
@@ -48,7 +48,8 @@ if TYPE_CHECKING:
|
|
|
48
48
|
SimViewStaticObject,
|
|
49
49
|
SimViewTerrain,
|
|
50
50
|
)
|
|
51
|
-
from simview.scene import SimulationScene
|
|
51
|
+
from simview.scene import SimulationScene
|
|
52
|
+
from simview.server import ViewerHandle
|
|
52
53
|
from simview.state import BodyTrajectory, SimViewBodyState
|
|
53
54
|
|
|
54
55
|
__all__ = [
|
|
@@ -4,11 +4,11 @@ import json
|
|
|
4
4
|
import logging
|
|
5
5
|
import shutil
|
|
6
6
|
import sys
|
|
7
|
-
import tempfile
|
|
8
7
|
from pathlib import Path
|
|
9
8
|
|
|
10
9
|
from simview import CACHE_DIR, __version__, remote
|
|
11
10
|
from simview.server import SimViewServer
|
|
11
|
+
from simview.utils import human_bytes, load_scene, load_scene_model
|
|
12
12
|
|
|
13
13
|
logger = logging.getLogger("simview.cli")
|
|
14
14
|
|
|
@@ -48,46 +48,25 @@ def _package_version() -> str:
|
|
|
48
48
|
|
|
49
49
|
|
|
50
50
|
def _dir_size(path: Path) -> int:
|
|
51
|
-
|
|
52
|
-
for entry in path.rglob("*"):
|
|
53
|
-
try:
|
|
54
|
-
if entry.is_file():
|
|
55
|
-
total += entry.stat().st_size
|
|
56
|
-
except OSError:
|
|
57
|
-
pass
|
|
58
|
-
return total
|
|
51
|
+
return sum(p.stat().st_size for p in path.rglob("*") if p.is_file())
|
|
59
52
|
|
|
60
53
|
|
|
61
54
|
def clear_cache():
|
|
62
|
-
"""Remove simview's on-disk cache
|
|
63
|
-
(see `simview.remote`),
|
|
55
|
+
"""Remove simview's on-disk cache of scene files fetched from remote hosts
|
|
56
|
+
(see `simview.remote`), including the default location when
|
|
57
|
+
$XDG_CACHE_HOME points elsewhere."""
|
|
64
58
|
freed = 0
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
remote.cache_dir(),
|
|
68
|
-
Path("/tmp") / CACHE_DIR,
|
|
69
|
-
Path.home() / ".cache" / CACHE_DIR,
|
|
59
|
+
for cache_dir in dict.fromkeys(
|
|
60
|
+
(remote.cache_dir(), Path.home() / ".cache" / CACHE_DIR)
|
|
70
61
|
):
|
|
71
|
-
if
|
|
62
|
+
if not cache_dir.is_dir():
|
|
72
63
|
continue
|
|
73
|
-
seen.add(cache_dir)
|
|
74
64
|
freed += _dir_size(cache_dir)
|
|
75
65
|
logger.info("Removing %s", cache_dir)
|
|
76
66
|
shutil.rmtree(cache_dir, ignore_errors=True)
|
|
77
67
|
|
|
78
|
-
# Temp scenes written by SimViewLauncher (tempfile.mkstemp with this prefix);
|
|
79
|
-
# these leak if a launched viewer is killed before cleanup runs.
|
|
80
|
-
removed = 0
|
|
81
|
-
for leftover in Path(tempfile.gettempdir()).glob("simview_viz_*.json"):
|
|
82
|
-
try:
|
|
83
|
-
leftover.unlink()
|
|
84
|
-
removed += 1
|
|
85
|
-
except OSError as e:
|
|
86
|
-
logger.warning("Could not remove %s: %s", leftover, e)
|
|
87
|
-
if removed:
|
|
88
|
-
logger.info("Removed %d leftover temporary scene file(s).", removed)
|
|
89
68
|
if freed:
|
|
90
|
-
logger.info("Freed %s.",
|
|
69
|
+
logger.info("Freed %s.", human_bytes(freed))
|
|
91
70
|
|
|
92
71
|
logger.info("Cache cleared.")
|
|
93
72
|
|
|
@@ -128,7 +107,7 @@ def run_terrain(path: Path, args: argparse.Namespace) -> None:
|
|
|
128
107
|
|
|
129
108
|
try:
|
|
130
109
|
if args.along_body is not None:
|
|
131
|
-
model_data, states_data =
|
|
110
|
+
model_data, states_data = load_scene(path)
|
|
132
111
|
if diff_mode:
|
|
133
112
|
batch_a, batch_b = args.batches
|
|
134
113
|
result = terrain_mod.query_along_body_diff(
|
|
@@ -154,7 +133,7 @@ def run_terrain(path: Path, args: argparse.Namespace) -> None:
|
|
|
154
133
|
text_fn = terrain_mod.format_along_text
|
|
155
134
|
csv_fn = terrain_mod.format_along_csv
|
|
156
135
|
else:
|
|
157
|
-
model_data =
|
|
136
|
+
model_data = load_scene_model(path)
|
|
158
137
|
if diff_mode:
|
|
159
138
|
batch_a, batch_b = args.batches
|
|
160
139
|
if args.point is not None:
|
|
@@ -226,7 +205,7 @@ def run_diff(path: Path, args: argparse.Namespace) -> None:
|
|
|
226
205
|
sys.exit(1)
|
|
227
206
|
|
|
228
207
|
try:
|
|
229
|
-
model_data, states_data =
|
|
208
|
+
model_data, states_data = load_scene(path)
|
|
230
209
|
result = diff_mod.compute_trajectory_diff(
|
|
231
210
|
model_data,
|
|
232
211
|
states_data,
|
|
@@ -366,6 +345,24 @@ def _add_json_csv_flags(sp: argparse.ArgumentParser) -> None:
|
|
|
366
345
|
fmt.add_argument("--csv", action="store_true", help="Print CSV instead of text.")
|
|
367
346
|
|
|
368
347
|
|
|
348
|
+
def _add_host_port_flags(sp: argparse.ArgumentParser) -> None:
|
|
349
|
+
sp.add_argument(
|
|
350
|
+
"--host",
|
|
351
|
+
type=str,
|
|
352
|
+
default="127.0.0.1",
|
|
353
|
+
help="Host/interface for the server to bind to (default: 127.0.0.1).",
|
|
354
|
+
)
|
|
355
|
+
sp.add_argument(
|
|
356
|
+
"--port",
|
|
357
|
+
type=int,
|
|
358
|
+
default=5420,
|
|
359
|
+
help=(
|
|
360
|
+
"Port for the server to use (default: 5420). If it's already taken, "
|
|
361
|
+
"the next free port is used instead."
|
|
362
|
+
),
|
|
363
|
+
)
|
|
364
|
+
|
|
365
|
+
|
|
369
366
|
def _add_file_arg(sp: argparse.ArgumentParser) -> None:
|
|
370
367
|
sp.add_argument(
|
|
371
368
|
"file",
|
|
@@ -406,21 +403,7 @@ def build_parser() -> argparse.ArgumentParser:
|
|
|
406
403
|
nargs="*",
|
|
407
404
|
help="Path(s) to simulation JSON file(s) to visualize.",
|
|
408
405
|
)
|
|
409
|
-
view
|
|
410
|
-
"--host",
|
|
411
|
-
type=str,
|
|
412
|
-
default="127.0.0.1",
|
|
413
|
-
help="Host/interface for the server to bind to (default: 127.0.0.1).",
|
|
414
|
-
)
|
|
415
|
-
view.add_argument(
|
|
416
|
-
"--port",
|
|
417
|
-
type=int,
|
|
418
|
-
default=5420,
|
|
419
|
-
help=(
|
|
420
|
-
"Port for the server to use (default: 5420). If it's already taken, "
|
|
421
|
-
"the next free port is used instead."
|
|
422
|
-
),
|
|
423
|
-
)
|
|
406
|
+
_add_host_port_flags(view)
|
|
424
407
|
view.add_argument(
|
|
425
408
|
"--no-browser",
|
|
426
409
|
action="store_true",
|
|
@@ -606,21 +589,7 @@ def build_parser() -> argparse.ArgumentParser:
|
|
|
606
589
|
metavar="PATH",
|
|
607
590
|
help="PNG file path to save the screenshot to. Required.",
|
|
608
591
|
)
|
|
609
|
-
render
|
|
610
|
-
"--host",
|
|
611
|
-
type=str,
|
|
612
|
-
default="127.0.0.1",
|
|
613
|
-
help="Host/interface for the server to bind to (default: 127.0.0.1).",
|
|
614
|
-
)
|
|
615
|
-
render.add_argument(
|
|
616
|
-
"--port",
|
|
617
|
-
type=int,
|
|
618
|
-
default=5420,
|
|
619
|
-
help=(
|
|
620
|
-
"Port for the server to use (default: 5420). If it's already taken, "
|
|
621
|
-
"the next free port is used instead."
|
|
622
|
-
),
|
|
623
|
-
)
|
|
592
|
+
_add_host_port_flags(render)
|
|
624
593
|
render.add_argument(
|
|
625
594
|
"--view",
|
|
626
595
|
type=str,
|
|
@@ -696,24 +665,14 @@ def main():
|
|
|
696
665
|
clear_cache()
|
|
697
666
|
return
|
|
698
667
|
|
|
699
|
-
|
|
700
|
-
path
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
return
|
|
708
|
-
|
|
709
|
-
if args.command == "diff":
|
|
710
|
-
path = _resolve_input(args.file, args)
|
|
711
|
-
run_diff(path, args)
|
|
712
|
-
return
|
|
713
|
-
|
|
714
|
-
if args.command == "render":
|
|
715
|
-
path = _resolve_input(args.file, args)
|
|
716
|
-
run_render(path, args)
|
|
668
|
+
single_file_commands = {
|
|
669
|
+
"info": lambda path, args: run_info(path, as_json=args.json),
|
|
670
|
+
"terrain": run_terrain,
|
|
671
|
+
"diff": run_diff,
|
|
672
|
+
"render": run_render,
|
|
673
|
+
}
|
|
674
|
+
if args.command in single_file_commands:
|
|
675
|
+
single_file_commands[args.command](_resolve_input(args.file, args), args)
|
|
717
676
|
return
|
|
718
677
|
|
|
719
678
|
# view mode: launch the viewer (or --save-merged) over one or more inputs.
|
|
@@ -81,13 +81,18 @@ def inline_blob(raw: bytes) -> str:
|
|
|
81
81
|
return BLOB_PREFIX + base64.b64encode(raw).decode()
|
|
82
82
|
|
|
83
83
|
|
|
84
|
+
def blob_bytes(value: str) -> bytes:
|
|
85
|
+
"""Raw bytes of one inline ``__b64__`` blob string."""
|
|
86
|
+
return base64.b64decode(value[len(BLOB_PREFIX) :])
|
|
87
|
+
|
|
88
|
+
|
|
84
89
|
def blob_floats(value: Any) -> list[float]:
|
|
85
90
|
"""Decode one ``__b64__`` blob (or pass through an already-plain nested
|
|
86
91
|
list, flattened) into a flat list of floats, without numpy."""
|
|
87
92
|
if isinstance(value, str):
|
|
88
93
|
if not value.startswith(BLOB_PREFIX):
|
|
89
94
|
raise ValueError(f"expected a {BLOB_PREFIX} blob, got {value[:32]!r}")
|
|
90
|
-
raw =
|
|
95
|
+
raw = blob_bytes(value)
|
|
91
96
|
return list(struct.unpack(f"<{len(raw) // 4}f", raw))
|
|
92
97
|
|
|
93
98
|
flat: list[float] = []
|
|
@@ -147,7 +152,7 @@ def _decode_state_field_rows(value, width: int, batch_size: int):
|
|
|
147
152
|
if isinstance(value, str):
|
|
148
153
|
if not value.startswith(BLOB_PREFIX):
|
|
149
154
|
raise StatesShapeMismatch(f"unexpected string value for field: {value!r}")
|
|
150
|
-
flat = np.frombuffer(
|
|
155
|
+
flat = np.frombuffer(blob_bytes(value), dtype="<f4")
|
|
151
156
|
else:
|
|
152
157
|
arr = np.asarray(value, dtype="<f4")
|
|
153
158
|
if arr.ndim == 1:
|
|
@@ -233,7 +238,7 @@ def columnarize_states(states_data: list, model_data: dict | None, register_blob
|
|
|
233
238
|
|
|
234
239
|
fields = sorted(k for k in body if k in STATE_FIELD_WIDTHS)
|
|
235
240
|
if key not in body_fields:
|
|
236
|
-
if state_idx != 0
|
|
241
|
+
if state_idx != 0:
|
|
237
242
|
# A body appearing for the first time after frame 0
|
|
238
243
|
# would leave earlier frames' rows undefined -- bail
|
|
239
244
|
# rather than guess a fill value.
|
|
@@ -396,7 +401,7 @@ def expand_columnar_states(states_doc: Any, batch_size: int) -> list[dict]:
|
|
|
396
401
|
for field, (flat, width) in fields.items():
|
|
397
402
|
start = t * B * width
|
|
398
403
|
chunk = flat[start : start + B * width]
|
|
399
|
-
entry[field] =
|
|
404
|
+
entry[field] = encode_floats(chunk)
|
|
400
405
|
if contacts is not None:
|
|
401
406
|
value = contacts[t] if t < len(contacts) else None
|
|
402
407
|
if value is not None:
|
|
@@ -16,13 +16,19 @@ truncation) for scripts/coding agents to consume directly, with
|
|
|
16
16
|
same data.
|
|
17
17
|
"""
|
|
18
18
|
|
|
19
|
-
import csv
|
|
20
|
-
import io
|
|
21
19
|
import math
|
|
22
20
|
|
|
23
21
|
from simview.columnar import body_key, decode_transform_row
|
|
24
|
-
from simview.utils import
|
|
25
|
-
|
|
22
|
+
from simview.utils import (
|
|
23
|
+
bodies_by_name,
|
|
24
|
+
body_label,
|
|
25
|
+
cap,
|
|
26
|
+
collect_body_names,
|
|
27
|
+
iter_names,
|
|
28
|
+
resolve_body,
|
|
29
|
+
series_stats,
|
|
30
|
+
write_csv,
|
|
31
|
+
)
|
|
26
32
|
|
|
27
33
|
_MAX_SERIES_ROWS = 10
|
|
28
34
|
|
|
@@ -115,19 +121,6 @@ def _compose(parent_row: list[float], local_row: list[float]) -> list[float]:
|
|
|
115
121
|
]
|
|
116
122
|
|
|
117
123
|
|
|
118
|
-
def _expand_raw_bodies(raw_bodies: list | None) -> dict:
|
|
119
|
-
"""`name -> entry` for one state's `bodies`, expanding grouped (list) name
|
|
120
|
-
entries so each individual body name maps to the shared entry."""
|
|
121
|
-
expanded: dict = {}
|
|
122
|
-
for entry in raw_bodies or []:
|
|
123
|
-
name = entry.get("name")
|
|
124
|
-
if name is None:
|
|
125
|
-
continue
|
|
126
|
-
for single in iter_names(name):
|
|
127
|
-
expanded[single] = entry
|
|
128
|
-
return expanded
|
|
129
|
-
|
|
130
|
-
|
|
131
124
|
def _resolve_frame(
|
|
132
125
|
meta: dict[str, dict],
|
|
133
126
|
topo_order: list[str],
|
|
@@ -192,12 +185,6 @@ def _resolve_batches(model_data: dict, batch_a: int, batch_b: int) -> int:
|
|
|
192
185
|
return batch_size
|
|
193
186
|
|
|
194
187
|
|
|
195
|
-
def _stats(values: list[float]) -> dict:
|
|
196
|
-
if not values:
|
|
197
|
-
return {"mean": None, "max": None, "final": None}
|
|
198
|
-
return {"mean": sum(values) / len(values), "max": max(values), "final": values[-1]}
|
|
199
|
-
|
|
200
|
-
|
|
201
188
|
def _first_exceeding(
|
|
202
189
|
frame_indices: list[int], values: list[float], threshold: float | None
|
|
203
190
|
) -> int | None:
|
|
@@ -250,18 +237,8 @@ def compute_trajectory_diff(
|
|
|
250
237
|
if every < 1:
|
|
251
238
|
raise ValueError(f"every must be >= 1; got {every}")
|
|
252
239
|
|
|
253
|
-
all_names
|
|
254
|
-
seen_keys =
|
|
255
|
-
for state in states_data:
|
|
256
|
-
for entry in state.get("bodies") or []:
|
|
257
|
-
name = entry.get("name")
|
|
258
|
-
if name is None:
|
|
259
|
-
continue
|
|
260
|
-
key = body_key(name)
|
|
261
|
-
if key not in seen_keys:
|
|
262
|
-
seen_keys.add(key)
|
|
263
|
-
all_names.append(name)
|
|
264
|
-
|
|
240
|
+
all_names = collect_body_names(states_data)
|
|
241
|
+
seen_keys = {body_key(name) for name in all_names}
|
|
265
242
|
if not all_names:
|
|
266
243
|
raise ValueError("no bodies found in the scene's states to diff")
|
|
267
244
|
|
|
@@ -296,7 +273,7 @@ def compute_trajectory_diff(
|
|
|
296
273
|
for idx, state in enumerate(states_data):
|
|
297
274
|
if idx % every != 0:
|
|
298
275
|
continue
|
|
299
|
-
raw_by_name =
|
|
276
|
+
raw_by_name = bodies_by_name(state.get("bodies"))
|
|
300
277
|
# Resolved once per frame for the whole scene rather than per body:
|
|
301
278
|
# a child's world pose needs its ancestors' poses anyway.
|
|
302
279
|
rows_a = _resolve_frame(meta, topo_order, raw_by_name, batch_size, batch_a)
|
|
@@ -318,41 +295,36 @@ def compute_trajectory_diff(
|
|
|
318
295
|
out["err_y"].append(row_a[1] - row_b[1])
|
|
319
296
|
out["err_z"].append(row_a[2] - row_b[2])
|
|
320
297
|
|
|
298
|
+
axes = ("err_x", "err_y", "err_z") if per_axis else ()
|
|
321
299
|
bodies_out = {}
|
|
322
300
|
for name in target_names:
|
|
323
301
|
out = series[body_key(name)]
|
|
324
|
-
label = body_label(name)
|
|
325
302
|
frame_indices = out["frame_indices"]
|
|
326
|
-
times = out["times"]
|
|
327
|
-
position_error = out["position_error"]
|
|
328
|
-
orientation_error_deg = out["orientation_error_deg"]
|
|
329
|
-
err_x, err_y, err_z = out["err_x"], out["err_y"], out["err_z"]
|
|
330
|
-
|
|
331
303
|
summary = {
|
|
332
304
|
"frame_count": len(frame_indices),
|
|
333
|
-
"position_error":
|
|
334
|
-
"orientation_error_deg":
|
|
305
|
+
"position_error": series_stats(out["position_error"]),
|
|
306
|
+
"orientation_error_deg": series_stats(out["orientation_error_deg"]),
|
|
335
307
|
"first_frame_exceeding_pos_threshold": _first_exceeding(
|
|
336
|
-
frame_indices, position_error, pos_threshold
|
|
308
|
+
frame_indices, out["position_error"], pos_threshold
|
|
337
309
|
),
|
|
338
310
|
"first_frame_exceeding_rot_threshold": _first_exceeding(
|
|
339
|
-
frame_indices, orientation_error_deg, rot_threshold_deg
|
|
311
|
+
frame_indices, out["orientation_error_deg"], rot_threshold_deg
|
|
340
312
|
),
|
|
341
313
|
}
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
314
|
+
body_out = {
|
|
315
|
+
key: out[key]
|
|
316
|
+
for key in (
|
|
317
|
+
"frame_indices",
|
|
318
|
+
"times",
|
|
319
|
+
"position_error",
|
|
320
|
+
"orientation_error_deg",
|
|
321
|
+
)
|
|
348
322
|
}
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
summary["err_y"] = _stats(err_y)
|
|
355
|
-
summary["err_z"] = _stats(err_z)
|
|
323
|
+
body_out["summary"] = summary
|
|
324
|
+
for axis in axes:
|
|
325
|
+
body_out[axis] = out[axis]
|
|
326
|
+
summary[axis] = series_stats(out[axis])
|
|
327
|
+
bodies_out[body_label(name)] = body_out
|
|
356
328
|
|
|
357
329
|
return {
|
|
358
330
|
"batch_a": batch_a,
|
|
@@ -438,22 +410,16 @@ def format_diff_csv(result: dict) -> str:
|
|
|
438
410
|
(body, frame), full series (no truncation) -- CSV output is for scripts,
|
|
439
411
|
matching the "just the numbers, in full" philosophy `--json` already
|
|
440
412
|
uses everywhere in this CLI."""
|
|
441
|
-
|
|
442
|
-
buf = io.StringIO()
|
|
443
|
-
writer = csv.writer(buf)
|
|
413
|
+
keys = ["frame_indices", "times", "position_error", "orientation_error_deg"]
|
|
444
414
|
header = ["body", "frame", "time", "position_error", "orientation_error_deg"]
|
|
445
|
-
if per_axis:
|
|
415
|
+
if result.get("per_axis"):
|
|
416
|
+
keys += ["err_x", "err_y", "err_z"]
|
|
446
417
|
header += ["err_x", "err_y", "err_z"]
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
body["
|
|
452
|
-
body[
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
if per_axis:
|
|
456
|
-
columns += [body["err_x"], body["err_y"], body["err_z"]]
|
|
457
|
-
for row in zip(*columns):
|
|
458
|
-
writer.writerow([label, *row])
|
|
459
|
-
return buf.getvalue()
|
|
418
|
+
return write_csv(
|
|
419
|
+
header,
|
|
420
|
+
(
|
|
421
|
+
[label, *row]
|
|
422
|
+
for label, body in result["bodies"].items()
|
|
423
|
+
for row in zip(*(body[k] for k in keys))
|
|
424
|
+
),
|
|
425
|
+
)
|
|
@@ -12,14 +12,14 @@ inspection tool. Shares its blob-decoding/body-label helpers with
|
|
|
12
12
|
which are stdlib-only on this read path.
|
|
13
13
|
"""
|
|
14
14
|
|
|
15
|
-
import base64
|
|
16
15
|
import json
|
|
17
16
|
from pathlib import Path
|
|
18
17
|
from typing import Any
|
|
19
18
|
|
|
20
19
|
from simview.columnar import (
|
|
21
|
-
BLOB_PREFIX,
|
|
22
20
|
STATE_FIELD_WIDTHS,
|
|
21
|
+
blob_bytes,
|
|
22
|
+
body_key,
|
|
23
23
|
expand_columnar_states,
|
|
24
24
|
is_blob,
|
|
25
25
|
is_columnar,
|
|
@@ -33,7 +33,7 @@ _LARGE_FILE_BYTES = 100_000_000
|
|
|
33
33
|
def _blob_byte_length(value: Any) -> int | None:
|
|
34
34
|
"""Decoded byte length if `value` is a `__b64__` blob string, else None."""
|
|
35
35
|
if is_blob(value):
|
|
36
|
-
return len(
|
|
36
|
+
return len(blob_bytes(value))
|
|
37
37
|
return None
|
|
38
38
|
|
|
39
39
|
|
|
@@ -230,7 +230,7 @@ def _summarize_states(states, model: dict | None, warnings: list[str]) -> dict:
|
|
|
230
230
|
reasons.append(f"state {idx} has a body entry missing 'name'")
|
|
231
231
|
continue
|
|
232
232
|
name = body["name"]
|
|
233
|
-
key =
|
|
233
|
+
key = body_key(name)
|
|
234
234
|
if key in seen_keys:
|
|
235
235
|
reasons.append(f"state {idx} lists body '{name}' more than once")
|
|
236
236
|
seen_keys.add(key)
|
|
@@ -25,14 +25,10 @@ class SimViewLauncher:
|
|
|
25
25
|
self._sim_file_path: Path | None = None
|
|
26
26
|
|
|
27
27
|
if isinstance(source, SimulationScene):
|
|
28
|
-
if
|
|
29
|
-
source.model is None
|
|
30
|
-
or not source.model.is_complete
|
|
31
|
-
or source.states is None
|
|
32
|
-
):
|
|
28
|
+
if not source.model.is_complete:
|
|
33
29
|
raise ValueError(
|
|
34
30
|
"Cannot initialize visualizer: The provided SimulationScene "
|
|
35
|
-
"is incomplete
|
|
31
|
+
"is incomplete (e.g. terrain might be missing)."
|
|
36
32
|
)
|
|
37
33
|
self._scene = source
|
|
38
34
|
elif isinstance(source, (str, Path)):
|
|
@@ -64,14 +60,7 @@ class SimViewLauncher:
|
|
|
64
60
|
"states": self._scene.states,
|
|
65
61
|
}
|
|
66
62
|
server = SimViewServer(data=data)
|
|
67
|
-
port
|
|
68
|
-
if port != preferred_port:
|
|
69
|
-
logger.warning(
|
|
70
|
-
"Preferred port %s is not available. Using port %s instead.",
|
|
71
|
-
preferred_port,
|
|
72
|
-
port,
|
|
73
|
-
)
|
|
74
|
-
server.run(host=host, port=port)
|
|
63
|
+
server.run(host=host, port=find_free_port(host, preferred_port))
|
|
75
64
|
else:
|
|
76
65
|
# __init__ guarantees exactly one of self._scene / self._sim_file_path
|
|
77
66
|
# is set (it raises otherwise), so if self._scene is None here,
|