[{"data":1,"prerenderedAt":24},["ShallowReactive",2],{"se-doc-modify-scene":3},{"html":4,"toc":5},"\u003Ch1>Modify a scene or behavior\u003C/h1>\n\u003Cp>This skill ships with the SimEngine \u003Ccode>first_scene\u003C/code> example and drives only\npublic tools: \u003Ccode>simengine_host\u003C/code> (scenario CLI), \u003Ccode>simengine_capture\u003C/code> (offscreen render)\nand \u003Ccode>examples/first_scene/first_scene.py\u003C/code> (the example driver). It assumes a project\ncreated with \u003Ccode>simengine-create-project\u003C/code>.\u003C/p>\n\u003Ch2 id=\"compatible-versions\">Compatible versions\u003C/h2>\n\u003Cp>Scenario schema \u003Ccode>simengine.scenario\u003C/code> \u003Cstrong>schema_version 1\u003C/strong>; capability document 1;\nscene state 1; simulation contract 1; module contract 1; scene/asset text formats\n\u003Ccode>simengine_scene 1\u003C/code> / \u003Ccode>simengine_asset 1\u003C/code>; capture manifest 1; example driver 1 and\n\u003Ccode>simengine.example_project\u003C/code> 1. The driver checks all of them (\u003Ccode>incompatible_engine\u003C/code>,\nexit 21, on a mismatch). The authoritative field list is\n\u003Ccode>simengine_host --capabilities\u003C/code> → \u003Ccode>capabilities.scenario_schema\u003C/code>; the scene and asset\nformats are documented in \u003Ccode>fixtures/README.md\u003C/code> of the SimEngine checkout.\u003C/p>\n\u003Ch2 id=\"how-a-project-fits-together\">How a project fits together\u003C/h2>\n\u003Ctable>\n\u003Cthead>\n\u003Ctr>\n\u003Cth>File\u003C/th>\n\u003Cth>Owns\u003C/th>\n\u003Cth>Notes\u003C/th>\n\u003C/tr>\n\u003C/thead>\n\u003Ctbody>\n\u003Ctr>\n\u003Ctd>\u003Ccode>scenario.json\u003C/code>\u003C/td>\n\u003Ctd>simulation: entities, seed, ticks, scheduled commands, expectations\u003C/td>\n\u003Ctd>validated all-or-nothing by \u003Ccode>simengine_host --load\u003C/code>\u003C/td>\n\u003C/tr>\n\u003Ctr>\n\u003Ctd>\u003Ccode>scene.sescene\u003C/code>\u003C/td>\n\u003Ctd>presentation: which asset each object uses, material, scale, camera, sun\u003C/td>\n\u003Ctd>validated by \u003Ccode>simengine_capture --check-scene\u003C/code>\u003C/td>\n\u003C/tr>\n\u003Ctr>\n\u003Ctd>\u003Ccode>project.json\u003C/code>\u003C/td>\n\u003Ctd>which scene and scenarios, viewpoints, capture size\u003C/td>\n\u003Ctd>read by the driver only\u003C/td>\n\u003C/tr>\n\u003Ctr>\n\u003Ctd>\u003Ccode>assets/*.seasset\u003C/code>\u003C/td>\n\u003Ctd>meshes and materials (text, meters, +Y up)\u003C/td>\n\u003Ctd>each file records its license and tool\u003C/td>\n\u003C/tr>\n\u003C/tbody>\n\u003C/table>\n\u003Cp>The rule that binds them: \u003Cstrong>every scenario entity needs a scene instance with exactly the\nsame name.\u003C/strong> When the driver poses the scene, each such instance takes the entity’s\nposition and yaw from the simulation state; instances without an entity (the ground)\nstay where they are authored. Generated entities are named \u003Ccode>id_prefix\u003C/code> + an index\nzero-padded to the width of \u003Ccode>count - 1\u003C/code> (\u003Ccode>barrel_0\u003C/code> … \u003Ccode>barrel_2\u003C/code> for count 3,\n\u003Ccode>crate_00\u003C/code> … for count 11 or more).\u003C/p>\n\u003Cp>Units and frame: meters, one Cartesian frame, right-handed, \u003Ccode>up_axis &quot;+y&quot;\u003C/code> (the scene\nconvention; the driver refuses any other). Orientations are quaternions \u003Ccode>[x, y, z, w]\u003C/code>\nthat must be pure yaw (rotation about +Y): \u003Ccode>[0, sin(a/2), 0, cos(a/2)]\u003C/code>.\u003C/p>\n\u003Cp>Placement reference (asset origins): \u003Ccode>crate\u003C/code> is a 0.5 m cube with its origin at the\ncenter of its base (on the ground: y = 0; on another crate: y = 0.5); \u003Ccode>spheres\u003C/code>\n(mesh \u003Ccode>sphere_r0p25\u003C/code>) has its origin at the center (on the ground: y = 0.25; on the\ntable: y = 1.0); \u003Ccode>barrel\u003C/code> (r 0.3 m, h 0.8 m) and \u003Ccode>table\u003C/code> (top at y = 0.75 m,\n1.2 m × 0.8 m) have their origin on the floor. Sphere materials: \u003Ccode>dielectric_rough\u003C/code>,\n\u003Ccode>dielectric_smooth\u003C/code>, \u003Ccode>metal_rough\u003C/code>, \u003Ccode>metal_smooth\u003C/code>.\u003C/p>\n\u003Cp>Motion in a core-only build is \u003Ccode>simengine.entity.set_position\u003C/code> at a tick (a teleport,\napplied at the start of that tick, before systems, in document order). There is no\nvelocity, interpolation, collision or rotation command. Expectations compare the state\nat the end of the run, component-wise, within \u003Ccode>tolerance\u003C/code>.\u003C/p>\n\u003Ch2 id=\"variables\">Variables\u003C/h2>\n\u003Cpre class=\"code\" data-lang=\"text\">\u003Cspan class=\"code__bar\">\u003Cspan class=\"code__lang\">text\u003C/span>\u003Cbutton type=\"button\" class=\"code__copy\" data-copy>Copy\u003C/button>\u003C/span>\u003Ccode>\u003Cspan class=\"tk-cmd\">SIMENGINE_ROOT=/absolute/path/to/SimEngine\u003C/span>\n\u003Cspan class=\"tk-cmd\">SIMENGINE_BUILD=$SIMENGINE_ROOT/build/linux-release\u003C/span>\n\u003Cspan class=\"tk-cmd\">PROJECT=/absolute/path/to/my_first_scene\u003C/span>\u003C/code>\u003C/pre>\n\u003Cp>Prefix each command with them if your shell tool does not keep variables between calls.\u003C/p>\n\u003Ch2 id=\"steps\">Steps\u003C/h2>\n\u003Col>\n\u003Cli>Record the baseline. Run it even if an earlier \u003Ccode>run\u003C/code> already passed: step 5 compares\nagainst \u003Ccode>runs/before.json\u003C/code>, which only this command writes (a \u003Ccode>check\u003C/code> result has no\ndigest or captures and is not a baseline).\u003C/li>\n\u003C/ol>\n\u003Cpre class=\"code\" data-lang=\"shell\">\u003Cspan class=\"code__bar\">\u003Cspan class=\"code__lang\">shell\u003C/span>\u003Cbutton type=\"button\" class=\"code__copy\" data-copy>Copy\u003C/button>\u003C/span>\u003Ccode>\u003Cspan class=\"tk-cmd\">mkdir\u003C/span> \u003Cspan class=\"tk-flag\">-p\u003C/span> \u003Cspan class=\"tk-str\">\"$PROJECT/runs\"\u003C/span>\n\u003Cspan class=\"tk-cmd\">python3\u003C/span> \u003Cspan class=\"tk-str\">\"$SIMENGINE_ROOT/examples/first_scene/first_scene.py\"\u003C/span> run \u003Cspan class=\"tk-flag\">--project\u003C/span> \u003Cspan class=\"tk-str\">\"$PROJECT\"\u003C/span> \u003Cspan class=\"tk-flag\">--build\u003C/span> \u003Cspan class=\"tk-str\">\"$SIMENGINE_BUILD\"\u003C/span> \u003Cspan class=\"tk-punc\">&gt;\u003C/span> \u003Cspan class=\"tk-str\">\"$PROJECT/runs/before.json\"\u003C/span>\u003C/code>\u003C/pre>\n\u003Col start=\"2\">\n\u003Cli>\n\u003Cp>Make the change in both files. Worked example — add a third crate that starts on the\nground and is stacked on top of the other two at tick 100:\u003C/p>\n\u003Cul>\n\u003Cli>\u003Ccode>scenario.json\u003C/code>, append to \u003Ccode>entities\u003C/code>:\n\u003Ccode>{&quot;id&quot;: &quot;crate_c&quot;, &quot;position&quot;: {&quot;value&quot;: [-1.2, 0, 0.9], &quot;unit&quot;: &quot;m&quot;, &quot;frame&quot;: &quot;world&quot;}}\u003C/code>\u003C/li>\n\u003Cli>append to \u003Ccode>commands\u003C/code>:\n\u003Ccode>{&quot;at_tick&quot;: 100, &quot;command&quot;: &quot;simengine.entity.set_position&quot;, &quot;version&quot;: 1, &quot;args&quot;: {&quot;entity&quot;: &quot;crate_c&quot;, &quot;position&quot;: {&quot;value&quot;: [-2, 1, -0.5], &quot;unit&quot;: &quot;m&quot;, &quot;frame&quot;: &quot;world&quot;}}}\u003C/code>\u003C/li>\n\u003Cli>append to \u003Ccode>expect\u003C/code>:\n\u003Ccode>{&quot;name&quot;: &quot;crate_c_on_top&quot;, &quot;entity&quot;: &quot;crate_c&quot;, &quot;quantity&quot;: &quot;position&quot;, &quot;value&quot;: {&quot;value&quot;: [-2, 1, -0.5], &quot;unit&quot;: &quot;m&quot;, &quot;frame&quot;: &quot;world&quot;}, &quot;tolerance&quot;: {&quot;value&quot;: 0, &quot;unit&quot;: &quot;m&quot;}}\u003C/code>\u003C/li>\n\u003Cli>\u003Ccode>scene.sescene\u003C/code>, after the other crates:\n\u003Ccode>instance crate_c crate * position -1.2 0 0.9\u003C/code>\u003C/li>\n\u003C/ul>\n\u003Cp>Make these edits with your editor. The block below applies exactly the same edit\n(the example’s automated test runs it):\u003C/p>\n\u003C/li>\n\u003C/ol>\n\u003Cpre class=\"code\" data-lang=\"shell\">\u003Cspan class=\"code__bar\">\u003Cspan class=\"code__lang\">shell\u003C/span>\u003Cbutton type=\"button\" class=\"code__copy\" data-copy>Copy\u003C/button>\u003C/span>\u003Ccode>\u003Cspan class=\"tk-cmd\">python3\u003C/span> - \u003Cspan class=\"tk-str\">\"$PROJECT\"\u003C/span> \u003Cspan class=\"tk-punc\">&lt;\u003C/span>\u003Cspan class=\"tk-punc\">&lt;\u003C/span>\u003Cspan class=\"tk-str\">'EOF'\u003C/span>\n\u003Cspan class=\"tk-cmd\">import\u003C/span> json, pathlib, sys\n\u003Cspan class=\"tk-cmd\">project\u003C/span> = pathlib.Path(sys.argv[1])\n\u003Cspan class=\"tk-cmd\">scenario_path\u003C/span> = project / \u003Cspan class=\"tk-str\">\"scenario.json\"\u003C/span>\n\u003Cspan class=\"tk-cmd\">scenario\u003C/span> = json.loads(scenario_path.read_text(encoding=\u003Cspan class=\"tk-str\">\"utf-8\"\u003C/span>))\n\u003Cspan class=\"tk-cmd\">pos\u003C/span> = lambda v: {\u003Cspan class=\"tk-str\">\"value\"\u003C/span>: v, \u003Cspan class=\"tk-str\">\"unit\"\u003C/span>: \u003Cspan class=\"tk-str\">\"m\"\u003C/span>, \u003Cspan class=\"tk-str\">\"frame\"\u003C/span>: \u003Cspan class=\"tk-str\">\"world\"\u003C/span>}\n\u003Cspan class=\"tk-cmd\">scenario[\"entities\"].append({\"id\":\u003C/span> \u003Cspan class=\"tk-str\">\"crate_c\"\u003C/span>, \u003Cspan class=\"tk-str\">\"position\"\u003C/span>: pos([-1.2, 0, 0.9])})\n\u003Cspan class=\"tk-cmd\">scenario[\"commands\"].append({\"at_tick\":\u003C/span> 100, \u003Cspan class=\"tk-str\">\"command\"\u003C/span>: \u003Cspan class=\"tk-str\">\"simengine.entity.set_position\"\u003C/span>, \u003Cspan class=\"tk-str\">\"version\"\u003C/span>: 1,\n                             \u003Cspan class=\"tk-cmd\">\"args\":\u003C/span> {\u003Cspan class=\"tk-str\">\"entity\"\u003C/span>: \u003Cspan class=\"tk-str\">\"crate_c\"\u003C/span>, \u003Cspan class=\"tk-str\">\"position\"\u003C/span>: pos([-2, 1, -0.5])}})\n\u003Cspan class=\"tk-cmd\">scenario[\"expect\"].append({\"name\":\u003C/span> \u003Cspan class=\"tk-str\">\"crate_c_on_top\"\u003C/span>, \u003Cspan class=\"tk-str\">\"entity\"\u003C/span>: \u003Cspan class=\"tk-str\">\"crate_c\"\u003C/span>, \u003Cspan class=\"tk-str\">\"quantity\"\u003C/span>: \u003Cspan class=\"tk-str\">\"position\"\u003C/span>,\n                           \u003Cspan class=\"tk-cmd\">\"value\":\u003C/span> pos([-2, 1, -0.5]), \u003Cspan class=\"tk-str\">\"tolerance\"\u003C/span>: {\u003Cspan class=\"tk-str\">\"value\"\u003C/span>: 0, \u003Cspan class=\"tk-str\">\"unit\"\u003C/span>: \u003Cspan class=\"tk-str\">\"m\"\u003C/span>}})\n\u003Cspan class=\"tk-cmd\">scenario_path.write_text(json.dumps(scenario,\u003C/span> indent=2) + \u003Cspan class=\"tk-str\">\"\\n\"\u003C/span>, encoding=\u003Cspan class=\"tk-str\">\"utf-8\"\u003C/span>)\n\u003Cspan class=\"tk-cmd\">scene_path\u003C/span> = project / \u003Cspan class=\"tk-str\">\"scene.sescene\"\u003C/span>\n\u003Cspan class=\"tk-cmd\">lines\u003C/span> = scene_path.read_text(encoding=\u003Cspan class=\"tk-str\">\"utf-8\"\u003C/span>).splitlines()\n\u003Cspan class=\"tk-cmd\">at\u003C/span> = max(i for i, line in enumerate(lines) if line.startswith(\u003Cspan class=\"tk-str\">\"instance crate_\"\u003C/span>))\n\u003Cspan class=\"tk-cmd\">lines.insert(at\u003C/span> + 1, \u003Cspan class=\"tk-str\">\"instance crate_c crate * position -1.2 0 0.9\"\u003C/span>)\n\u003Cspan class=\"tk-cmd\">scene_path.write_text(\"\\n\".join(lines)\u003C/span> + \u003Cspan class=\"tk-str\">\"\\n\"\u003C/span>, encoding=\u003Cspan class=\"tk-str\">\"utf-8\"\u003C/span>)\n\u003Cspan class=\"tk-cmd\">EOF\u003C/span>\u003C/code>\u003C/pre>\n\u003Col start=\"3\">\n\u003Cli>Check (no GPU). A mistake shows up here as \u003Ccode>scenario_invalid\u003C/code> (23) with a JSON\npointer per error, or \u003Ccode>scene_invalid\u003C/code> (24) with file and line. Fix and repeat.\u003C/li>\n\u003C/ol>\n\u003Cpre class=\"code\" data-lang=\"shell\">\u003Cspan class=\"code__bar\">\u003Cspan class=\"code__lang\">shell\u003C/span>\u003Cbutton type=\"button\" class=\"code__copy\" data-copy>Copy\u003C/button>\u003C/span>\u003Ccode>\u003Cspan class=\"tk-cmd\">python3\u003C/span> \u003Cspan class=\"tk-str\">\"$SIMENGINE_ROOT/examples/first_scene/first_scene.py\"\u003C/span> check \u003Cspan class=\"tk-flag\">--project\u003C/span> \u003Cspan class=\"tk-str\">\"$PROJECT\"\u003C/span> \u003Cspan class=\"tk-flag\">--build\u003C/span> \u003Cspan class=\"tk-str\">\"$SIMENGINE_BUILD\"\u003C/span>\u003C/code>\u003C/pre>\n\u003Col start=\"4\">\n\u003Cli>Run, capture and verify the changed project.\u003C/li>\n\u003C/ol>\n\u003Cpre class=\"code\" data-lang=\"shell\">\u003Cspan class=\"code__bar\">\u003Cspan class=\"code__lang\">shell\u003C/span>\u003Cbutton type=\"button\" class=\"code__copy\" data-copy>Copy\u003C/button>\u003C/span>\u003Ccode>\u003Cspan class=\"tk-cmd\">python3\u003C/span> \u003Cspan class=\"tk-str\">\"$SIMENGINE_ROOT/examples/first_scene/first_scene.py\"\u003C/span> run \u003Cspan class=\"tk-flag\">--project\u003C/span> \u003Cspan class=\"tk-str\">\"$PROJECT\"\u003C/span> \u003Cspan class=\"tk-flag\">--build\u003C/span> \u003Cspan class=\"tk-str\">\"$SIMENGINE_BUILD\"\u003C/span> \u003Cspan class=\"tk-punc\">&gt;\u003C/span> \u003Cspan class=\"tk-str\">\"$PROJECT/runs/after.json\"\u003C/span>\n\u003Cspan class=\"tk-cmd\">python3\u003C/span> \u003Cspan class=\"tk-str\">\"$SIMENGINE_ROOT/examples/first_scene/first_scene.py\"\u003C/span> verify \u003Cspan class=\"tk-flag\">--project\u003C/span> \u003Cspan class=\"tk-str\">\"$PROJECT\"\u003C/span>\u003C/code>\u003C/pre>\n\u003Col start=\"5\">\n\u003Cli>Prove the change: the state digest changed, the new expectation is evaluated and\npassed, and the images exist. Then open the new \u003Ccode>final-front\u003C/code> PNG and look at it.\u003C/li>\n\u003C/ol>\n\u003Cpre class=\"code\" data-lang=\"shell\">\u003Cspan class=\"code__bar\">\u003Cspan class=\"code__lang\">shell\u003C/span>\u003Cbutton type=\"button\" class=\"code__copy\" data-copy>Copy\u003C/button>\u003C/span>\u003Ccode>\u003Cspan class=\"tk-cmd\">python3\u003C/span> - \u003Cspan class=\"tk-str\">\"$PROJECT/runs/before.json\"\u003C/span> \u003Cspan class=\"tk-str\">\"$PROJECT/runs/after.json\"\u003C/span> \u003Cspan class=\"tk-punc\">&lt;\u003C/span>\u003Cspan class=\"tk-punc\">&lt;\u003C/span>\u003Cspan class=\"tk-str\">'EOF'\u003C/span>\n\u003Cspan class=\"tk-cmd\">import\u003C/span> json, sys\n\u003Cspan class=\"tk-cmd\">before,\u003C/span> after = (json.load(open(p, encoding=\u003Cspan class=\"tk-str\">\"utf-8\"\u003C/span>)) for p in sys.argv[1:3])\n\u003Cspan class=\"tk-cmd\">assert\u003C/span> before[\u003Cspan class=\"tk-str\">\"outcome\"\u003C/span>] == \u003Cspan class=\"tk-str\">\"PASS\"\u003C/span> and after[\u003Cspan class=\"tk-str\">\"outcome\"\u003C/span>] == \u003Cspan class=\"tk-str\">\"PASS\"\u003C/span>, (before[\u003Cspan class=\"tk-str\">\"failure\"\u003C/span>], after[\u003Cspan class=\"tk-str\">\"failure\"\u003C/span>])\n\u003Cspan class=\"tk-cmd\">assert\u003C/span> after[\u003Cspan class=\"tk-str\">\"final_state_sha256\"\u003C/span>] != before[\u003Cspan class=\"tk-str\">\"final_state_sha256\"\u003C/span>], \u003Cspan class=\"tk-str\">\"the simulation state did not change\"\u003C/span>\n\u003Cspan class=\"tk-cmd\">assert\u003C/span> after[\u003Cspan class=\"tk-str\">\"expectations\"\u003C/span>][\u003Cspan class=\"tk-str\">\"failed\"\u003C/span>] == 0 and after[\u003Cspan class=\"tk-str\">\"expectations\"\u003C/span>][\u003Cspan class=\"tk-str\">\"passed\"\u003C/span>] == before[\u003Cspan class=\"tk-str\">\"expectations\"\u003C/span>][\u003Cspan class=\"tk-str\">\"passed\"\u003C/span>] + 1\n\u003Cspan class=\"tk-cmd\">print(\"changed:\",\u003C/span> before[\u003Cspan class=\"tk-str\">\"final_state_sha256\"\u003C/span>][:12], \u003Cspan class=\"tk-str\">\"-&gt;\"\u003C/span>, after[\u003Cspan class=\"tk-str\">\"final_state_sha256\"\u003C/span>][:12],\n      \u003Cspan class=\"tk-cmd\">\"\u003C/span>\u003Cspan class=\"tk-punc\">|\u003C/span> expectations\u003Cspan class=\"tk-str\">\", after[\"\u003C/span>expectations\u003Cspan class=\"tk-str\">\"], \"\u003C/span>\u003Cspan class=\"tk-punc\">|\u003C/span> images\u003Cspan class=\"tk-str\">\", [c[\"\u003C/span>png\u003Cspan class=\"tk-str\">\"] for c in after[\"\u003C/span>captures\"]])\n\u003Cspan class=\"tk-cmd\">EOF\u003C/span>\u003C/code>\u003C/pre>\n\u003Cp>A presentation-only change (a material, the camera, \u003Ccode>project.json\u003C/code> viewpoints) leaves\n\u003Ccode>final_state_sha256\u003C/code> unchanged and changes the captured pixels (\u003Ccode>pixels_sha256\u003C/code>);\ncheck that instead.\u003C/p>\n\u003Ch2 id=\"behavior-with-velocity-and-gravity-the-point-mass-variant\">Behavior with velocity and gravity: the \u003Ccode>point_mass\u003C/code> variant\u003C/h2>\n\u003Cp>\u003Ccode>toss.scenario.json\u003C/code> tosses the ball under gravity with an impulse, using the optional\n\u003Ccode>point_mass\u003C/code> test module (point kinematics, semi-implicit Euler; no collisions, so a\nbody falls through the ground if you run long enough). It needs a build that compiles\nthe module in; a core-only build stops with \u003Ccode>module_missing\u003C/code> (22):\u003C/p>\n\u003Cpre class=\"code\" data-lang=\"text\">\u003Cspan class=\"code__bar\">\u003Cspan class=\"code__lang\">text\u003C/span>\u003Cbutton type=\"button\" class=\"code__copy\" data-copy>Copy\u003C/button>\u003C/span>\u003Ccode>\u003Cspan class=\"tk-cmd\">cmake\u003C/span> \u003Cspan class=\"tk-flag\">--preset\u003C/span> linux-release \u003Cspan class=\"tk-flag\">-B\u003C/span> \u003Cspan class=\"tk-str\">\"$SIMENGINE_ROOT/build/linux-release-point_mass\"\u003C/span> \u003Cspan class=\"tk-flag\">-DSIMENGINE_MODULES\u003C/span>=point_mass\n\u003Cspan class=\"tk-cmd\">cmake\u003C/span> \u003Cspan class=\"tk-flag\">--build\u003C/span> \u003Cspan class=\"tk-str\">\"$SIMENGINE_ROOT/build/linux-release-point_mass\"\u003C/span>\n\u003Cspan class=\"tk-cmd\">SIMENGINE_BUILD_POINT_MASS=$SIMENGINE_ROOT/build/linux-release-point_mass\u003C/span>\u003C/code>\u003C/pre>\n\u003Cpre class=\"code\" data-lang=\"shell\">\u003Cspan class=\"code__bar\">\u003Cspan class=\"code__lang\">shell\u003C/span>\u003Cbutton type=\"button\" class=\"code__copy\" data-copy>Copy\u003C/button>\u003C/span>\u003Ccode>\u003Cspan class=\"tk-cmd\">python3\u003C/span> \u003Cspan class=\"tk-str\">\"$SIMENGINE_ROOT/examples/first_scene/first_scene.py\"\u003C/span> run \u003Cspan class=\"tk-flag\">--project\u003C/span> \u003Cspan class=\"tk-str\">\"$PROJECT\"\u003C/span> \u003Cspan class=\"tk-flag\">--build\u003C/span> \u003Cspan class=\"tk-str\">\"$SIMENGINE_BUILD_POINT_MASS\"\u003C/span> \u003Cspan class=\"tk-flag\">--scenario\u003C/span> toss\n\u003Cspan class=\"tk-cmd\">python3\u003C/span> \u003Cspan class=\"tk-str\">\"$SIMENGINE_ROOT/examples/first_scene/first_scene.py\"\u003C/span> verify \u003Cspan class=\"tk-flag\">--project\u003C/span> \u003Cspan class=\"tk-str\">\"$PROJECT\"\u003C/span> \u003Cspan class=\"tk-flag\">--scenario\u003C/span> toss\u003C/code>\u003C/pre>\n\u003Cp>Its components and commands (\u003Ccode>point_mass.body\u003C/code>, \u003Ccode>point_mass.world\u003C/code>,\n\u003Ccode>point_mass.apply_impulse\u003C/code>, \u003Ccode>point_mass.set_velocity\u003C/code>) are listed by \u003Ccode>--capabilities\u003C/code>\nof that build only. Expected values for its expectations follow the closed form of\nsemi-implicit Euler: after n ticks of duration dt, v = v0 + n·g·dt and\nx = x0 + n·v0·dt + g·dt²·n(n+1)/2 (plus impulse/mass from the tick it is applied).\u003C/p>\n\u003Ch2 id=\"on-failure\">On failure\u003C/h2>\n\u003Ctable>\n\u003Cthead>\n\u003Ctr>\n\u003Cth>Exit\u003C/th>\n\u003Cth>\u003Ccode>failure.code\u003C/code>\u003C/th>\n\u003Cth>Do this\u003C/th>\n\u003C/tr>\n\u003C/thead>\n\u003Ctbody>\n\u003Ctr>\n\u003Ctd>23\u003C/td>\n\u003Ctd>\u003Ccode>scenario_invalid\u003C/code>\u003C/td>\n\u003Ctd>For each \u003Ccode>failure.detail.errors[]\u003C/code>: open the scenario at \u003Ccode>line\u003C/code>/\u003Ccode>column\u003C/code>, fix the field at \u003Ccode>path\u003C/code> (\u003Ccode>code\u003C/code> says what: \u003Ccode>unit_mismatch\u003C/code>, \u003Ccode>unknown_entity\u003C/code>, \u003Ccode>unknown_command\u003C/code>, \u003Ccode>unknown_component\u003C/code>, \u003Ccode>non_normalized_orientation\u003C/code>, …; \u003Ccode>expected\u003C/code>/\u003Ccode>found\u003C/code> give the values). Nothing ran.\u003C/td>\n\u003C/tr>\n\u003Ctr>\n\u003Ctd>24\u003C/td>\n\u003Ctd>\u003Ccode>scene_invalid\u003C/code>\u003C/td>\n\u003Ctd>Fix the line in \u003Ccode>failure.detail\u003C/code> (\u003Ccode>code\u003C/code>, \u003Ccode>file\u003C/code>, \u003Ccode>line\u003C/code>): e.g. \u003Ccode>unknown_mesh\u003C/code>, \u003Ccode>syntax_error\u003C/code>, \u003Ccode>invalid_scene\u003C/code>.\u003C/td>\n\u003C/tr>\n\u003Ctr>\n\u003Ctd>25\u003C/td>\n\u003Ctd>\u003Ccode>pose_mapping_failed\u003C/code>\u003C/td>\n\u003Ctd>Add the missing scene instances listed in \u003Ccode>failure.detail.entities_without_instance\u003C/code> (same names), or fix a non-yaw orientation / non-\u003Ccode>+y\u003C/code> frame.\u003C/td>\n\u003C/tr>\n\u003Ctr>\n\u003Ctd>27\u003C/td>\n\u003Ctd>\u003Ccode>expectation_failed\u003C/code>\u003C/td>\n\u003Ctd>Compare \u003Ccode>failure.detail.failed[].expected\u003C/code> and \u003Ccode>.actual\u003C/code>; fix whichever is wrong (the command or the expectation), never widen a tolerance just to pass.\u003C/td>\n\u003C/tr>\n\u003Ctr>\n\u003Ctd>22\u003C/td>\n\u003Ctd>\u003Ccode>module_missing\u003C/code>\u003C/td>\n\u003Ctd>Use the point_mass build or a core-only scenario.\u003C/td>\n\u003C/tr>\n\u003Ctr>\n\u003Ctd>other\u003C/td>\n\u003Ctd>see \u003Ccode>simengine-run-capture-diagnose\u003C/code>\u003C/td>\n\u003Ctd>\u003C/td>\n\u003C/tr>\n\u003C/tbody>\n\u003C/table>\n\u003Cp>Change only the project’s files. Never edit SimEngine sources, the example under\n\u003Ccode>$SIMENGINE_ROOT/examples/\u003C/code>, or a tolerance to make a run pass.\u003C/p>\n",[6,9,12,15,18,21],{"id":7,"text":8},"compatible-versions","Compatible versions",{"id":10,"text":11},"how-a-project-fits-together","How a project fits together",{"id":13,"text":14},"variables","Variables",{"id":16,"text":17},"steps","Steps",{"id":19,"text":20},"behavior-with-velocity-and-gravity-the-point-mass-variant","Behavior with velocity and gravity: the point_mass variant",{"id":22,"text":23},"on-failure","On failure",1793299074004]