or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

batch-operations.mdbatch-rotations.mdcamera.mdcoordinates.mdeditor.mdindex.mdplot-utils.mdrotations.mdtrajectories.mdtransform-manager.mdtransformations.mduncertainty.mdurdf.mdvisualization.md

editor.mddocs/

0

# Editor

1

2

Interactive GUI tools for visual transformation editing using PyQt with real-time 3D visualization and parameter adjustment capabilities.

3

4

## Capabilities

5

6

### TransformEditor Class

7

8

Complete GUI application for interactive transformation editing with 3D visualization.

9

10

```python { .api }

11

class TransformEditor(QMainWindow):

12

def __init__(self, transform_manager, base_frame, xlim=(-1.0, 1.0), ylim=(-1.0, 1.0), zlim=(-1.0, 1.0), s=1.0, figsize=(10, 10), dpi=100, window_size=(500, 600), parent=None):

13

"""

14

Interactive GUI for editing transformations with 3D visualization.

15

16

Parameters:

17

- transform_manager: TransformManager - Transform manager instance

18

- base_frame: str - Base reference frame name

19

- xlim: tuple - X-axis visualization limits

20

- ylim: tuple - Y-axis visualization limits

21

- zlim: tuple - Z-axis visualization limits

22

- s: float - Frame visualization scaling

23

- figsize: tuple - Matplotlib figure size

24

- dpi: int - Figure DPI

25

- window_size: tuple - GUI window size (width, height)

26

- parent: QWidget, optional - Parent widget

27

"""

28

29

def show(self):

30

"""Start the GUI application and display editor window."""

31

32

# Attributes after completion:

33

# transform_manager: TransformManager - Updated with all edited transformations

34

```

35

36

### PositionEulerEditor Class

37

38

Frame editor widget using Euler angle representation for orientation control.

39

40

```python { .api }

41

class PositionEulerEditor(QWidget):

42

# Signal emitted when frame changes

43

frameChanged = QtCore.pyqtSignal()

44

45

def __init__(self, base_frame, xlim, ylim, zlim, parent=None):

46

"""

47

Frame editor using position and Euler angles.

48

49

Parameters:

50

- base_frame: str - Base frame name

51

- xlim: tuple - X-axis limits for visualization

52

- ylim: tuple - Y-axis limits for visualization

53

- zlim: tuple - Z-axis limits for visualization

54

- parent: QWidget, optional - Parent widget

55

"""

56

57

def set_frame(self, A2B):

58

"""

59

Set pose of frame using transformation matrix.

60

61

Parameters:

62

- A2B: array, shape (4, 4) - Transformation matrix

63

"""

64

```

65

66

### GUI Availability

67

68

Constants indicating PyQt availability and version information.

69

70

```python { .api }

71

qt_available: bool # Whether PyQt is available for GUI functionality

72

qt_version: int | None # PyQt version (4 or 5) if available, None otherwise

73

```

74

75

## Usage Examples

76

77

### Basic Transform Editor

78

79

```python

80

from pytransform3d.editor import TransformEditor, qt_available

81

from pytransform3d.transform_manager import TransformManager

82

import pytransform3d.transformations as pt

83

84

if qt_available:

85

# Create transform manager with some initial transformations

86

tm = TransformManager()

87

tm.add_transform("base", "link1", pt.transform_from(p=[1, 0, 0]))

88

tm.add_transform("link1", "link2", pt.transform_from(p=[0, 1, 0]))

89

tm.add_transform("link2", "end_effector", pt.transform_from(p=[0, 0, 0.5]))

90

91

# Create and show editor

92

app = QApplication.instance()

93

if app is None:

94

app = QApplication([])

95

96

editor = TransformEditor(tm, "base", xlim=(-2, 2), ylim=(-2, 2), zlim=(-1, 2))

97

editor.show()

98

99

# Run application

100

app.exec_()

101

102

# Access modified transformations

103

print("Final transformations:")

104

for from_frame, to_frame in [("base", "link1"), ("link1", "link2"), ("link2", "end_effector")]:

105

T = tm.get_transform(from_frame, to_frame)

106

print(f"{from_frame} -> {to_frame}:")

107

print(f" Position: {T[:3, 3]}")

108

109

else:

110

print("PyQt not available - GUI editor cannot be used")

111

```

112

113

### Robot Joint Editor

114

115

```python

116

from pytransform3d.editor import TransformEditor, qt_available

117

from pytransform3d.transform_manager import TransformManager

118

import pytransform3d.transformations as pt

119

import pytransform3d.rotations as pr

120

import numpy as np

121

122

if qt_available:

123

# Create robot arm

124

tm = TransformManager()

125

126

# Base

127

tm.add_transform("world", "base", pt.transform_from(p=[0, 0, 0.1]))

128

129

# Shoulder joint

130

tm.add_transform("base", "shoulder", pt.transform_from(p=[0, 0, 0.2]))

131

132

# Upper arm

133

tm.add_transform("shoulder", "upper_arm", pt.transform_from(p=[0.3, 0, 0]))

134

135

# Elbow joint

136

R_elbow = pr.matrix_from_euler([0, -np.pi/4, 0], "xyz", extrinsic=True)

137

tm.add_transform("upper_arm", "elbow", pt.transform_from(R=R_elbow))

138

139

# Forearm

140

tm.add_transform("elbow", "forearm", pt.transform_from(p=[0.25, 0, 0]))

141

142

# Wrist

143

tm.add_transform("forearm", "wrist", pt.transform_from(p=[0.1, 0, 0]))

144

145

# Hand

146

tm.add_transform("wrist", "hand", pt.transform_from(p=[0.05, 0, 0]))

147

148

# Launch editor

149

app = QApplication.instance()

150

if app is None:

151

app = QApplication([])

152

153

# Configure editor for robot workspace

154

editor = TransformEditor(

155

transform_manager=tm,

156

base_frame="world",

157

xlim=(-0.8, 0.8),

158

ylim=(-0.8, 0.8),

159

zlim=(0, 1.0),

160

s=0.1, # Smaller frame visualization

161

figsize=(12, 8),

162

window_size=(800, 600)

163

)

164

165

editor.show()

166

app.exec_()

167

168

# Print final robot configuration

169

print("\nFinal robot configuration:")

170

print(f"Hand position: {tm.get_transform('world', 'hand')[:3, 3]}")

171

172

else:

173

print("PyQt not available - install PyQt5 or PyQt6 to use GUI editor")

174

```

175

176

### Custom Frame Editor

177

178

```python

179

from pytransform3d.editor import PositionEulerEditor, qt_available

180

import pytransform3d.transformations as pt

181

import pytransform3d.rotations as pr

182

import numpy as np

183

184

if qt_available:

185

from PyQt5.QtWidgets import QApplication, QMainWindow, QVBoxLayout, QWidget

186

from PyQt5.QtCore import pyqtSlot

187

188

class CustomFrameEditor(QMainWindow):

189

def __init__(self):

190

super().__init__()

191

self.setWindowTitle("Custom Frame Editor")

192

193

# Create central widget

194

central_widget = QWidget()

195

self.setCentralWidget(central_widget)

196

layout = QVBoxLayout(central_widget)

197

198

# Create frame editor

199

self.frame_editor = PositionEulerEditor(

200

base_frame="world",

201

xlim=(-2, 2),

202

ylim=(-2, 2),

203

zlim=(-2, 2)

204

)

205

206

# Connect signal

207

self.frame_editor.frameChanged.connect(self.on_frame_changed)

208

209

layout.addWidget(self.frame_editor)

210

211

# Set initial frame

212

initial_transform = pt.transform_from(p=[1, 0, 0.5])

213

self.frame_editor.set_frame(initial_transform)

214

215

@pyqtSlot()

216

def on_frame_changed(self):

217

"""Handle frame change event."""

218

print("Frame was modified by user!")

219

# Access current frame state from editor

220

# (Implementation depends on specific editor internals)

221

222

# Run custom editor

223

app = QApplication.instance()

224

if app is None:

225

app = QApplication([])

226

227

editor = CustomFrameEditor()

228

editor.show()

229

app.exec_()

230

231

else:

232

print("PyQt not available")

233

```

234

235

### Programmatic Frame Editing

236

237

```python

238

from pytransform3d.editor import PositionEulerEditor, qt_available

239

import pytransform3d.transformations as pt

240

import pytransform3d.rotations as pr

241

import numpy as np

242

243

if qt_available:

244

from PyQt5.QtWidgets import QApplication

245

246

# Create application

247

app = QApplication.instance()

248

if app is None:

249

app = QApplication([])

250

251

# Create editor widget

252

editor = PositionEulerEditor(

253

base_frame="base",

254

xlim=(-3, 3),

255

ylim=(-3, 3),

256

zlim=(-1, 3)

257

)

258

259

# Set various frame poses programmatically

260

poses = [

261

pt.transform_from(p=[1, 0, 0]),

262

pt.transform_from(p=[0, 1, 0]),

263

pt.transform_from(p=[0, 0, 1]),

264

pt.transform_from(

265

R=pr.matrix_from_euler([0, 0, np.pi/4], "xyz", extrinsic=True),

266

p=[1, 1, 0]

267

)

268

]

269

270

# Demonstrate setting different frames

271

for i, pose in enumerate(poses):

272

print(f"Setting pose {i+1}: position = {pose[:3, 3]}")

273

editor.set_frame(pose)

274

275

# Show editor briefly (in real app, user would interact)

276

editor.show()

277

app.processEvents() # Process GUI events

278

279

# In practice, you would wait for user interaction

280

# or use signals/slots to handle frame changes

281

282

print("Frame editing demonstration complete")

283

284

else:

285

print("PyQt not available - cannot demonstrate frame editor")

286

```

287

288

### Checking GUI Availability

289

290

```python

291

from pytransform3d.editor import qt_available, qt_version

292

293

print(f"PyQt available: {qt_available}")

294

if qt_available:

295

print(f"PyQt version: {qt_version}")

296

print("GUI editor functionality is available")

297

298

# Import GUI classes safely

299

from pytransform3d.editor import TransformEditor, PositionEulerEditor

300

print("Successfully imported GUI classes")

301

302

else:

303

print("PyQt not available")

304

print("Install PyQt5 or PyQt6 to enable GUI functionality:")

305

print(" pip install PyQt5")

306

print(" or")

307

print(" pip install PyQt6")

308

309

# Fallback to non-GUI alternatives

310

print("Using matplotlib-based visualization instead...")

311

# Use standard matplotlib plotting functions

312

```

313

314

## Features

315

316

The interactive editor provides:

317

318

- **Real-time 3D visualization** of transformation changes

319

- **Slider controls** for position and orientation parameters

320

- **Euler angle representation** for intuitive rotation control

321

- **Live update** of transformation matrix display

322

- **Multi-frame editing** capability within transform manager

323

- **Coordinate frame visualization** with customizable scaling

324

- **Configurable workspace limits** for visualization bounds

325

- **Integration with transform manager** for complex kinematic chains

326

327

The editor is particularly useful for:

328

329

- **Robot joint configuration** and workspace exploration

330

- **Camera pose adjustment** for computer vision applications

331

- **Sensor calibration** and mounting parameter optimization

332

- **Interactive debugging** of transformation chains

333

- **Educational visualization** of 3D transformations

334

- **Rapid prototyping** of spatial relationships