def __str__(self): """ Pretty prints the ETS Model of the robot. Will output angles in degrees :return: Pretty print of the robot model :rtype: str Constant links are shown in blue. End-effector links are prefixed with an @ """ table = ANSITable(Column("id", headalign="^"), Column("link", headalign="^"), Column("parent", headalign="^"), Column("joint", headalign="^"), Column("ETS", headalign="^", colalign=">"), border="thin") for k, link in enumerate(self): color = "" if link.isjoint else "<<blue>>" ee = "@" if link in self.ee_links else "" ets = link.ets() table.row(k, color + ee + link.name, link.parent.name if link.parent is not None else "-", link._joint_name if link.parent is not None else "", ets.__str__(f"q{link._jindex}")) s = str(table) s += self.configurations_str() return s
def configurations_str(self): deg = 180 / np.pi # TODO: factor this out of DHRobot def angle(theta, fmt=None): if fmt is not None: return fmt.format(theta * deg) + "\u00b0" else: return str(theta * deg) + "\u00b0" config = self.config() # show named configurations if len(self._configdict) > 0: table = ANSITable(Column("name", colalign=">"), *[ Column(f"q{j:d}", colalign="<", headalign="<") for j in range(self.n) ], border="thin") for name, q in self._configdict.items(): qlist = [] for i, c in enumerate(config): if c == 'P': qlist.append(f"{q[i]: .3g}") else: qlist.append(angle(q[i], "{: .3g}")) table.row(name, *qlist) return "\n" + str(table) else: return ""
def __repr__(self): table = ANSITable(Column("id"), Column("centroid"), Column("strength", fmt="{:.3g}"), Column("scale", fmt="{:.3g}"), border="thin") for i, f in enumerate(self): table.row(i, f"{f.u:.1f}, {f.v:.1f}", f.strength, f.scale) return str(table)
def __repr__(self): # s = "" for i, blob in enumerate(self): s += f"{i}: # area={blob.area:.1f} @ ({blob.uc:.1f}, {blob.vc:.1f}), # touch={blob.touch}, orient={blob.orientation * 180 / np.pi:.1f}°, # aspect={blob.aspect:.2f}, circularity={blob.circularity:.2f}, # parent={blob._parent}\n" # return s table = ANSITable(Column("id"), Column("parent"), Column("centroid"), Column("area", fmt="{:.3g}"), Column("touch"), Column("perim", fmt="{:.1f}"), Column("circularity", fmt="{:.3f}"), Column("orient", fmt="{:.1f}°"), Column("aspect", fmt="{:.3g}"), border="thin") for i, b in enumerate(self): table.row(i, b.parent, f"{b.u:.1f}, {b.v:.1f}", b.area, b.touch, b.perimeter, b.circularity, b.orientation * 180 / np.pi, b.aspect) return str(table)
def make_table(border): table = ANSITable(Column("class", headalign="^", colalign="<"), Column("name", headalign="^", colalign="<"), Column("manufacturer", headalign="^", colalign="<"), Column("type", headalign="^", colalign="<"), Column("DoF", colalign="<"), Column("dims", colalign="<"), Column("structure", colalign="<"), Column("dynamics", colalign="<"), Column("geometry", colalign="<"), Column("keywords", headalign="^", colalign="<"), border=border) if mtype is not None: categories = [mtype] else: categories = ['DH', 'URDF', 'ETS'] for category in categories: group = m.__dict__[category] for cls in group.__dict__.values(): if isinstance(cls, type) and issubclass(cls, Robot): # we found a BaseRobot subclass, instantiate it try: robot = cls() except: print(f"failed to load {cls}") try: structure = robot.structure except Exception: # pragma nocover structure = "" # apply filters if keywords is not None: if len(set(keywords) & set(robot.keywords)) == 0: continue if dof is not None and robot.n != dof: continue # pragma nocover dims = 0 if isinstance(robot, ERobot2): dims = 2 else: dims = 3 # add the row table.row(cls.__name__, robot.name, robot.manufacturer, category, robot.n, f"{dims}d", structure, 'Y' if robot._hasdynamics else '', 'Y' if robot._hasgeometry else '', ', '.join(robot.keywords)) table.print()
def dyntable(self): """ Pretty print the dynamic parameters (Robot superclass) The dynamic parameters are printed in a table, with one row per link. Example: .. runblock:: pycon >>> import roboticstoolbox as rtb >>> robot = rtb.models.DH.Puma560() >>> robot.links[2].dyntable() >>> import roboticstoolbox as rtb >>> robot = rtb.models.DH.Puma560() >>> robot.dyntable() """ table = ANSITable(Column("j", colalign=">", headalign="^"), Column("m", colalign="<", headalign="^"), Column("r", colalign="<", headalign="^"), Column("I", colalign="<", headalign="^"), Column("Jm", colalign="<", headalign="^"), Column("B", colalign="<", headalign="^"), Column("Tc", colalign="<", headalign="^"), Column("G", colalign="<", headalign="^"), border="thin") for j, link in enumerate(self): table.row(link.name, *link._dyn2list()) return str(table)
def test_table_5(self): ans = r""" col1 column 2 has a big header column 3 aaaaaaaaa 2.2 3.0000 bbbbbbbbb… -5.5 6.0000 ccccccc 8.8 -9.0000 """ table = ANSITable(Column("col1", width=10), Column("column 2 has a big header", "{:.3g}"), Column("column 3", "{:-10.4f}"), color=False) table.row("aaaaaaaaa", 2.2, 3) table.row("bbbbbbbbbbbbb", -5.5, 6) table.row("ccccccc", 8.8, -9) self.assertEqual(str(table), ans)
def test_table_3(self): ans = r""" col1 column 2 has a big header column 3 aaaaaaaaa 2.2 3 bbbbbbbbbbbbb -5.5 6 ccccccc 8.8 -9 """ table = ANSITable(Column("col1"), Column("column 2 has a big header"), Column("column 3"), color=False) table.row("aaaaaaaaa", 2.2, 3) table.row("bbbbbbbbbbbbb", -5.5, 6) table.row("ccccccc", 8.8, -9) self.assertEqual(str(table), ans)
def report(self): """ Print a tabular report about the block diagram """ # print all the blocks print('\nBlocks::\n') table = ANSITable( Column("id"), Column("name"), Column("nin"), Column("nout"), Column("nstate"), border="thin" ) for b in self.blocklist: table.row( b.id, str(b), b.nin, b.nout, b.nstates) table.print() # print all the wires print('\nWires::\n') table = ANSITable( Column("id"), Column("from", headalign="^"), Column("to", headalign="^"), Column("description", headalign="^", colalign="<"), Column("type", headalign="^", colalign="<"), border="thin" ) for w in self.wirelist: start = "{:d}[{:d}]".format(w.start.block.id, w.start.port) end = "{:d}[{:d}]".format(w.end.block.id, w.end.port) value = w.end.block.inputs[w.end.port] typ = type(value).__name__ if isinstance(value, np.ndarray): typ += ' {:s}'.format(str(value.shape)) table.row( w.id, start, end, w.fullname, typ) table.print() print('\nState variables: {:d}'.format(self.nstates)) if not self.compiled: print('** System has not been compiled, or had a compile time error')
def list(keywords=None, dof=None): """ Display all robot models in summary form :param keywords: keywords to filter on, defaults to None :type keywords: tuple of str, optional :param dof: number of DoF to filter on, defaults to None :type dof: int, optional - ``list()`` displays a list of all models provided by the Toolbox. It lists the name, manufacturer, model type, number of DoF, and keywords. - ``list(keywords=KW)`` as above, but only displays models that have a keyword in the tuple ``KW``. - ``list(dof=N)`` as above, but only display models that have ``N`` degrees of freedom. The filters can be combined - ``list(keywords=KW, dof=N)`` are those models that have a keyword in ``KW`` and have ``N`` degrees of freedom. """ import roboticstoolbox.models as m # module = importlib.import_module('.' + os.path.splitext(file)[0], package='bdsim.blocks') table = ANSITable(Column("class", headalign="^", colalign="<"), Column("model", headalign="^", colalign="<"), Column("manufacturer", headalign="^", colalign="<"), Column("model type", headalign="^", colalign="<"), Column("DoF", colalign="<"), Column("config", colalign="<"), Column("keywords", headalign="^", colalign="<"), border="thin") for category in ['DH', 'URDF', 'ETS']: group = m.__dict__[category] for cls in group.__dict__.values(): if isinstance(cls, type) and issubclass(cls, Robot): # we found a Robot subclass, instantiate it robot = cls() try: config = robot.config() except: config = "" # apply filters if keywords is not None: if len(set(keywords) & set(robot.keywords)) == 0: continue if dof is not None and robot.n != dof: continue # add the row table.row(cls.__name__, robot.name, robot.manufacturer, category, robot.n, config, ', '.join(robot.keywords)) table.print()
def test_table_ascii(self): ans = r"""+--------------+---------------------------+----------+ | col1 | column 2 has a big header | column 3 | +--------------+---------------------------+----------+ | aaaaaaaaa | 2.2 | 3 | |bbbbbbbbbbbbb | -5.5 | 6 | | ccccccc | 8.8 | -9 | +--------------+---------------------------+----------+ """ table = ANSITable(Column("col1"), Column("column 2 has a big header"), Column("column 3"), border="ascii", color=False) table.row("aaaaaaaaa", 2.2, 3) table.row("bbbbbbbbbbbbb", -5.5, 6) table.row("ccccccc", 8.8, -9) self.assertEqual(str(table), ans)
def test_table_border_3(self): ans = r"""┏━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━┓ ┃col1 ┃ column 2 has a big header ┃ column 3 ┃ ┣━━━━━━━━━━━━━━╋━━━━━━━━━━━━━━━━━━━━━━━━━━━╋━━━━━━━━━━┫ ┃ aaaaaaaaa ┃ 2.2 ┃ 3 ┃ ┃bbbbbbbbbbbbb ┃ -5.5 ┃ 6 ┃ ┃ ccccccc ┃ 8.8 ┃ -9 ┃ ┗━━━━━━━━━━━━━━┻━━━━━━━━━━━━━━━━━━━━━━━━━━━┻━━━━━━━━━━┛ """ table = ANSITable(Column("col1", headalign="<"), Column("column 2 has a big header", colalign="^"), Column("column 3", colalign="<"), border="thick", color=False) table.row("aaaaaaaaa", 2.2, 3) table.row("bbbbbbbbbbbbb", -5.5, 6) table.row("ccccccc", 8.8, -9) self.assertEqual(str(table), ans)
def _dyn2list(self, fmt="{: .3g}"): """ Inertial properties of link as a string :param fmt: conversion format for each number :type fmt: str :return: The string representation of the link dynamics :rtype: string ``link.)_dyn2list()`` returns a list of pretty-printed inertial properties of the link The properties included are mass, centre of mass, inertia, friction, gear ratio and motor properties. :seealso: :func:`~dyn` """ ANSITable( Column("Parameter", headalign="^"), Column("Value", headalign="^", colalign="<"), border="thin") def format(l, fmt, val): # noqa if isinstance(val, np.ndarray): s = ', '.join([fmt.format(v) for v in val]) else: s = fmt.format(val) l.append(s) dyn = [] format(dyn, fmt, self.m) format(dyn, fmt, self.r) I = self.I.flatten() # noqa format(dyn, fmt, np.r_[[I[k] for k in [0, 4, 8, 1, 2, 5]]]) format(dyn, fmt, self.Jm) format(dyn, fmt, self.B) format(dyn, fmt, self.Tc) format(dyn, fmt, self.G) return dyn
def make_table(border): table = ANSITable(Column("class", headalign="^", colalign="<"), Column("model", headalign="^", colalign="<"), Column("manufacturer", headalign="^", colalign="<"), Column("model type", headalign="^", colalign="<"), Column("DoF", colalign="<"), Column("config", colalign="<"), Column("keywords", headalign="^", colalign="<"), border=border) if mtype is not None: categories = [mtype] else: categories = ['DH', 'URDF', 'ETS'] for category in categories: group = m.__dict__[category] for cls in group.__dict__.values(): if isinstance(cls, type) and issubclass(cls, Robot): # we found a Robot subclass, instantiate it robot = cls() try: config = robot.config() except Exception: # pragma nocover config = "" # apply filters if keywords is not None: if len(set(keywords) & set(robot.keywords)) == 0: continue if dof is not None and robot.n != dof: continue # pragma nocover # add the row table.row(cls.__name__, robot.name, robot.manufacturer, category, robot.n, config, ', '.join(robot.keywords)) print(str(table))
print(robot.n, robot.M) print(robot.elinks) print(robot.q_idx) for link in robot: print(link.name, link) print(link.ets, link.v, link.isjoint) print(link.parent, link.child) print(link.Ts) print(link.geometry, link.collision) print() from ansitable import ANSITable, Column table = ANSITable( Column("link"), Column("parent"), Column("ETS", headalign="^", colalign="<"), border="thin") for link in robot: if link.isjoint: color = "" else: color = "<<blue>>" table.row( color + link.name, link.parent.name if link.parent is not None else "-", link.ets * link.v if link.v is not None else link.ets) table.print()
if hasattr(robot, "ikine_a"): a = (robot.ikine_a, # analytic solution "ikine_a", "sol = robot.ikine_a(T)" ) ikfuncs.insert(0, a) # setup to run timeit setup = ''' from __main__ import robot, T, q0 ''' N = 10 # setup results table table = ANSITable( Column("Operation", headalign="^", colalign='<'), Column("Time (ms)", headalign="^", fmt="{:.2g}"), Column("Error", headalign="^", fmt="{:.3g}"), border="thick") # test the IK methods for ik in ikfuncs: print('Testing:', ik[1]) # test the method, don't pass q0 to the analytic function if ik[1] == "ikine_a": sol = ik[0](T) else: sol = ik[0](T, q0=q0) # print error message if there is one
] if hasattr(robot, "ikine_a"): a = ( robot.ikine_a, # analytic solution "ikine_a", "sol = robot.ikine_a}(T)") ikfuncs.insert(0, a) # setup to run timeit setup = ''' from __main__ import robot, T, q0 ''' N = 10 # setup results table table = ANSITable(Column("Operation", headalign="^"), Column("Time (μs)", headalign="^", fmt="{:.2f}"), Column("Error", headalign="^", fmt="{:.3g}"), border="thick") # test the IK methods for ik in ikfuncs: print('Testing:', ik[1]) # test the method, don't pass q0 to the analytic function if ik[1] == "ikine_a": sol = ik[0](T) else: sol = ik[0](T, q0=q0) # print error message if there is one
'SLSQP', 'trust-constr', 'dogleg', 'trust-ncg', 'trust-exact', 'trust-krylov', ] # setup to run timeit setup = ''' from __main__ import robot, T, q0 ''' N = 10 # setup results table table = ANSITable(Column("Solver", headalign="^", colalign='<'), Column("Time (ms)", headalign="^", fmt="{:.2g}", colalign='>'), Column("Error", headalign="^", fmt="{:.3g}", colalign='>'), border="thick") # test the IK methods for solver in solvers: print('Testing:', solver) # test the method, don't pass q0 to the analytic function try: sol = robot.ikine_min(T, q0=q0, qlim=True, method=solver) except Exception as e: