Skip to content

Commit 815e5ec

Browse files
committed
Merge branch 'future' of github.com:petercorke/robotics-toolbox-python into future
2 parents db6e9b1 + 6b6136e commit 815e5ec

File tree

7 files changed

+74
-85
lines changed

7 files changed

+74
-85
lines changed

roboticstoolbox/backends/PyPlot/EllipsePlot.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,9 @@ def make_ellipsoid2(self):
192192
# A = np.linalg.inv(A)
193193
# except:
194194
# A = np.zeros((2,2))
195+
if self.vell:
196+
# Do the extra step for the velocity ellipse
197+
A = np.linalg.inv(A)
195198

196199
if isinstance(self.centre, str) and self.centre == "ee":
197200
centre = self.robot.fkine(self.q).A[:3, -1]
@@ -204,7 +207,7 @@ def make_ellipsoid2(self):
204207
# RVC2 p 602
205208
# x = sp.linalg.sqrtm(A) @ y
206209

207-
x, y = base.ellipse(A, inverted=True, centre=centre[:2], scale=self.scale)
210+
x, y = base.ellipse(A, inverted=False, centre=centre[:2], scale=self.scale)
208211
self.x = x
209212
self.y = y
210213
# = x[0,:] * self.scale + centre[0]

roboticstoolbox/blocks/uav.py

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -38,11 +38,18 @@ class MultiRotor(TransferBlock):
3838
vehicle state is a dict containing the following items:
3939

4040
- ``x`` pose in the world frame as :math:`[x, y, z, \theta_Y, \theta_P, \theta_R]`
41-
- ``vb`` translational velocity in the world frame (metres/sec)
42-
- ``w`` angular rates in the world frame as yaw-pitch-roll rates (radians/second)
41+
- ``trans`` position and velocity in the world frame as
42+
:math:`[x, y, z, \dot{x}, \dot{y}, \dot{z}]`
43+
- ``rot`` orientation and angular rate in the world frame as
44+
:math:`[\theta_Y, \theta_P, \theta_R, \dot{\theta_Y}, \dot{\theta_P}, \dot{\theta_R}]`
45+
- ``vb`` translational velocity in the body frame as
46+
:math:`[\dot{x}, \dot{y}, \dot{z}]`
47+
- ``w`` angular rates in the body frame as
48+
:math:`[\dot{\theta_Y}, \dot{\theta_P}, \dot{\theta_R}]`
4349
- ``a1s`` longitudinal flapping angles (radians)
4450
- ``b1s`` lateral flapping angles (radians)
45-
51+
- ``X`` full state vector as
52+
:math:`[x, y, z, \theta_Y, \theta_P, \theta_R, \dot{x}, \dot{y}, \dot{z}, \dot{\theta_Y}, \dot{\theta_P}, \dot{\theta_R}]`
4653

4754
The dynamic model is a dict with the following key/value pairs.
4855

@@ -263,6 +270,8 @@ def output(self, t, inports, x):
263270
out["x"] = x[0:6]
264271
out["trans"] = np.r_[x[:3], vd]
265272
out["rot"] = np.r_[x[3:6], rpyd]
273+
out["vb"] = np.linalg.inv(R) @ x[6:9] # translational velocity mapped to body frame
274+
out["w"] = iW @ x[9:12] # RPY rates mapped to body frame
266275

267276
out["a1s"] = self.a1s
268277
out["b1s"] = self.b1s

roboticstoolbox/models/ETS/Planar2.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,11 +35,11 @@ def __init__(self):
3535

3636
super().__init__([l0, l1, l2], name="Planar2", comment="Planar 2D manipulator")
3737

38-
self.qr = np.array([0, 0])
38+
self.qb = np.array([0, np.pi/2])
3939
self.qz = np.zeros(2)
4040

41-
self.addconfiguration("qr", self.qr)
4241
self.addconfiguration("qz", self.qz)
42+
self.addconfiguration("qb", self.qb)
4343

4444

4545
if __name__ == "__main__": # pragma nocover

roboticstoolbox/robot/DHLink.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -380,11 +380,11 @@ def __repr__(self):
380380
name = self.__class__.__name__
381381
args = []
382382
if self.isrevolute:
383-
self._format(args, "d")
383+
self._format_param(args, "d")
384384
else:
385-
self._format(args, "theta", "θ")
386-
self._format(args, "a")
387-
self._format(args, "alpha", "⍺")
385+
self._format_param(args, "theta", "θ")
386+
self._format_param(args, "a")
387+
self._format_param(args, "alpha", "⍺")
388388
args.extend(super()._params())
389389
return name + "(" + ", ".join(args) + ")"
390390

roboticstoolbox/robot/Link.py

Lines changed: 47 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -1367,61 +1367,62 @@ def format(l, fmt, val): # noqa
13671367

13681368
return dyn
13691369

1370+
def _format_param(
1371+
self, l, name, symbol=None, ignorevalue=None, indices=None
1372+
): # noqa # pragma nocover
1373+
# if value == ignorevalue then don't display it
1374+
1375+
v = getattr(self, name)
1376+
s = None
1377+
if v is None:
1378+
return
1379+
if isinstance(v, str):
1380+
s = f'{name} = "{v}"'
1381+
elif isscalar(v) and v != ignorevalue:
1382+
if symbol is not None:
1383+
s = f"{symbol}={v:.3g}"
1384+
else: # pragma: nocover
1385+
try:
1386+
s = f"{name}={v:.3g}"
1387+
except TypeError:
1388+
s = f"{name}={v}"
1389+
elif isinstance(v, np.ndarray):
1390+
# if np.linalg.norm(v, ord=np.inf) > 0:
1391+
# if indices is not None:
1392+
# flat = v.flatten()
1393+
# v = np.r_[[flat[k] for k in indices]]
1394+
# s = f"{name}=[" + ", ".join([f"{x:.3g}" for x in v]) + "]"
1395+
if indices is not None:
1396+
v = v.ravel()[indices]
1397+
s = f"{name}=" + np.array2string(
1398+
v,
1399+
separator=", ",
1400+
suppress_small=True,
1401+
formatter={"float": lambda x: f"{x:.3g}"},
1402+
)
1403+
if s is not None:
1404+
l.append(s)
1405+
13701406
def _params(self, name: bool = True): # pragma nocover
1371-
def format_param(
1372-
self, l, name, symbol=None, ignorevalue=None, indices=None
1373-
): # noqa # pragma nocover
1374-
# if value == ignorevalue then don't display it
1375-
1376-
v = getattr(self, name)
1377-
s = None
1378-
if v is None:
1379-
return
1380-
if isinstance(v, str):
1381-
s = f'{name} = "{v}"'
1382-
elif isscalar(v) and v != ignorevalue:
1383-
if symbol is not None:
1384-
s = f"{symbol}={v:.3g}"
1385-
else: # pragma: nocover
1386-
try:
1387-
s = f"{name}={v:.3g}"
1388-
except TypeError:
1389-
s = f"{name}={v}"
1390-
elif isinstance(v, np.ndarray):
1391-
# if np.linalg.norm(v, ord=np.inf) > 0:
1392-
# if indices is not None:
1393-
# flat = v.flatten()
1394-
# v = np.r_[[flat[k] for k in indices]]
1395-
# s = f"{name}=[" + ", ".join([f"{x:.3g}" for x in v]) + "]"
1396-
if indices is not None:
1397-
v = v.ravel()[indices]
1398-
s = f"{name}=" + np.array2string(
1399-
v,
1400-
separator=", ",
1401-
suppress_small=True,
1402-
formatter={"float": lambda x: f"{x:.3g}"},
1403-
)
1404-
if s is not None:
1405-
l.append(s)
14061407

14071408
l = [] # noqa
14081409
if name:
1409-
format_param(self, l, "name")
1410+
self._format_param(l, "name")
14101411
if self.parent_name is not None:
14111412
l.append('parent="' + self.parent_name + '"')
14121413
elif isinstance(self.parent, BaseLink):
14131414
l.append('parent="' + self.parent.name + '"')
1414-
format_param(self, l, "parent")
1415-
format_param(self, l, "isflip", ignorevalue=False)
1416-
format_param(self, l, "qlim")
1415+
self._format_param(l, "parent")
1416+
self._format_param(l, "isflip", ignorevalue=False)
1417+
self._format_param(l, "qlim")
14171418
if self._hasdynamics:
1418-
format_param(self, l, "m")
1419-
format_param(self, l, "r")
1420-
format_param(self, l, "I", indices=[0, 4, 8, 1, 2, 5])
1421-
format_param(self, l, "Jm")
1422-
format_param(self, l, "B")
1423-
format_param(self, l, "Tc")
1424-
format_param(self, l, "G")
1419+
self._format_param(l, "m")
1420+
self._format_param(l, "r")
1421+
self._format_param(l, "I", indices=[0, 4, 8, 1, 2, 5])
1422+
self._format_param(l, "Jm")
1423+
self._format_param(l, "B")
1424+
self._format_param(l, "Tc")
1425+
self._format_param(l, "G")
14251426

14261427
return l
14271428

roboticstoolbox/robot/PoERobot.py

Lines changed: 4 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -33,18 +33,6 @@ def __str__(self):
3333
s += "]"
3434
return s
3535

36-
def _repr_pretty_(self, p, cycle):
37-
"""
38-
Pretty string for IPython (superclass method)
39-
40-
:param p: pretty printer handle (ignored)
41-
:param cycle: pretty printer flag (ignored)
42-
43-
"""
44-
# see https://ipython.org/ipython-doc/stable/api/generated/IPython.lib.pretty.html
45-
46-
p.text(f"{i}:\n{str(x)}")
47-
4836

4937
class PoERevolute(PoELink):
5038
def __init__(self, axis, point, **kwargs):
@@ -114,26 +102,14 @@ def __str__(self):
114102
return s
115103

116104
def __repr__(self):
117-
s = "PoERobot([\n "
118-
for j, link in enumerate(self):
119-
s += repr(link) + ","
120-
s += "],\n"
105+
s = "PoERobot([\n"
106+
s += "\n".join([" " + repr(link) + "," for link in self])
107+
s += "\n ],\n"
121108
s += f" T0=SE3({np.array_repr(self.T0.A)}),\n"
122-
s += f" name={self.name},\n"
109+
s += f" name=\"{self.name}\",\n"
123110
s += ")"
124111
return s
125112

126-
def _repr_pretty_(self, p, cycle):
127-
"""
128-
Pretty string for IPython (superclass method)
129-
130-
:param p: pretty printer handle (ignored)
131-
:param cycle: pretty printer flag (ignored)
132-
133-
"""
134-
# see https://ipython.org/ipython-doc/stable/api/generated/IPython.lib.pretty.html
135-
136-
p.text(f"{i}:\n{str(x)}")
137113

138114
def nbranches(self):
139115
return 0

tests/test_ERobot.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -170,7 +170,7 @@ def test_teach(self):
170170
def test_plot_with_vellipse(self):
171171
robot = rtb.models.ETS.Planar2()
172172
e = robot.plot(
173-
robot.qz, block=False, name=True, vellipse=True, limits=[1, 2, 1, 2]
173+
robot.qb, block=False, name=True, vellipse=True, limits=[1, 2, 1, 2]
174174
)
175175
e.step()
176176
e.close()

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy