moro 0.3.0.dev0__tar.gz → 0.5.0__tar.gz
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.
- moro-0.5.0/PKG-INFO +224 -0
- moro-0.5.0/README.md +194 -0
- moro-0.5.0/moro/__init__.py +41 -0
- {moro-0.3.0.dev0 → moro-0.5.0}/moro/abc.py +9 -13
- moro-0.5.0/moro/core.py +1323 -0
- moro-0.5.0/moro/differential_kinematics.py +877 -0
- moro-0.5.0/moro/dynamics.py +496 -0
- moro-0.5.0/moro/inverse_kinematics.py +2273 -0
- moro-0.5.0/moro/lib.py +1 -0
- moro-0.5.0/moro/plotting.py +482 -0
- moro-0.5.0/moro/trajectory.py +431 -0
- moro-0.5.0/moro/transformations.py +1462 -0
- {moro-0.3.0.dev0 → moro-0.5.0}/moro/util.py +45 -55
- moro-0.5.0/moro/version.py +1 -0
- moro-0.5.0/moro/visualization/__init__.py +32 -0
- moro-0.5.0/moro/visualization/data.py +41 -0
- moro-0.5.0/moro/visualization/evaluation.py +50 -0
- moro-0.5.0/moro/visualization/matplotlib_backend.py +216 -0
- moro-0.5.0/moro/visualization/style.py +71 -0
- moro-0.5.0/moro/visualization/templates/__init__.py +0 -0
- moro-0.5.0/moro/visualization/templates/threejs_animation.html +572 -0
- moro-0.5.0/moro/visualization/templates/threejs_common.js +937 -0
- moro-0.5.0/moro/visualization/templates/threejs_viewer.html +303 -0
- moro-0.5.0/moro/visualization/threejs_backend.py +203 -0
- moro-0.5.0/moro/visualization/visualizer.py +151 -0
- moro-0.5.0/moro/visualization/workspace.py +138 -0
- moro-0.5.0/moro/workspace.py +281 -0
- moro-0.5.0/moro.egg-info/PKG-INFO +224 -0
- moro-0.5.0/moro.egg-info/SOURCES.txt +43 -0
- {moro-0.3.0.dev0 → moro-0.5.0}/moro.egg-info/requires.txt +2 -0
- moro-0.5.0/pyproject.toml +60 -0
- moro-0.5.0/setup.cfg +4 -0
- moro-0.5.0/tests/test_core.py +503 -0
- moro-0.5.0/tests/test_differential_kinematics.py +1229 -0
- moro-0.5.0/tests/test_dynamics.py +461 -0
- moro-0.5.0/tests/test_dynamics_hardening.py +230 -0
- moro-0.5.0/tests/test_inverse_kinematics.py +2046 -0
- moro-0.5.0/tests/test_release_hardening.py +260 -0
- moro-0.5.0/tests/test_trajectory.py +436 -0
- moro-0.5.0/tests/test_transformations.py +1306 -0
- moro-0.5.0/tests/test_visualization.py +901 -0
- moro-0.5.0/tests/test_workspace.py +275 -0
- moro-0.3.0.dev0/PKG-INFO +0 -62
- moro-0.3.0.dev0/README.md +0 -32
- moro-0.3.0.dev0/moro/__init__.py +0 -25
- moro-0.3.0.dev0/moro/core.py +0 -893
- moro-0.3.0.dev0/moro/inverse_kinematics.py +0 -149
- moro-0.3.0.dev0/moro/lib.py +0 -126
- moro-0.3.0.dev0/moro/plotting.py +0 -99
- moro-0.3.0.dev0/moro/transformations.py +0 -757
- moro-0.3.0.dev0/moro/version.py +0 -1
- moro-0.3.0.dev0/moro/ws.py +0 -89
- moro-0.3.0.dev0/moro.egg-info/PKG-INFO +0 -62
- moro-0.3.0.dev0/moro.egg-info/SOURCES.txt +0 -19
- moro-0.3.0.dev0/setup.cfg +0 -7
- moro-0.3.0.dev0/setup.py +0 -34
- {moro-0.3.0.dev0 → moro-0.5.0}/LICENSE.txt +0 -0
- {moro-0.3.0.dev0 → moro-0.5.0}/moro.egg-info/dependency_links.txt +0 -0
- {moro-0.3.0.dev0 → moro-0.5.0}/moro.egg-info/top_level.txt +0 -0
moro-0.5.0/PKG-INFO
ADDED
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: moro
|
|
3
|
+
Version: 0.5.0
|
|
4
|
+
Summary: Python library for kinematic and dynamic modeling of robots
|
|
5
|
+
Author-email: Pedro Jorge De Los Santos <delossantosmfq@gmail.com>
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/JorgeDeLosSantos/moro
|
|
8
|
+
Project-URL: Repository, https://github.com/JorgeDeLosSantos/moro
|
|
9
|
+
Project-URL: Issues, https://github.com/JorgeDeLosSantos/moro/issues
|
|
10
|
+
Keywords: robotics,kinematics,dynamics
|
|
11
|
+
Classifier: Development Status :: 2 - Pre-Alpha
|
|
12
|
+
Classifier: Intended Audience :: Education
|
|
13
|
+
Classifier: Intended Audience :: Developers
|
|
14
|
+
Classifier: Operating System :: OS Independent
|
|
15
|
+
Classifier: Programming Language :: Python
|
|
16
|
+
Classifier: Programming Language :: Python :: 3
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
21
|
+
Classifier: Programming Language :: Python :: Implementation :: CPython
|
|
22
|
+
Requires-Python: >=3.11
|
|
23
|
+
Description-Content-Type: text/markdown
|
|
24
|
+
License-File: LICENSE.txt
|
|
25
|
+
Requires-Dist: sympy
|
|
26
|
+
Requires-Dist: numpy
|
|
27
|
+
Requires-Dist: matplotlib
|
|
28
|
+
Requires-Dist: scipy
|
|
29
|
+
Dynamic: license-file
|
|
30
|
+
|
|
31
|
+
# moro
|
|
32
|
+
|
|
33
|
+
[](https://pypi.org/project/moro/)
|
|
34
|
+
[](https://github.com/JorgeDeLosSantos/moro/blob/master/LICENSE.txt)
|
|
35
|
+
|
|
36
|
+
`moro` is a Python library for symbolic modeling, analysis, numerical simulation, and visualization of serial robot manipulators.
|
|
37
|
+
|
|
38
|
+
It is designed primarily for robotics education and for workflows where inspecting the underlying kinematic and dynamic expressions is as important as evaluating them numerically.
|
|
39
|
+
|
|
40
|
+
## Features
|
|
41
|
+
|
|
42
|
+
* **Robot modeling:** Define serial manipulators with revolute and prismatic joints using Denavit-Hartenberg parameters.
|
|
43
|
+
* **Transformations:** Work with `SO(3)` rotations, `SE(3)` homogeneous transformations, Euler/Tait-Bryan angles, axis-angle, quaternions, and rotation vectors.
|
|
44
|
+
* **Forward kinematics:** Compute symbolic end-effector and intermediate-frame transformations.
|
|
45
|
+
* **Differential kinematics:** Evaluate task Jacobians, Cartesian velocities, velocity IK, singular values, numerical rank, condition number, and manipulability.
|
|
46
|
+
* **Inverse kinematics:** Solve numerical Cartesian position IK and full-pose IK with Jacobian-based methods; position-only CCD remains available.
|
|
47
|
+
* **Trajectory generation:** Generate linear, cubic, and quintic point-to-point trajectories in joint or Cartesian position space.
|
|
48
|
+
* **Dynamics:** Derive symbolic equations of motion, evaluate inverse/forward dynamics numerically, and integrate motion with `solve_ivp`.
|
|
49
|
+
* **Workspace sampling:** Approximate reachable Cartesian workspace from finite joint ranges with reproducible joint-space sampling.
|
|
50
|
+
* **Visualization:** Plot and animate robot configurations using Matplotlib or Three.js, and plot sampled workspaces with Matplotlib.
|
|
51
|
+
|
|
52
|
+
## Installation
|
|
53
|
+
|
|
54
|
+
Install the latest stable release from PyPI:
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
pip install moro
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
To install the current development version from GitHub:
|
|
61
|
+
|
|
62
|
+
```bash
|
|
63
|
+
pip install git+https://github.com/JorgeDeLosSantos/moro.git
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
Moro 0.5.x requires **Python 3.11 or newer**.
|
|
67
|
+
|
|
68
|
+
Its main runtime dependencies are SymPy, NumPy, Matplotlib, and SciPy.
|
|
69
|
+
|
|
70
|
+
## Quick Start
|
|
71
|
+
|
|
72
|
+
The following example creates a symbolic planar 2R manipulator and evaluates its forward kinematics and Jacobian at one configuration:
|
|
73
|
+
|
|
74
|
+
```python
|
|
75
|
+
from moro import Robot
|
|
76
|
+
from moro.abc import q1, q2, l1, l2
|
|
77
|
+
|
|
78
|
+
robot = Robot(
|
|
79
|
+
(l1, 0, 0, q1, "r"),
|
|
80
|
+
(l2, 0, 0, q2, "r"),
|
|
81
|
+
)
|
|
82
|
+
|
|
83
|
+
T = robot.T
|
|
84
|
+
J = robot.J
|
|
85
|
+
|
|
86
|
+
values = {
|
|
87
|
+
l1: 1.0,
|
|
88
|
+
l2: 1.0,
|
|
89
|
+
q1: 0.5,
|
|
90
|
+
q2: 0.8,
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
T_num = T.subs(values).evalf()
|
|
94
|
+
J_num = J.subs(values).evalf()
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
The same symbolic model can be visualized:
|
|
98
|
+
|
|
99
|
+
```python
|
|
100
|
+
from moro.visualization import RobotVisualizer
|
|
101
|
+
|
|
102
|
+
viz = RobotVisualizer(robot)
|
|
103
|
+
viz.plot(values)
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
For interactive visualization in a notebook:
|
|
107
|
+
|
|
108
|
+
```python
|
|
109
|
+
viz.plot(values, backend="threejs")
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
## Inverse Kinematics
|
|
113
|
+
|
|
114
|
+
Position IK:
|
|
115
|
+
|
|
116
|
+
```python
|
|
117
|
+
from moro.inverse_kinematics import solve_position_ik
|
|
118
|
+
|
|
119
|
+
solution = solve_position_ik(
|
|
120
|
+
robot,
|
|
121
|
+
[1.5, 0.5, 0.0],
|
|
122
|
+
q0=[0.1, 0.1],
|
|
123
|
+
parameters={l1: 1.0, l2: 1.0},
|
|
124
|
+
)
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
Full-pose IK is available through:
|
|
128
|
+
|
|
129
|
+
```python
|
|
130
|
+
from moro.inverse_kinematics import solve_pose_ik
|
|
131
|
+
|
|
132
|
+
solution = solve_pose_ik(
|
|
133
|
+
robot,
|
|
134
|
+
target_transform,
|
|
135
|
+
q0=initial_guess,
|
|
136
|
+
parameters=parameters,
|
|
137
|
+
)
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
## Trajectories
|
|
141
|
+
|
|
142
|
+
Generate a smooth joint-space trajectory with:
|
|
143
|
+
|
|
144
|
+
```python
|
|
145
|
+
import numpy as np
|
|
146
|
+
from moro.trajectory import joint_trajectory
|
|
147
|
+
|
|
148
|
+
traj = joint_trajectory(
|
|
149
|
+
[0.0, 0.0],
|
|
150
|
+
[0.8, -0.4],
|
|
151
|
+
np.linspace(0.0, 2.0, 101),
|
|
152
|
+
method="quintic",
|
|
153
|
+
)
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
The result uses time-major arrays such as `traj.q.shape == (N, dof)` and can be passed directly to `RobotVisualizer.animate()`.
|
|
157
|
+
|
|
158
|
+
## Dynamics and Simulation
|
|
159
|
+
|
|
160
|
+
After assigning masses, centers of mass, inertia tensors, and gravity, the symbolic manipulator equation is obtained with:
|
|
161
|
+
|
|
162
|
+
```python
|
|
163
|
+
model = robot.dynamic_model()
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
In Moro 0.5.0, `dynamic_model()` returns the matrix-form equation
|
|
167
|
+
|
|
168
|
+
```text
|
|
169
|
+
M(q) qdd + C(q, qd) qd + G(q) = tau
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
The former per-joint Euler-Lagrange behavior is available as:
|
|
173
|
+
|
|
174
|
+
```python
|
|
175
|
+
equations = robot.euler_lagrange_equations()
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
Numerical dynamics and simulation live in `moro.dynamics`:
|
|
179
|
+
|
|
180
|
+
```python
|
|
181
|
+
from moro.dynamics import inverse_dynamics, forward_dynamics, simulate
|
|
182
|
+
|
|
183
|
+
forces = inverse_dynamics(robot, q, qd, qdd, parameters=parameters)
|
|
184
|
+
acceleration = forward_dynamics(robot, q, qd, forces, parameters=parameters)
|
|
185
|
+
|
|
186
|
+
solution = simulate(
|
|
187
|
+
robot,
|
|
188
|
+
(0.0, 2.0),
|
|
189
|
+
q0,
|
|
190
|
+
qd0=qd0,
|
|
191
|
+
tau=controller,
|
|
192
|
+
parameters=parameters,
|
|
193
|
+
)
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
## Workspace Sampling
|
|
197
|
+
|
|
198
|
+
```python
|
|
199
|
+
from moro.workspace import sample_workspace
|
|
200
|
+
from moro.visualization import plot_workspace
|
|
201
|
+
|
|
202
|
+
workspace = sample_workspace(robot, samples=5000, seed=42)
|
|
203
|
+
fig, ax = plot_workspace(workspace)
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
Workspace samples are uniform in joint coordinates, not Cartesian space. The result stores both `workspace.configurations` and their corresponding Cartesian `workspace.points`.
|
|
207
|
+
|
|
208
|
+
## Documentation
|
|
209
|
+
|
|
210
|
+
The complete documentation is available at:
|
|
211
|
+
|
|
212
|
+
https://jorgedelossantos.github.io/moro/
|
|
213
|
+
|
|
214
|
+
It includes Getting Started guides, User Guide, worked examples, API Reference, mathematical Theory notes, and contributor documentation.
|
|
215
|
+
|
|
216
|
+
## Roadmap
|
|
217
|
+
|
|
218
|
+
Want to know what may come next? See the [Moro Roadmap Wiki](https://github.com/JorgeDeLosSantos/moro/wiki/Roadmap).
|
|
219
|
+
|
|
220
|
+
## Bug Reports and Contributions
|
|
221
|
+
|
|
222
|
+
If you encounter a bug, have a question, or want to request a feature, please open an issue in the [GitHub Issue Tracker](https://github.com/JorgeDeLosSantos/moro/issues).
|
|
223
|
+
|
|
224
|
+
Contributions are welcome. See the contributor documentation included in the project documentation for the recommended development workflow.
|
moro-0.5.0/README.md
ADDED
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
# moro
|
|
2
|
+
|
|
3
|
+
[](https://pypi.org/project/moro/)
|
|
4
|
+
[](https://github.com/JorgeDeLosSantos/moro/blob/master/LICENSE.txt)
|
|
5
|
+
|
|
6
|
+
`moro` is a Python library for symbolic modeling, analysis, numerical simulation, and visualization of serial robot manipulators.
|
|
7
|
+
|
|
8
|
+
It is designed primarily for robotics education and for workflows where inspecting the underlying kinematic and dynamic expressions is as important as evaluating them numerically.
|
|
9
|
+
|
|
10
|
+
## Features
|
|
11
|
+
|
|
12
|
+
* **Robot modeling:** Define serial manipulators with revolute and prismatic joints using Denavit-Hartenberg parameters.
|
|
13
|
+
* **Transformations:** Work with `SO(3)` rotations, `SE(3)` homogeneous transformations, Euler/Tait-Bryan angles, axis-angle, quaternions, and rotation vectors.
|
|
14
|
+
* **Forward kinematics:** Compute symbolic end-effector and intermediate-frame transformations.
|
|
15
|
+
* **Differential kinematics:** Evaluate task Jacobians, Cartesian velocities, velocity IK, singular values, numerical rank, condition number, and manipulability.
|
|
16
|
+
* **Inverse kinematics:** Solve numerical Cartesian position IK and full-pose IK with Jacobian-based methods; position-only CCD remains available.
|
|
17
|
+
* **Trajectory generation:** Generate linear, cubic, and quintic point-to-point trajectories in joint or Cartesian position space.
|
|
18
|
+
* **Dynamics:** Derive symbolic equations of motion, evaluate inverse/forward dynamics numerically, and integrate motion with `solve_ivp`.
|
|
19
|
+
* **Workspace sampling:** Approximate reachable Cartesian workspace from finite joint ranges with reproducible joint-space sampling.
|
|
20
|
+
* **Visualization:** Plot and animate robot configurations using Matplotlib or Three.js, and plot sampled workspaces with Matplotlib.
|
|
21
|
+
|
|
22
|
+
## Installation
|
|
23
|
+
|
|
24
|
+
Install the latest stable release from PyPI:
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
pip install moro
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
To install the current development version from GitHub:
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
pip install git+https://github.com/JorgeDeLosSantos/moro.git
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
Moro 0.5.x requires **Python 3.11 or newer**.
|
|
37
|
+
|
|
38
|
+
Its main runtime dependencies are SymPy, NumPy, Matplotlib, and SciPy.
|
|
39
|
+
|
|
40
|
+
## Quick Start
|
|
41
|
+
|
|
42
|
+
The following example creates a symbolic planar 2R manipulator and evaluates its forward kinematics and Jacobian at one configuration:
|
|
43
|
+
|
|
44
|
+
```python
|
|
45
|
+
from moro import Robot
|
|
46
|
+
from moro.abc import q1, q2, l1, l2
|
|
47
|
+
|
|
48
|
+
robot = Robot(
|
|
49
|
+
(l1, 0, 0, q1, "r"),
|
|
50
|
+
(l2, 0, 0, q2, "r"),
|
|
51
|
+
)
|
|
52
|
+
|
|
53
|
+
T = robot.T
|
|
54
|
+
J = robot.J
|
|
55
|
+
|
|
56
|
+
values = {
|
|
57
|
+
l1: 1.0,
|
|
58
|
+
l2: 1.0,
|
|
59
|
+
q1: 0.5,
|
|
60
|
+
q2: 0.8,
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
T_num = T.subs(values).evalf()
|
|
64
|
+
J_num = J.subs(values).evalf()
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
The same symbolic model can be visualized:
|
|
68
|
+
|
|
69
|
+
```python
|
|
70
|
+
from moro.visualization import RobotVisualizer
|
|
71
|
+
|
|
72
|
+
viz = RobotVisualizer(robot)
|
|
73
|
+
viz.plot(values)
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
For interactive visualization in a notebook:
|
|
77
|
+
|
|
78
|
+
```python
|
|
79
|
+
viz.plot(values, backend="threejs")
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
## Inverse Kinematics
|
|
83
|
+
|
|
84
|
+
Position IK:
|
|
85
|
+
|
|
86
|
+
```python
|
|
87
|
+
from moro.inverse_kinematics import solve_position_ik
|
|
88
|
+
|
|
89
|
+
solution = solve_position_ik(
|
|
90
|
+
robot,
|
|
91
|
+
[1.5, 0.5, 0.0],
|
|
92
|
+
q0=[0.1, 0.1],
|
|
93
|
+
parameters={l1: 1.0, l2: 1.0},
|
|
94
|
+
)
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
Full-pose IK is available through:
|
|
98
|
+
|
|
99
|
+
```python
|
|
100
|
+
from moro.inverse_kinematics import solve_pose_ik
|
|
101
|
+
|
|
102
|
+
solution = solve_pose_ik(
|
|
103
|
+
robot,
|
|
104
|
+
target_transform,
|
|
105
|
+
q0=initial_guess,
|
|
106
|
+
parameters=parameters,
|
|
107
|
+
)
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
## Trajectories
|
|
111
|
+
|
|
112
|
+
Generate a smooth joint-space trajectory with:
|
|
113
|
+
|
|
114
|
+
```python
|
|
115
|
+
import numpy as np
|
|
116
|
+
from moro.trajectory import joint_trajectory
|
|
117
|
+
|
|
118
|
+
traj = joint_trajectory(
|
|
119
|
+
[0.0, 0.0],
|
|
120
|
+
[0.8, -0.4],
|
|
121
|
+
np.linspace(0.0, 2.0, 101),
|
|
122
|
+
method="quintic",
|
|
123
|
+
)
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
The result uses time-major arrays such as `traj.q.shape == (N, dof)` and can be passed directly to `RobotVisualizer.animate()`.
|
|
127
|
+
|
|
128
|
+
## Dynamics and Simulation
|
|
129
|
+
|
|
130
|
+
After assigning masses, centers of mass, inertia tensors, and gravity, the symbolic manipulator equation is obtained with:
|
|
131
|
+
|
|
132
|
+
```python
|
|
133
|
+
model = robot.dynamic_model()
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
In Moro 0.5.0, `dynamic_model()` returns the matrix-form equation
|
|
137
|
+
|
|
138
|
+
```text
|
|
139
|
+
M(q) qdd + C(q, qd) qd + G(q) = tau
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
The former per-joint Euler-Lagrange behavior is available as:
|
|
143
|
+
|
|
144
|
+
```python
|
|
145
|
+
equations = robot.euler_lagrange_equations()
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
Numerical dynamics and simulation live in `moro.dynamics`:
|
|
149
|
+
|
|
150
|
+
```python
|
|
151
|
+
from moro.dynamics import inverse_dynamics, forward_dynamics, simulate
|
|
152
|
+
|
|
153
|
+
forces = inverse_dynamics(robot, q, qd, qdd, parameters=parameters)
|
|
154
|
+
acceleration = forward_dynamics(robot, q, qd, forces, parameters=parameters)
|
|
155
|
+
|
|
156
|
+
solution = simulate(
|
|
157
|
+
robot,
|
|
158
|
+
(0.0, 2.0),
|
|
159
|
+
q0,
|
|
160
|
+
qd0=qd0,
|
|
161
|
+
tau=controller,
|
|
162
|
+
parameters=parameters,
|
|
163
|
+
)
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
## Workspace Sampling
|
|
167
|
+
|
|
168
|
+
```python
|
|
169
|
+
from moro.workspace import sample_workspace
|
|
170
|
+
from moro.visualization import plot_workspace
|
|
171
|
+
|
|
172
|
+
workspace = sample_workspace(robot, samples=5000, seed=42)
|
|
173
|
+
fig, ax = plot_workspace(workspace)
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
Workspace samples are uniform in joint coordinates, not Cartesian space. The result stores both `workspace.configurations` and their corresponding Cartesian `workspace.points`.
|
|
177
|
+
|
|
178
|
+
## Documentation
|
|
179
|
+
|
|
180
|
+
The complete documentation is available at:
|
|
181
|
+
|
|
182
|
+
https://jorgedelossantos.github.io/moro/
|
|
183
|
+
|
|
184
|
+
It includes Getting Started guides, User Guide, worked examples, API Reference, mathematical Theory notes, and contributor documentation.
|
|
185
|
+
|
|
186
|
+
## Roadmap
|
|
187
|
+
|
|
188
|
+
Want to know what may come next? See the [Moro Roadmap Wiki](https://github.com/JorgeDeLosSantos/moro/wiki/Roadmap).
|
|
189
|
+
|
|
190
|
+
## Bug Reports and Contributions
|
|
191
|
+
|
|
192
|
+
If you encounter a bug, have a question, or want to request a feature, please open an issue in the [GitHub Issue Tracker](https://github.com/JorgeDeLosSantos/moro/issues).
|
|
193
|
+
|
|
194
|
+
Contributions are welcome. See the contributor documentation included in the project documentation for the recommended development workflow.
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Numython R&D, (c) 2026
|
|
3
|
+
Moro is a Python library for kinematic and dynamic modeling of serial robots.
|
|
4
|
+
This library has been designed, mainly, for academic and research purposes,
|
|
5
|
+
using SymPy as base library.
|
|
6
|
+
"""
|
|
7
|
+
from .version import __version__
|
|
8
|
+
|
|
9
|
+
from .core import Robot
|
|
10
|
+
from .util import enable_vprinting
|
|
11
|
+
from .transformations import (
|
|
12
|
+
rotx, roty, rotz,
|
|
13
|
+
rot2eul, eul2rot,
|
|
14
|
+
axa2rot, rot2axa,
|
|
15
|
+
htmtra, htmrot,
|
|
16
|
+
rot2htm, rt2htm,
|
|
17
|
+
htm2rot, htm2tra,
|
|
18
|
+
invhtm,
|
|
19
|
+
dh
|
|
20
|
+
)
|
|
21
|
+
|
|
22
|
+
__all__ = [
|
|
23
|
+
"__version__",
|
|
24
|
+
"Robot",
|
|
25
|
+
"enable_vprinting",
|
|
26
|
+
"rotx",
|
|
27
|
+
"roty",
|
|
28
|
+
"rotz",
|
|
29
|
+
"rot2eul",
|
|
30
|
+
"eul2rot",
|
|
31
|
+
"axa2rot",
|
|
32
|
+
"rot2axa",
|
|
33
|
+
"htmtra",
|
|
34
|
+
"htmrot",
|
|
35
|
+
"rot2htm",
|
|
36
|
+
"rt2htm",
|
|
37
|
+
"htm2rot",
|
|
38
|
+
"htm2tra",
|
|
39
|
+
"invhtm",
|
|
40
|
+
"dh"
|
|
41
|
+
]
|
|
@@ -3,17 +3,15 @@ from sympy.physics.mechanics import dynamicsymbols
|
|
|
3
3
|
|
|
4
4
|
t = symbols("t") # time
|
|
5
5
|
q1,q2,q3,q4,q5,q6 = dynamicsymbols('q_1:7') # joint variables
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
6
|
+
qd1,qd2,qd3,qd4,qd5,qd6 = [q.diff(t) for q in (q1,q2,q3,q4,q5,q6)] # joint velocities
|
|
7
|
+
qdd1,qdd2,qdd3,qdd4,qdd5,qdd6 = [qd.diff(t) for qd in (qd1,qd2,qd3,qd4,qd5,qd6)] # joint accelerations
|
|
8
|
+
theta1,theta2,theta3,theta4,theta5,theta6 = symbols('theta_1:7', real=True) # theta parameter
|
|
9
9
|
l1,l2,l3,l4,l5,l6 = symbols('l_1:7', real=True) # parameters for constant lengths of the robot
|
|
10
10
|
lc1,lc2,lc3,lc4,lc5,lc6 = symbols('l_c1:7', real=True) # parameters for center of mass location
|
|
11
11
|
d1,d2,d3,d4,d5,d6 = symbols('d_1:7', real=True) # for constant lengths of the robot
|
|
12
12
|
m1,m2,m3,m4,m5,m6 = symbols('m_1:7', real=True) # for mass symbols
|
|
13
13
|
a1,a2,a3,a4,a5,a6 = symbols('a_1:7', real=True) # for constant lengths of the robot
|
|
14
|
-
|
|
15
|
-
y0,y1,y2,y3,y4,y5,y6 = symbols("y_0:7", real=True)
|
|
16
|
-
z0,z1,z2,z3,z4,z5,z6 = symbols("z_0:7", real=True)
|
|
14
|
+
alpha1,alpha2,alpha3,alpha4,alpha5,alpha6 = symbols('alpha_1:7', real=True) # for DH parameters
|
|
17
15
|
g = symbols("g") # gravity
|
|
18
16
|
tau1,tau2,tau3,tau4,tau5,tau6 = symbols("tau_1:7", real=True) # for generalized forces/torques
|
|
19
17
|
|
|
@@ -25,20 +23,18 @@ xi,omicron,rho,sigma = symbols("xi,omicron,rho,sigma", real=True)
|
|
|
25
23
|
tau,upsilon,phi,chi = symbols("tau,upsilon,phi,chi", real=True)
|
|
26
24
|
psi,omega = symbols("psi,omega", real=True)
|
|
27
25
|
|
|
28
|
-
|
|
26
|
+
|
|
29
27
|
available_symvars = [g,t,
|
|
30
28
|
q1,q2,q3,q4,q5,q6,
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
29
|
+
qd1,qd2,qd3,qd4,qd5,qd6,
|
|
30
|
+
qdd1,qdd2,qdd3,qdd4,qdd5,qdd6,
|
|
31
|
+
theta1,theta2,theta3,theta4,theta5,theta6,
|
|
32
|
+
alpha1,alpha2,alpha3,alpha4,alpha5,alpha6,
|
|
34
33
|
l1,l2,l3,l4,l5,l6,
|
|
35
34
|
lc1,lc2,lc3,lc4,lc5,lc6,
|
|
36
35
|
d1,d2,d3,d4,d5,d6,
|
|
37
36
|
m1,m2,m3,m4,m5,m6,
|
|
38
37
|
a1,a2,a3,a4,a5,a6,
|
|
39
|
-
x0,x1,x2,x3,x4,x5,x6,
|
|
40
|
-
y0,y1,y2,y3,y4,y5,y6,
|
|
41
|
-
z0,z1,z2,z3,z4,z5,z6,
|
|
42
38
|
alpha,beta,gamma,delta,
|
|
43
39
|
epsilon,zeta,eta,theta,
|
|
44
40
|
iota,kappa,mu,nu,
|