mujoco 3.2.4 → 3.2.6

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.
Files changed (2) hide show
  1. package/README.md +55 -25
  2. package/package.json +1 -1
package/README.md CHANGED
@@ -110,6 +110,9 @@ write your application in C++ and compile it using Emscripten, you may want to
110
110
  copy a subset of the `EMSCRIPTEN_BINDINGS` from `bindings.cc` into your
111
111
  application’s source file.
112
112
 
113
+ The package is ESM (`type: module`) and ships TypeScript types.
114
+ Ensure your bundler or dev server serves the `.wasm` asset at runtime.
115
+
113
116
  ### Named Access
114
117
 
115
118
  The bindings support named access methods, similar to the Python bindings,
@@ -119,38 +122,58 @@ joint using `data.jnt('myjoint')`.
119
122
 
120
123
  For more details and examples of how to use named access, please refer to the [named access tests](tests/bindings_test.ts#L1876-L2378) and [documentation](https://mujoco.readthedocs.io/en/stable/python.html#named-access).
121
124
 
122
- ## Usage Guide
123
- When interacting with MuJoCo objects through the WASM bindings, it's important to understand how data is accessed. Properties on objects like `MjModel` and `MjData` can expose data in two ways: by copy or by reference.
125
+ ### Memory Management
126
+ Embind-wrapped C++ object handles created or returned into JavaScript live on the
127
+ WebAssembly heap and are **not** garbage-collected by the JS runtime.
124
128
 
125
- ### Install
126
- ```sh
127
- npm install mujoco
128
- ```
129
+ Any heap-allocated C++ object exposed to JS (e.g. via `new Module.MyClass(...)`
130
+ or returned as a pointer/reference from a binding) must be explicitly freed
131
+ when no longer needed to avoid memory leaks.
129
132
 
130
- ```ts
131
- import loadMujoco from 'mujoco';
133
+ Use the generated `.delete()` method on wrapped instances to destroy the
134
+ underlying C++ object:
132
135
 
133
- const mujoco = await loadMujoco();
136
+ ```typescript
137
+ const obj = new Module.MyClass(...);
138
+ // ... use obj ...
139
+ obj.delete(); // free the C++ memory
140
+ ```
134
141
 
135
- const model = mujoco.MjModel.fromXMLString(`
136
- <mujoco>
137
- <worldbody>
138
- <geom type="sphere" size="0.1"/>
139
- </worldbody>
140
- </mujoco>
141
- `);
142
+ Be careful to call `.delete()` exactly once per created object (double-delete
143
+ is an error). In JS code paths that may throw or return early, ensure
144
+ deletion happens in finally blocks or wrap lifetime management to avoid leaks.
142
145
 
143
- const data = new mujoco.MjData(model);
144
- mujoco.mj_step(model, data);
145
- ```
146
+ > [!IMPORTANT]
147
+ > _Embind's documentation strongly recommends that JavaScript code explicitly deletes any C++ object handles it has received._
146
148
 
147
149
  ### Copy vs. Reference
148
150
 
151
+ When interacting with MuJoCo objects through the WASM bindings, it's important to understand how data is accessed. Properties on objects like `MjModel` and `MjData` can expose data in two ways: by copy or by reference.
152
+
149
153
  #### 1. By Copy (Value-based access)
150
154
 
151
155
  Some properties return a copy of the data at the time of access. This is common for complex data structures that need to be marshalled from C++ to JavaScript.
152
156
 
153
- A key example is `MjData.contact`. When you access `data.contact`, you get a new array containing the contacts at that specific moment in the simulation. If you step the simulation forward, this array will not be updated. You must access `data.contact` again to get the new contact information.
157
+ A key example is `MjData.contact`. When you access `data.contact`, you get an object containing a copy of the contacts at that specific moment in the simulation.
158
+
159
+ If you step the simulation forward, they will not be updated. You must access `data.contact` again to get the new contact information.
160
+
161
+ The object you get is a JavaScript proxy interface generated by [Emscripten’s Embind library](https://emscripten.org/docs/porting/connecting_cpp_and_javascript/embind.html#built-in-type-conversions) when you expose a `std::vector` using `register_vector<T>`. It is essentially a "bridge" object.
162
+
163
+ ```typescript
164
+ export interface MjContactVec extends ClassHandle {
165
+ /** Appends a new element to the end of the vector, increasing its length by one. */
166
+ push_back(_0: MjContact): void;
167
+ /** Resizes the vector to contain the specified number of elements, filling new slots with the provided value. */
168
+ resize(_0: number, _1: MjContact): void;
169
+ /** Returns the total number of elements currently stored in the vector. */
170
+ size(): number;
171
+ /** Retrieves the element at the specified index, or returns undefined if the index is out of bounds. */
172
+ get(_0: number): MjContact | undefined;
173
+ /** Overwrites the element at the specified index; returns true if successful or false if the index is invalid. */
174
+ set(_0: number, _1: MjContact): boolean;
175
+ }
176
+ ```
154
177
 
155
178
  Example:
156
179
  ```typescript
@@ -162,9 +185,14 @@ mujoco.mj_step(model, data);
162
185
 
163
186
  // `contacts` is now stale. To get the new contacts, you must access the property again:
164
187
  const newContacts = data.contact;
188
+
189
+ // Remember to delete all created objects when they are no longer needed.
190
+ contacts.delete();
191
+ newContacts.delete();
165
192
  ```
166
193
 
167
194
  #### 2. By Reference (View-based access)
195
+
168
196
  Many properties, especially large numerical arrays, return a live view directly into the WebAssembly memory. This is highly efficient as it avoids copying large amounts of data.
169
197
 
170
198
  A key example is `MjData.qpos` (joint positions). When you get a reference to this array, it points directly to the simulation's state data. Any changes in the simulation (e.g., after a call to `mj_step`) will be immediately reflected in this array.
@@ -180,9 +208,13 @@ mujoco.mj_step(model, data);
180
208
 
181
209
  // `qpos` is automatically updated.
182
210
  console.log(qpos[0]); // Print new position
211
+
212
+ // Remember to delete all created objects when they are no longer needed.
213
+ data.delete();
183
214
  ```
184
215
 
185
216
  ### Data Layout: Row-Major Matrices
217
+
186
218
  When a function from the MuJoCo C API returns a matrix (or needs a matrix as input), these are represented in the JavaScript bindings as flat, one-dimensional `TypedArray`'s. The elements are stored in row-major order.
187
219
 
188
220
  For example, a 3x10 matrix will be returned as a flat array with 30 elements. The first 10 elements represent the first row, the next 10 represent the second row, and so on.
@@ -199,11 +231,13 @@ const element = matrix[i * nCols + j];
199
231
  ```
200
232
 
201
233
  ### Working with Out Parameters
234
+
202
235
  Many functions in the MuJoCo C API use "out parameters" to return data. This means instead of returning a value, they write the result into one of the arguments passed to them by reference (using pointers). In our JavaScript bindings, you'll need to handle these cases specifically.
203
236
 
204
237
  There are two main scenarios you'll encounter:
205
238
 
206
239
  #### 1. Array-like Out Parameters
240
+
207
241
  When a function expects a pointer to a primitive type (like `mjtNum*` or `int*`) to write an array of values, you need to pre-allocate memory for the result on the JavaScript side. We provide helper classes for this: `mujoco.Uint8Buffer`, `mujoco.DoubleBuffer`, `mujoco.FloatBuffer`, and `mujoco.IntBuffer`.
208
242
 
209
243
  Here's how to use them:
@@ -239,6 +273,7 @@ try {
239
273
  ```
240
274
 
241
275
  #### 2. Struct Out Parameters (e.g., mjvCamera*, mjvScene*)
276
+
242
277
  When a function modifies a struct passed by pointer, you should pass an instance of the corresponding JavaScript wrapper class. The underlying C++ struct will be modified in place.
243
278
 
244
279
  Example: Updating a scene
@@ -300,11 +335,6 @@ mujoco.get_mjFRAMESTRING()
300
335
 
301
336
  This will return a javascript array representation of the values in MuJoCo `mjFRAMESTRING`.
302
337
 
303
- ### About assets
304
- The package is ESM (`type: module`) and ships TypeScript types.
305
-
306
- Ensure your bundler or dev server serves the `.wasm` asset at runtime.
307
-
308
338
  ## Development
309
339
 
310
340
  In order to change the bindings you will need to change the [`bindings.cc`](codegen/generated/bindings.cc)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mujoco",
3
- "version": "3.2.4",
3
+ "version": "3.2.6",
4
4
  "description": "MuJoCo WASM bindings",
5
5
  "repository": {
6
6
  "type": "git",