Ordinate 2DDocs Community Open the studio

Python scripts

Every scene has a script: Home → Script opens it in a tab beside the scene. Press ▶ Run (⌘Enter) to run it, ■ Stop to stop. The script is saved with the scene. To keep a script on its own, press Save… in the Script tab: it goes to My Assets (this device, or your account), and Open… brings it back into any scene. Examples in the Script tab opens the ready-made ones in the Marketplace (a PID-balanced cart-pole, a projectile experiment, orbits …); one you choose goes into the Script tab and runs when you press Run.

import studio as s

s.clear()
s.ground()
ball = s.circle(0, 2, 0.1, mass=0.5, name="Ball")

@s.on_step
def push(t, dt):
    ball.force = (1.0, 0.0)          # newtons, until changed
    s.record(t=t, x=ball.x, v=ball.vx)

s.run(3)                             # seconds

Units are SI. x points right and y up; angles are in radians, counter-clockwise positive, as in Properties. The full list of functions is the Python reference.

What a script can do

  • Build a scene in code: bodies, grounds, joints, in loops (a chain of 20 pendulums, a grid of boxes).
  • Control it while it runs: a function decorated with @s.on_step runs before every simulation step and can set forces, torques, motor speeds and positions — a controller, a thrust schedule, a switch.
  • React to events: @s.on_collision when two bodies start touching, @s.on_end when the run ends.
  • Measure: read any body's or joint's state, and s.record(...) rows into a table (the Script sheet of the Table tab) for graphs and CSV.
  • Experiment: run, reset, change a parameter, run again — and print a result.

How it runs

Run sends the script and the scene to Python (Pyodide) running in a separate, locked-down worker of the browser: it has no network, no storage and no access to the page. Python asks the studio for what it wants (make a body, set a force, record a row); the studio checks every request and applies it. A script that does not answer within a few seconds is stopped, so an endless loop cannot freeze the studio. Loading Python takes a few seconds the first time, then well under a second.

In the studio s.run() ends the script's top level and the simulation then runs; put what should happen afterwards in a function decorated with @s.on_end. Run starts from the scene as it was before the last run, and is one undo step.

A scene you open from someone else may contain a script: it runs only when you press Run, and never in a shared link's player.

The same script on your computer

The studio module also runs locally against the engine's Python module, at the studio's Research step, and prints the same results:

PYTHONPATH=PhysicsEngineCore:PhysicsEngineCore/python python3 cartpole_pid.py

There s.run() returns when the time is up, and s.open("scene.physics.json") loads a scene saved by the studio.