or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

composer.mdindex.mdmjcf.mdphysics.mdsuite.mdviewer.md

mjcf.mddocs/

0

# MJCF Model Building

1

2

Object-oriented library for creating, manipulating, and composing MuJoCo MJCF (MuJoCo XML Configuration Format) models programmatically. Provides high-level abstractions for model elements while maintaining full compatibility with MuJoCo's XML format and enabling complex model composition.

3

4

## Capabilities

5

6

### Model Loading and Parsing

7

8

Load MJCF models from various sources with full element hierarchy support.

9

10

```python { .api }

11

def from_xml_string(xml_string: str) -> 'RootElement':

12

"""

13

Parse MJCF model from XML string.

14

15

Parameters:

16

- xml_string: Complete MJCF XML content as string

17

18

Returns:

19

RootElement representing the parsed model

20

21

Example:

22

>>> xml = '<mujoco><worldbody><body name="box"/></worldbody></mujoco>'

23

>>> model = mjcf.from_xml_string(xml)

24

"""

25

26

def from_path(path: str) -> 'RootElement':

27

"""

28

Parse MJCF model from file path.

29

30

Parameters:

31

- path: Path to MJCF XML file

32

33

Returns:

34

RootElement representing the loaded model

35

36

Example:

37

>>> model = mjcf.from_path('/path/to/model.xml')

38

"""

39

40

def from_file(file_object) -> 'RootElement':

41

"""

42

Parse MJCF model from file object.

43

44

Parameters:

45

- file_object: Open file object containing MJCF XML

46

47

Returns:

48

RootElement representing the parsed model

49

"""

50

```

51

52

### Model Elements

53

54

Core classes for representing MJCF model structure and hierarchy.

55

56

```python { .api }

57

class RootElement:

58

"""

59

Root element of an MJCF model representing the complete model hierarchy.

60

61

Provides access to all model components and enables model-level operations

62

like compilation, attachment, and asset management.

63

"""

64

65

@property

66

def worldbody(self) -> 'Element':

67

"""Access to the worldbody element."""

68

69

@property

70

def asset(self) -> 'Element':

71

"""Access to the asset element."""

72

73

@property

74

def actuator(self) -> 'Element':

75

"""Access to actuator definitions."""

76

77

@property

78

def sensor(self) -> 'Element':

79

"""Access to sensor definitions."""

80

81

def find_all(self, tag: str) -> list:

82

"""

83

Find all elements with specified tag.

84

85

Parameters:

86

- tag: Element tag name to search for

87

88

Returns:

89

List of matching Element instances

90

"""

91

92

def compile_model(self) -> 'Physics':

93

"""

94

Compile MJCF model to Physics instance.

95

96

Returns:

97

Physics instance ready for simulation

98

"""

99

100

class Element:

101

"""

102

Base class for MJCF elements supporting attribute access and hierarchy.

103

104

Represents individual MJCF elements with dynamic attribute access,

105

parent-child relationships, and element-specific operations.

106

"""

107

108

@property

109

def tag(self) -> str:

110

"""Element tag name."""

111

112

@property

113

def parent(self) -> 'Element':

114

"""Parent element in hierarchy."""

115

116

def add(self, tag: str, **attributes) -> 'Element':

117

"""

118

Add child element with specified tag and attributes.

119

120

Parameters:

121

- tag: Child element tag name

122

- **attributes: Element attributes as keyword arguments

123

124

Returns:

125

Newly created child Element

126

127

Example:

128

>>> body = worldbody.add('body', name='box', pos=[0, 0, 1])

129

>>> geom = body.add('geom', type='box', size=[0.1, 0.1, 0.1])

130

"""

131

132

def remove(self) -> None:

133

"""Remove this element from parent."""

134

135

def find(self, tag: str, name: str = None) -> 'Element':

136

"""

137

Find first child element matching criteria.

138

139

Parameters:

140

- tag: Element tag to search for

141

- name: Optional name attribute to match

142

143

Returns:

144

First matching Element or None

145

"""

146

147

def find_all(self, tag: str) -> list:

148

"""

149

Find all child elements with specified tag.

150

151

Parameters:

152

- tag: Element tag to search for

153

154

Returns:

155

List of matching child Elements

156

"""

157

```

158

159

### Asset Management

160

161

Handle external assets like meshes, textures, and materials.

162

163

```python { .api }

164

class Asset:

165

"""

166

Represents MJCF asset with file path and metadata.

167

168

Handles asset file paths, automatic copying, and asset referencing

169

within MJCF models.

170

"""

171

172

@property

173

def path(self) -> str:

174

"""Asset file path."""

175

176

@property

177

def prefix(self) -> str:

178

"""Asset name prefix for namespacing."""

179

180

def export_with_assets(model: 'RootElement', out_dir: str,

181

model_filename: str = 'model.xml') -> None:

182

"""

183

Export model with all referenced assets to directory.

184

185

Parameters:

186

- model: RootElement to export

187

- out_dir: Output directory path

188

- model_filename: Name for main model file (default: 'model.xml')

189

190

Creates directory containing model XML and all asset files with

191

correct relative paths preserved.

192

"""

193

194

def export_with_assets_as_zip(model: 'RootElement', zip_path: str,

195

model_filename: str = 'model.xml') -> None:

196

"""

197

Export model with assets as ZIP archive.

198

199

Parameters:

200

- model: RootElement to export

201

- zip_path: Output ZIP file path

202

- model_filename: Name for main model file (default: 'model.xml')

203

204

Creates ZIP archive containing model and all assets.

205

"""

206

```

207

208

### Model Composition and Attachment

209

210

Tools for combining and modifying MJCF models.

211

212

```python { .api }

213

def get_attachment_frame(element: 'Element') -> 'Element':

214

"""

215

Get attachment frame for element composition.

216

217

Parameters:

218

- element: Element to get attachment frame for

219

220

Returns:

221

Element representing the attachment frame

222

"""

223

224

def get_frame_freejoint(frame: 'Element') -> 'Element':

225

"""

226

Get free joint associated with frame.

227

228

Parameters:

229

- frame: Frame element

230

231

Returns:

232

Associated free joint Element or None

233

"""

234

235

def get_frame_joints(frame: 'Element') -> list:

236

"""

237

Get all joints associated with frame.

238

239

Parameters:

240

- frame: Frame element

241

242

Returns:

243

List of joint Elements

244

"""

245

246

def get_freejoint(body: 'Element') -> 'Element':

247

"""

248

Get free joint for body element.

249

250

Parameters:

251

- body: Body element

252

253

Returns:

254

Associated free joint Element or None

255

"""

256

257

def commit_defaults(root: 'RootElement') -> None:

258

"""

259

Commit default values throughout model hierarchy.

260

261

Parameters:

262

- root: Root element to process

263

264

Applies default values to all elements recursively.

265

"""

266

```

267

268

### Constants and Utilities

269

270

```python { .api }

271

PREFIX_SEPARATOR: str

272

"""Separator used in element name prefixing for model composition."""

273

274

class Physics:

275

"""MJCF-specific physics instance with enhanced model access."""

276

277

def bind(self, element: 'Element') -> object:

278

"""

279

Bind MJCF element to physics data.

280

281

Parameters:

282

- element: MJCF element to bind

283

284

Returns:

285

Bound physics data object

286

"""

287

```

288

289

## Usage Examples

290

291

### Creating Models Programmatically

292

293

```python

294

from dm_control import mjcf

295

296

# Create new model

297

model = mjcf.RootElement()

298

299

# Add basic structure

300

worldbody = model.worldbody

301

302

# Create a simple pendulum

303

pendulum_body = worldbody.add('body', name='pendulum', pos=[0, 0, 1])

304

pendulum_body.add('joint', name='hinge', type='hinge', axis=[0, 1, 0])

305

pendulum_body.add('geom', name='bob', type='sphere', size=[0.05],

306

rgba=[1, 0, 0, 1])

307

308

# Add actuator

309

model.actuator.add('motor', name='motor', joint='hinge', gear=[1])

310

311

# Compile to physics

312

physics = model.compile_model()

313

```

314

315

### Loading and Modifying Models

316

317

```python

318

# Load existing model

319

model = mjcf.from_path('/path/to/robot.xml')

320

321

# Find and modify elements

322

arm = model.find('body', name='arm')

323

if arm:

324

# Add new sensor

325

arm.add('site', name='wrist_site', pos=[0, 0, 0.1])

326

model.sensor.add('touch', name='wrist_sensor', site='wrist_site')

327

328

# Add new actuator

329

model.actuator.add('position', name='new_actuator',

330

joint='elbow_joint', kp=100)

331

```

332

333

### Model Composition

334

335

```python

336

# Load base robot

337

robot = mjcf.from_path('/path/to/base_robot.xml')

338

339

# Load tool model

340

tool = mjcf.from_path('/path/to/tool.xml')

341

342

# Get attachment point

343

attachment_frame = robot.find('site', name='end_effector')

344

345

# Attach tool to robot (conceptual - actual attachment may require

346

# more complex operations depending on model structure)

347

if attachment_frame:

348

# This would typically involve more complex attachment logic

349

pass

350

```

351

352

### Asset Handling

353

354

```python

355

# Create model with assets

356

model = mjcf.RootElement()

357

358

# Add mesh asset

359

model.asset.add('mesh', name='custom_mesh', file='path/to/mesh.stl')

360

361

# Use asset in geometry

362

body = model.worldbody.add('body', name='custom_body')

363

body.add('geom', name='mesh_geom', type='mesh', mesh='custom_mesh')

364

365

# Export with assets

366

mjcf.export_with_assets(model, '/output/directory/')

367

368

# Or export as ZIP

369

mjcf.export_with_assets_as_zip(model, '/output/model.zip')

370

```

371

372

### Advanced Element Operations

373

374

```python

375

# Create complex hierarchy

376

model = mjcf.from_path('/path/to/base.xml')

377

378

# Find all bodies

379

bodies = model.find_all('body')

380

for body in bodies:

381

print(f"Body: {body.name}, Mass: {body.get('mass', 'default')}")

382

383

# Add sensors to all bodies

384

for i, body in enumerate(bodies):

385

if body.name: # Only named bodies

386

site_name = f"{body.name}_site"

387

sensor_name = f"{body.name}_sensor"

388

389

body.add('site', name=site_name, pos=[0, 0, 0])

390

model.sensor.add('accelerometer', name=sensor_name, site=site_name)

391

392

# Commit defaults to finalize

393

mjcf.commit_defaults(model)

394

```

395

396

### Physics Integration

397

398

```python

399

# Create model and compile

400

model = mjcf.from_path('/path/to/model.xml')

401

physics = model.compile_model()

402

403

# Bind MJCF elements to physics data

404

hinge_joint = model.find('joint', name='hinge')

405

if hinge_joint:

406

joint_data = physics.bind(hinge_joint)

407

# Use bound data for direct physics access

408

```