@holoscript/robotics-plugin 2.0.1 → 2.0.2

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.
@@ -1,49 +0,0 @@
1
- export function createROS2HardwareLoopHandler() {
2
- return {
3
- name: 'ros2_hardware_loop',
4
- defaultConfig: { nodeName: 'holo_rig_01', topicPrefix: '/holo', updateFrequencyHz: 60, bidirectional: true },
5
- onAttach(n, c, ctx) {
6
- n.__ros2State = { connected: false, lastPingMs: 0, activeTopics: [], hardwareSyncDriftMs: 0 };
7
- ctx.emit?.('ros2:init', { node: c.nodeName });
8
- },
9
- onDetach(n, _c, ctx) {
10
- delete n.__ros2State;
11
- ctx.emit?.('ros2:disconnect');
12
- },
13
- onUpdate() { },
14
- onEvent(n, c, ctx, e) {
15
- const s = n.__ros2State;
16
- if (!s)
17
- return;
18
- const evt = e;
19
- switch (evt.type) {
20
- case 'ros2:connect':
21
- s.connected = true;
22
- // In real usage, initializes rclnodejs bridge for pub/sub physics
23
- ctx.emit?.('ros2:connected', { latencyMs: 12 });
24
- break;
25
- case 'scene:transform_change':
26
- if (c.bidirectional && s.connected) {
27
- // Push virtual set transform to physical robot joint
28
- ctx.emit?.('ros2:publish', { topic: `${c.topicPrefix}/joint_cmd`, payload: evt.payload });
29
- }
30
- break;
31
- case 'ros2:telemetry':
32
- // Receive physical robot telemetry to drive virtual set
33
- s.hardwareSyncDriftMs = Math.abs(Date.now() - (evt.payload.timestamp || Date.now()));
34
- n.transform = evt.payload.transform;
35
- break;
36
- case 'ttu:manifested':
37
- // Dynamically bind to Text-To-Universe AST streams
38
- const crdtRoot = evt.payload?.crdtRoot;
39
- if (crdtRoot && s.connected) {
40
- const dynamicTopic = `${c.topicPrefix}/ttu_sync/${crdtRoot}`;
41
- s.activeTopics.push(dynamicTopic);
42
- ctx.emit?.('ros2:subscribe', { topic: dynamicTopic });
43
- ctx.emit?.('ros2:log', { message: `Bridged digital twin for TTU root: ${crdtRoot}` });
44
- }
45
- break;
46
- }
47
- }
48
- };
49
- }
@@ -1,4 +0,0 @@
1
- export type TraitContext = unknown;
2
- export type TraitEvent = unknown;
3
- export type HSPlusNode = unknown;
4
- export type TraitHandler<_T> = unknown;
@@ -1 +0,0 @@
1
- export {};
@@ -1,45 +0,0 @@
1
- /**
2
- * HoloScript → USD Code Generator
3
- *
4
- * Generates Universal Scene Description (USD) files from HoloScript AST.
5
- * Targets NVIDIA Isaac Sim with UsdPhysics and PhysX schemas.
6
- *
7
- * Isaac Lab Interop (Path A):
8
- * - Emits PhysicsDriveAPI for PD actuator control
9
- * - Emits PhysxJointAxisAPI for per-axis joint friction assumptions
10
- * - Supports domain randomization metadata for sim-to-real transfer
11
- */
12
- import { CompositionNode } from './ast';
13
- export interface IsaacLabConfig {
14
- /** Isaac Lab version target for generated code */
15
- isaacLabVersion?: string;
16
- /** Enable PhysX articulation and per-axis joint friction schemas (default: true) */
17
- enableJointFriction?: boolean;
18
- /** Enable drive attributes for PD control (default: true) */
19
- enableDriveAttributes?: boolean;
20
- }
21
- export declare class USDCodeGen {
22
- private output;
23
- private indentLevel;
24
- private config;
25
- constructor(config?: IsaacLabConfig);
26
- generate(ast: CompositionNode): string;
27
- private generateLink;
28
- private generateJoint;
29
- private indent;
30
- private emit;
31
- private geometryToUSD;
32
- private isJointObject;
33
- private getJointKind;
34
- private getJointApiSchemas;
35
- private hasDriveProperties;
36
- private hasPhysxJointAxisProperties;
37
- private emitPhysxJointAxisProperties;
38
- private emitActuatorGroupComment;
39
- private numberProp;
40
- private convertJointScalar;
41
- private formatNumber;
42
- private formatTokenArray;
43
- private vectorToAxisName;
44
- private emitDomainRandomizationAsComment;
45
- }
@@ -1,504 +0,0 @@
1
- /**
2
- * HoloScript → USD Code Generator
3
- *
4
- * Generates Universal Scene Description (USD) files from HoloScript AST.
5
- * Targets NVIDIA Isaac Sim with UsdPhysics and PhysX schemas.
6
- *
7
- * Isaac Lab Interop (Path A):
8
- * - Emits PhysicsDriveAPI for PD actuator control
9
- * - Emits PhysxJointAxisAPI for per-axis joint friction assumptions
10
- * - Supports domain randomization metadata for sim-to-real transfer
11
- */
12
- export class USDCodeGen {
13
- constructor(config) {
14
- this.output = [];
15
- this.indentLevel = 0;
16
- this.config = {
17
- isaacLabVersion: config?.isaacLabVersion || '2.3',
18
- enableJointFriction: config?.enableJointFriction ?? true,
19
- enableDriveAttributes: config?.enableDriveAttributes ?? true,
20
- };
21
- }
22
- generate(ast) {
23
- this.output = [];
24
- this.indentLevel = 0;
25
- // USD header
26
- this.emit('#usda 1.0');
27
- this.emit('(');
28
- this.indentLevel++;
29
- this.emit(`defaultPrim = "${ast.name}"`);
30
- this.emit('upAxis = "Z"');
31
- this.emit('metersPerUnit = 1.0');
32
- this.emit('kilogramsPerMass = 1.0');
33
- this.indentLevel--;
34
- this.emit(')');
35
- this.emit('');
36
- // Isaac Lab header comment
37
- this.emit(`# Generated for Isaac Lab ${this.config.isaacLabVersion}`);
38
- this.emit('# Units: meters, kilograms, seconds; HoloScript angular inputs are radians.');
39
- this.emit('# USD angular joint limits and velocities are exported in degrees per OpenUSD/PhysX.');
40
- // Emit domain randomization config as USD comments (for Isaac Lab Python codegen)
41
- if (ast.domainRandomization) {
42
- this.emit('');
43
- this.emit('# Domain Randomization Configuration');
44
- this.emitDomainRandomizationAsComment(ast.domainRandomization);
45
- this.emit('');
46
- }
47
- // Root articulation.
48
- const rootSchemas = ['PhysicsArticulationRootAPI'];
49
- if (this.config.enableJointFriction) {
50
- rootSchemas.push('PhysxArticulationAPI');
51
- }
52
- this.emit(`def Xform "${ast.name}" (`);
53
- this.indentLevel++;
54
- this.emit(`prepend apiSchemas = ${this.formatTokenArray(rootSchemas)}`);
55
- this.indentLevel--;
56
- this.emit(')');
57
- this.emit('{');
58
- this.indentLevel++;
59
- if (this.config.enableJointFriction) {
60
- this.emit('');
61
- this.emit('# PhysxArticulationAPI root settings');
62
- this.emit('bool physxArticulation:articulationEnabled = true');
63
- this.emit('bool physxArticulation:enabledSelfCollisions = false');
64
- this.emit('int physxArticulation:solverPositionIterationCount = 32');
65
- this.emit('int physxArticulation:solverVelocityIterationCount = 1');
66
- }
67
- // Collect joints for later generation
68
- const joints = [];
69
- // Separate joint and link objects
70
- const jointObjects = [];
71
- const linkObjects = [];
72
- for (const obj of ast.objects) {
73
- if (this.isJointObject(obj)) {
74
- jointObjects.push(obj);
75
- }
76
- else {
77
- linkObjects.push(obj);
78
- }
79
- }
80
- // Generate links
81
- for (const obj of ast.objects) {
82
- if (this.isJointObject(obj)) {
83
- // New template format: Joint is separate object
84
- // Check if there's a corresponding link (child of this joint)
85
- const childLink = linkObjects.find((link) => link.properties.parent === obj.name);
86
- const kind = this.getJointKind(obj);
87
- if (childLink) {
88
- // Generate the child link
89
- this.generateLink(childLink);
90
- // Collect joint info
91
- const parent = obj.properties.parent || 'World';
92
- joints.push({
93
- name: obj.name,
94
- kind,
95
- parent,
96
- child: childLink.name,
97
- props: obj.properties,
98
- actuatorGroups: obj.actuatorGroups,
99
- });
100
- }
101
- else {
102
- // Old format: joint_parent property (backward compatibility)
103
- this.generateLink(obj);
104
- const parent = obj.properties.joint_parent || 'World';
105
- joints.push({
106
- name: `${obj.name}Joint`,
107
- kind,
108
- parent,
109
- child: obj.name,
110
- props: obj.properties,
111
- actuatorGroups: obj.actuatorGroups,
112
- });
113
- }
114
- }
115
- else {
116
- // Link object without joint (base, end effector, etc.)
117
- // Only generate if not already generated as child of a joint
118
- const isChildOfJoint = jointObjects.some((j) => linkObjects.find((l) => l.properties.parent === j.name && l.name === obj.name));
119
- if (!isChildOfJoint) {
120
- this.generateLink(obj);
121
- }
122
- }
123
- }
124
- // Generate joints after all links
125
- this.emit('');
126
- this.emit('# Joints');
127
- for (const joint of joints) {
128
- this.generateJoint(joint);
129
- }
130
- this.indentLevel--;
131
- this.emit('}');
132
- return this.output.join('\n');
133
- }
134
- generateLink(obj) {
135
- const geometry = obj.properties.geometry || 'box';
136
- const usdType = this.geometryToUSD(geometry);
137
- const isStatic = obj.traits.includes('static');
138
- this.emit('');
139
- this.emit(`# ${obj.name}`);
140
- if (obj.domainRandomization) {
141
- this.emit('# Object Domain Randomization Configuration');
142
- this.emitDomainRandomizationAsComment(obj.domainRandomization);
143
- }
144
- this.emit(`def ${usdType} "${obj.name}" (`);
145
- this.indentLevel++;
146
- // Add physics APIs (unless static)
147
- if (!isStatic) {
148
- this.emit('prepend apiSchemas = ["PhysicsCollisionAPI", "PhysicsRigidBodyAPI", "PhysicsMassAPI"]');
149
- }
150
- this.indentLevel--;
151
- this.emit(')');
152
- this.emit('{');
153
- this.indentLevel++;
154
- // Geometry dimensions (support both array and individual properties)
155
- if (geometry === 'cylinder') {
156
- let radius, height;
157
- if (obj.properties.dimensions) {
158
- // Old format: dimensions: [radius, height]
159
- const dims = obj.properties.dimensions;
160
- [radius, height] = dims;
161
- }
162
- else {
163
- // New format: radius: 0.2, height/length: 0.2
164
- radius = obj.properties.radius || 0.1;
165
- height = (obj.properties.height || obj.properties.length) || 0.1;
166
- }
167
- this.emit(`float radius = ${radius}`);
168
- this.emit(`float height = ${height}`);
169
- }
170
- else if (geometry === 'box') {
171
- let length, width, height;
172
- if (obj.properties.dimensions) {
173
- // Old format: dimensions: [length, width, height]
174
- const dims = obj.properties.dimensions;
175
- [length, width, height] = dims;
176
- }
177
- else {
178
- // New format: length: 1.0, width: 0.1, height: 0.1
179
- length = obj.properties.length || 1.0;
180
- width = obj.properties.width || 1.0;
181
- height = obj.properties.height || 1.0;
182
- }
183
- this.emit('double size = 1.0');
184
- this.emit(`float3 xformOp:scale = (${length}, ${width}, ${height})`);
185
- this.emit('uniform token[] xformOpOrder = ["xformOp:scale"]');
186
- }
187
- else if (geometry === 'sphere') {
188
- let radius;
189
- if (obj.properties.dimensions) {
190
- // Old format: dimensions: [radius]
191
- const dims = obj.properties.dimensions;
192
- [radius] = dims;
193
- }
194
- else {
195
- // New format: radius: 0.08
196
- radius = obj.properties.radius || 0.1;
197
- }
198
- this.emit(`float radius = ${radius}`);
199
- }
200
- // Color/Material
201
- if (obj.properties.color) {
202
- const color = obj.properties.color;
203
- const [r, g, b] = color;
204
- this.emit(`color3f[] primvars:displayColor = [(${r}, ${g}, ${b})]`);
205
- }
206
- else if (obj.properties.material) {
207
- // Default colors based on material
208
- const materialColors = {
209
- metal: '0.6, 0.6, 0.65',
210
- plastic: '0.8, 0.8, 0.8',
211
- wood: '0.6, 0.4, 0.2',
212
- glass: '0.9, 0.9, 1.0',
213
- };
214
- const material = obj.properties.material;
215
- const color = materialColors[material] || '0.8, 0.8, 0.8';
216
- this.emit(`color3f[] primvars:displayColor = [(${color})]`);
217
- }
218
- // Physics properties
219
- if (!isStatic) {
220
- this.emit('');
221
- this.emit('# Physics properties');
222
- const mass = obj.properties.mass || 1.0;
223
- this.emit(`float physics:mass = ${mass}`);
224
- if (obj.properties.inertia) {
225
- const inertia = obj.properties.inertia;
226
- this.emit(`float3 physics:diagonalInertia = (${inertia[0]}, ${inertia[1]}, ${inertia[2]})`);
227
- }
228
- this.emit('uniform token physics:approximation = "convexHull"');
229
- }
230
- else {
231
- this.emit('');
232
- this.emit('# Static object');
233
- this.emit('uniform token physics:rigidBodyEnabled = false');
234
- }
235
- // Position (if specified)
236
- if (obj.properties.position) {
237
- const pos = obj.properties.position;
238
- this.emit('');
239
- this.emit(`double3 xformOp:translate = (${pos[0]}, ${pos[1]}, ${pos[2]})`);
240
- if (!obj.properties.dimensions) {
241
- this.emit('uniform token[] xformOpOrder = ["xformOp:translate"]');
242
- }
243
- }
244
- this.indentLevel--;
245
- this.emit('}');
246
- }
247
- generateJoint(joint) {
248
- const axisToken = joint.kind === 'prismatic' ? 'linear' : 'angular';
249
- const schemas = this.getJointApiSchemas(joint, axisToken);
250
- this.emit('');
251
- this.emit(`def ${joint.kind === 'prismatic' ? 'PhysicsPrismaticJoint' : 'PhysicsRevoluteJoint'} "${joint.name}"`);
252
- if (schemas.length > 0) {
253
- this.emit('(');
254
- this.indentLevel++;
255
- this.emit(`prepend apiSchemas = ${this.formatTokenArray(schemas)}`);
256
- this.indentLevel--;
257
- this.emit(')');
258
- }
259
- this.emit('{');
260
- this.indentLevel++;
261
- // Body references
262
- this.emit(`rel physics:body0 = <../${joint.parent}>`);
263
- this.emit(`rel physics:body1 = <../${joint.child}>`);
264
- this.emit('');
265
- // Joint frames
266
- const origin = joint.props.joint_origin || joint.props.position;
267
- if (origin) {
268
- const pos = origin;
269
- this.emit(`point3f physics:localPos0 = (${pos[0]}, ${pos[1]}, ${pos[2]})`);
270
- }
271
- else {
272
- this.emit('point3f physics:localPos0 = (0, 0, 0)');
273
- }
274
- this.emit('quatf physics:localRot0 = (1, 0, 0, 0)');
275
- this.emit('');
276
- this.emit('point3f physics:localPos1 = (0, 0, 0)');
277
- this.emit('quatf physics:localRot1 = (1, 0, 0, 0)');
278
- this.emit('');
279
- // Joint axis (support both old and new property names)
280
- const axis = joint.props.joint_axis || joint.props.axis;
281
- if (axis) {
282
- const axisVec = axis;
283
- const axisName = this.vectorToAxisName(axisVec);
284
- this.emit(`uniform token physics:axis = "${axisName}"`);
285
- }
286
- else {
287
- this.emit('uniform token physics:axis = "Y"');
288
- }
289
- this.emit('');
290
- // Joint limits (support both old and new property names)
291
- const limits = joint.props.joint_limits || joint.props.limits;
292
- if (limits) {
293
- const limitsVec = limits;
294
- this.emit(`float physics:lowerLimit = ${this.formatNumber(this.convertJointScalar(limitsVec[0], joint.kind))}`);
295
- this.emit(`float physics:upperLimit = ${this.formatNumber(this.convertJointScalar(limitsVec[1], joint.kind))}`);
296
- }
297
- this.emit('');
298
- // Joint dynamics (support both old and new property names)
299
- const effort = this.numberProp(joint.props, 'joint_effort', 'max_effort');
300
- if (effort !== undefined) {
301
- this.emit(`float physics:maxForce = ${effort}`);
302
- }
303
- const velocity = this.numberProp(joint.props, 'max_velocity');
304
- if (velocity !== undefined) {
305
- this.emit(`float physics:maxVelocity = ${this.formatNumber(this.convertJointScalar(velocity, joint.kind))}`);
306
- }
307
- // OpenUSD PhysicsDriveAPI attributes for PD actuator control.
308
- if (this.config.enableDriveAttributes && this.hasDriveProperties(joint.props)) {
309
- this.emit('');
310
- this.emit('# PhysicsDriveAPI attributes for PD control');
311
- const kp = this.numberProp(joint.props, 'kp', 'stiffness');
312
- const kd = this.numberProp(joint.props, 'kd', 'damping');
313
- if (kp !== undefined) {
314
- this.emit(`float drive:${axisToken}:physics:stiffness = ${kp}`);
315
- }
316
- if (kd !== undefined) {
317
- this.emit(`float drive:${axisToken}:physics:damping = ${kd}`);
318
- }
319
- if (effort !== undefined) {
320
- this.emit(`float drive:${axisToken}:physics:maxForce = ${effort}`);
321
- }
322
- this.emit(`uniform token drive:${axisToken}:physics:type = "force"`);
323
- }
324
- if (this.config.enableJointFriction && this.hasPhysxJointAxisProperties(joint.props)) {
325
- this.emit('');
326
- this.emit('# PhysxJointAxisAPI per-axis friction and velocity assumptions');
327
- this.emitPhysxJointAxisProperties(joint.props, joint.kind, axisToken);
328
- }
329
- const latency = this.numberProp(joint.props, 'actuator_latency', 'latency');
330
- if (latency !== undefined) {
331
- this.emit('');
332
- this.emit('# Isaac Lab delayed actuator hint; convert seconds to delay steps in task config.');
333
- this.emit(`custom float holoscript:isaacLab:actuatorLatencySeconds = ${latency}`);
334
- }
335
- if (joint.actuatorGroups?.length) {
336
- this.emit('');
337
- this.emit('# Isaac Lab actuator group hints');
338
- for (const group of joint.actuatorGroups) {
339
- this.emitActuatorGroupComment(group);
340
- }
341
- }
342
- this.indentLevel--;
343
- this.emit('}');
344
- }
345
- indent() {
346
- return ' '.repeat(this.indentLevel);
347
- }
348
- emit(line) {
349
- this.output.push(this.indent() + line);
350
- }
351
- geometryToUSD(geometry) {
352
- const mapping = {
353
- cylinder: 'Cylinder',
354
- box: 'Cube',
355
- sphere: 'Sphere',
356
- cone: 'Cone',
357
- plane: 'Plane',
358
- torus: 'Torus',
359
- };
360
- return mapping[geometry] || 'Cube';
361
- }
362
- isJointObject(obj) {
363
- return obj.traits.includes('joint_revolute') || obj.traits.includes('joint_prismatic');
364
- }
365
- getJointKind(obj) {
366
- return obj.traits.includes('joint_prismatic') ? 'prismatic' : 'revolute';
367
- }
368
- getJointApiSchemas(joint, axisToken) {
369
- const schemas = [];
370
- if (this.config.enableDriveAttributes && this.hasDriveProperties(joint.props)) {
371
- schemas.push(`PhysicsDriveAPI:${axisToken}`);
372
- }
373
- if (this.config.enableJointFriction && this.hasPhysxJointAxisProperties(joint.props)) {
374
- schemas.push(`PhysxJointAxisAPI:${axisToken}`);
375
- }
376
- return schemas;
377
- }
378
- hasDriveProperties(props) {
379
- return this.numberProp(props, 'kp', 'stiffness', 'kd', 'damping', 'joint_effort', 'max_effort') !== undefined;
380
- }
381
- hasPhysxJointAxisProperties(props) {
382
- return (this.numberProp(props, 'joint_friction', 'friction', 'joint_static_friction', 'joint_dynamic_friction', 'joint_viscous_friction', 'armature', 'max_velocity') !== undefined);
383
- }
384
- emitPhysxJointAxisProperties(props, kind, axisToken) {
385
- const friction = this.numberProp(props, 'joint_friction', 'friction');
386
- const staticFriction = this.numberProp(props, 'joint_static_friction') ?? friction;
387
- const dynamicFriction = this.numberProp(props, 'joint_dynamic_friction') ?? friction;
388
- const viscousFriction = this.numberProp(props, 'joint_viscous_friction');
389
- const armature = this.numberProp(props, 'armature');
390
- const velocity = this.numberProp(props, 'max_velocity');
391
- if (staticFriction !== undefined) {
392
- this.emit(`float physxJointAxis:${axisToken}:staticFrictionEffort = ${staticFriction}`);
393
- }
394
- if (dynamicFriction !== undefined) {
395
- this.emit(`float physxJointAxis:${axisToken}:dynamicFrictionEffort = ${dynamicFriction}`);
396
- }
397
- if (viscousFriction !== undefined) {
398
- this.emit(`float physxJointAxis:${axisToken}:viscousFrictionCoefficient = ${viscousFriction}`);
399
- }
400
- if (armature !== undefined) {
401
- this.emit(`float physxJointAxis:${axisToken}:armature = ${armature}`);
402
- }
403
- if (velocity !== undefined) {
404
- this.emit(`float physxJointAxis:${axisToken}:maxJointVelocity = ${this.formatNumber(this.convertJointScalar(velocity, kind))}`);
405
- }
406
- }
407
- emitActuatorGroupComment(group) {
408
- const details = [
409
- `type=${group.type}`,
410
- `joints=[${group.jointNames.join(', ')}]`,
411
- group.stiffness !== undefined ? `stiffness=${group.stiffness}` : undefined,
412
- group.damping !== undefined ? `damping=${group.damping}` : undefined,
413
- group.friction !== undefined ? `friction=${group.friction}` : undefined,
414
- group.latency !== undefined ? `latencySeconds=${group.latency}` : undefined,
415
- ].filter(Boolean);
416
- this.emit(`# ${group.name}: ${details.join(' ')}`);
417
- }
418
- numberProp(props, ...keys) {
419
- for (const key of keys) {
420
- const value = props[key];
421
- if (typeof value === 'number' && Number.isFinite(value)) {
422
- return value;
423
- }
424
- }
425
- return undefined;
426
- }
427
- convertJointScalar(value, kind) {
428
- return kind === 'revolute' ? (value * 180) / Math.PI : value;
429
- }
430
- formatNumber(value) {
431
- return Number(value.toFixed(6)).toString();
432
- }
433
- formatTokenArray(values) {
434
- return `[${values.map((value) => `"${value}"`).join(', ')}]`;
435
- }
436
- vectorToAxisName(axis) {
437
- const [x = 0, y = 0, z = 1] = axis;
438
- if (Math.abs(x) > Math.abs(y) && Math.abs(x) > Math.abs(z)) {
439
- return 'X';
440
- }
441
- else if (Math.abs(y) > Math.abs(z)) {
442
- return 'Y';
443
- }
444
- else {
445
- return 'Z';
446
- }
447
- }
448
- emitDomainRandomizationAsComment(dr) {
449
- if (dr.physics) {
450
- this.emit('# physics:');
451
- if (dr.physics.massScale) {
452
- this.emit(`# massScale: [${dr.physics.massScale[0]}, ${dr.physics.massScale[1]}]`);
453
- }
454
- if (dr.physics.frictionRange) {
455
- this.emit(`# frictionRange: [${dr.physics.frictionRange[0]}, ${dr.physics.frictionRange[1]}]`);
456
- }
457
- if (dr.physics.dampingRange) {
458
- this.emit(`# dampingRange: [${dr.physics.dampingRange[0]}, ${dr.physics.dampingRange[1]}]`);
459
- }
460
- if (dr.physics.armatureRange) {
461
- this.emit(`# armatureRange: [${dr.physics.armatureRange[0]}, ${dr.physics.armatureRange[1]}]`);
462
- }
463
- }
464
- if (dr.actuator) {
465
- this.emit('# actuator:');
466
- if (dr.actuator.kpNoise !== undefined) {
467
- this.emit(`# kpNoise: ${dr.actuator.kpNoise}`);
468
- }
469
- if (dr.actuator.kdNoise !== undefined) {
470
- this.emit(`# kdNoise: ${dr.actuator.kdNoise}`);
471
- }
472
- if (dr.actuator.latencyNoise !== undefined) {
473
- this.emit(`# latencyNoise: ${dr.actuator.latencyNoise}`);
474
- }
475
- }
476
- if (dr.observation) {
477
- this.emit('# observation:');
478
- if (dr.observation.jointPosNoise !== undefined) {
479
- this.emit(`# jointPosNoise: ${dr.observation.jointPosNoise}`);
480
- }
481
- if (dr.observation.jointVelNoise !== undefined) {
482
- this.emit(`# jointVelNoise: ${dr.observation.jointVelNoise}`);
483
- }
484
- if (dr.observation.imuNoise !== undefined) {
485
- this.emit(`# imuNoise: ${dr.observation.imuNoise}`);
486
- }
487
- }
488
- if (dr.initialState) {
489
- this.emit('# initialState:');
490
- if (dr.initialState.rootPoseRange) {
491
- this.emit(`# rootPoseRange: [${dr.initialState.rootPoseRange.join(', ')}]`);
492
- }
493
- }
494
- if (dr.disturbance) {
495
- this.emit('# disturbance:');
496
- if (dr.disturbance.forceRange) {
497
- this.emit(`# forceRange: [${dr.disturbance.forceRange[0]}, ${dr.disturbance.forceRange[1]}]`);
498
- }
499
- if (dr.disturbance.intervalRange) {
500
- this.emit(`# intervalRange: [${dr.disturbance.intervalRange[0]}, ${dr.disturbance.intervalRange[1]}]`);
501
- }
502
- }
503
- }
504
- }