From c3d54f6c53db90bed8f75f03d7b359cf61c690bd Mon Sep 17 00:00:00 2001 From: Brian Delhaisse Date: Sun, 14 Apr 2019 19:19:11 +0200 Subject: [PATCH] update doc of several classes --- .../priorities/constraints/constraint.py | 2 +- .../constraints/dynamic_constraints.py | 22 +++ .../constraints/kinematic_constraints.py | 10 +- pyrobolearn/priorities/tasks/dynamic_tasks.py | 24 ++- .../priorities/tasks/kinematic_tasks.py | 34 ++++ pyrobolearn/robots/robot.py | 164 ++++++++++-------- pyrobolearn/simulators/bullet.py | 2 + 7 files changed, 178 insertions(+), 80 deletions(-) diff --git a/pyrobolearn/priorities/constraints/constraint.py b/pyrobolearn/priorities/constraints/constraint.py index bf823c7..afacb82 100644 --- a/pyrobolearn/priorities/constraints/constraint.py +++ b/pyrobolearn/priorities/constraints/constraint.py @@ -1,5 +1,5 @@ #!/usr/bin/env python -r"""Provide the various constraints used in QP. +r"""Provide the various constraints and bounds used in QP. Provide the various optimization constraints (:math:`G, h, F, c` in the upcoming formulation) used in QP. diff --git a/pyrobolearn/priorities/constraints/dynamic_constraints.py b/pyrobolearn/priorities/constraints/dynamic_constraints.py index 16664e1..b1d2435 100644 --- a/pyrobolearn/priorities/constraints/dynamic_constraints.py +++ b/pyrobolearn/priorities/constraints/dynamic_constraints.py @@ -27,6 +27,7 @@ __status__ = "Development" class DynamicConstraint(Constraint): r"""Dynamic Constraints + Dynamic constraint using Equation of Motion (by using inertia and the non-linear terms). """ pass @@ -57,8 +58,29 @@ class FrictionCones(DynamicConstraint): pass +class FrictionPyramide(DynamicConstraint): + r"""Friction pyramide constraint (using contact force optimization) + + """ + pass + + +class UnilateralContact(DynamicConstraint): + r"""Unilateral Contact constraint. + + Mechanical constraint which prevents penetration between two bodies. + """ + + class WrenchLimits(DynamicConstraint): r"""Wrench Limits (using contact force optimization). """ pass + + +class ZMP(DynamicConstraint): + r"""ZMP constraint. + + """ + pass diff --git a/pyrobolearn/priorities/constraints/kinematic_constraints.py b/pyrobolearn/priorities/constraints/kinematic_constraints.py index 3b4d543..64b29dd 100644 --- a/pyrobolearn/priorities/constraints/kinematic_constraints.py +++ b/pyrobolearn/priorities/constraints/kinematic_constraints.py @@ -69,4 +69,12 @@ class JointVelocityLimits(KinematicConstraint): class SelfCollisionAvoidance(KinematicConstraint): r"""Self-collision avoidance constraint. - """ \ No newline at end of file + """ + pass + + +class ConvexHull(Constraint): + r"""Convex Hull constraint + + """ + pass diff --git a/pyrobolearn/priorities/tasks/dynamic_tasks.py b/pyrobolearn/priorities/tasks/dynamic_tasks.py index 2908d84..0bca284 100644 --- a/pyrobolearn/priorities/tasks/dynamic_tasks.py +++ b/pyrobolearn/priorities/tasks/dynamic_tasks.py @@ -34,6 +34,7 @@ class DynamicTask(Task): class MinAcceleration(DynamicTask): r"""Min acceleration task. + Minimize joint accelerations. """ pass @@ -41,6 +42,7 @@ class MinAcceleration(DynamicTask): class MinEffort(DynamicTask): r"""Min effort task. + Minimize joint torques / forces. """ pass @@ -60,7 +62,27 @@ class ForceManipulability(DynamicTask): class CentroidalDynamics(DynamicTask): - r"""Centroidal dynamics task (u + r"""Centroidal dynamics task. + """ + pass + + +class LinearMomentum(DynamicTask): + r"""Linear Momentum task. + + """ + pass + + +class AngularMomentum(DynamicTask): + r"""Angular Momentum Task. + + """ + pass + + +class MinGroundReactionForce(DynamicTask): + r"""Min Ground Reaction Force task. """ pass diff --git a/pyrobolearn/priorities/tasks/kinematic_tasks.py b/pyrobolearn/priorities/tasks/kinematic_tasks.py index 6fac378..7237eb5 100644 --- a/pyrobolearn/priorities/tasks/kinematic_tasks.py +++ b/pyrobolearn/priorities/tasks/kinematic_tasks.py @@ -58,6 +58,34 @@ class Postural(KinematicTask): While optimizing, the robot can get to weird configurations. This postural kinematic task tries to keep the robot's kinematic configuration close to the given default joint positions. This task is usually put at the end of the stack of tasks, once all the other tasks have been fulfilled. + + The A matrix is the identity matrix, the variables being optimized are the joint velocities :math:`\dot{q}`, and + the :math:`b` vector is :math:`\dot{q}_d + K_q (q_d - q)`. + """ + pass + + +class CartesianPosition(KinematicTask): + r"""Cartesian position kinematic task. + + The A matrix is the translational Jacobian matrix between the base (or world) and the specified link, the variables + being optimized are the joint velocities :math:`\dot{q}`, and the :math:`b` vector is + :math:`\dot{p}_d + K_p (p_d - p)`. + """ + pass + + +class CartesianOrientation(KinematicTask): + r"""Cartesian orientation kinematic task. + + The A matrix is the rotational Jacobian matrix, the variables being optimized are the joint velocities + :math:`\dot{q}`, and the :math:`b` vector is :math:`\omega_d + K_o e_o` where + :math:`e_o = -(\eta_d \espilon - \eta \epsilon_d + [\epsilon_d \times] \epsilon)`. The :math:`\eta` and + :math:`\epsilon` are respectively the scalar and vector part of the quaternion. + The quaternion error :math:`\Delta Q` is given by :math:`Q_d * Q_e^{-1}`. + + Once the optimal joint velocities :math:`\dot{q}^*` have been computed, they can be given to a velocity controller, + or a position controller using :math:`q = q + \dot{q}^* dt`, with :math:`dt` being the control loop period. """ pass @@ -65,6 +93,7 @@ class Postural(KinematicTask): class Cartesian(KinematicTask): r"""Cartesian kinematic task + The Cartesian task is the aggregate of a Cartesian position task and a Cartesian orientation task. """ pass @@ -72,6 +101,7 @@ class Cartesian(KinematicTask): class CoM(KinematicTask): r"""Center of Mass task + The Center of Mass is a specific Cartesian position task. """ pass @@ -79,6 +109,10 @@ class CoM(KinematicTask): class VelocityManipulability(KinematicTask): r"""Velocity manipulability task + The A matrix is the identity matrix, the variables being optimized are the joint velocities :math:`\dot{q}`, and + the :math:`b` vector is 0. + + This task is often used to avoid joint singularities and their neighborhood. """ pass diff --git a/pyrobolearn/robots/robot.py b/pyrobolearn/robots/robot.py index e7ab118..9d28320 100644 --- a/pyrobolearn/robots/robot.py +++ b/pyrobolearn/robots/robot.py @@ -879,7 +879,7 @@ class Robot(ControllableBody): self.sim.set_joint_motor_control(self.id, joint_ids, self.sim.TORQUE_CONTROL, forces=torque) def set_joint_motor_control(self, joint_ids, control_mode, **kwargs): - """ + r""" Set joint motor control. In position control: @@ -1110,7 +1110,7 @@ class Robot(ControllableBody): compute_forward_kinematics=compute_forward_kinematics) def get_link_names(self, link_ids=None): - """ + r""" Return the name of the given link(s). Args: @@ -1130,7 +1130,7 @@ class Robot(ControllableBody): return [self.sim.get_joint_info(self.id, link)[12] for link in link_ids] def get_link_masses(self, link_ids=None): - """ + r""" Return the mass of the given link(s). Args: @@ -1150,7 +1150,7 @@ class Robot(ControllableBody): return np.array([self.sim.get_dynamics_info(self.id, link)[0] for link in link_ids]) def get_link_frames(self, link_ids=None, flatten=False): - """ + r""" Return the link frame position and orientation (expressed in the world space). Args: @@ -1171,7 +1171,7 @@ class Robot(ControllableBody): flatten) def get_link_frame_world_positions(self, link_ids=None, flatten=False): - """ + r""" Return the frame position (in the Cartesian world space coordinates) of the given link(s). Args: @@ -1195,7 +1195,7 @@ class Robot(ControllableBody): return pos # 2D array def get_link_frame_world_orientations(self, link_ids=None, flatten=False): - """ + r""" Return the frame orientation (in the Cartesian world space) of the given link(s). Args: @@ -1219,7 +1219,7 @@ class Robot(ControllableBody): return orientation # 2D array def get_link_world_positions(self, link_ids=None, flatten=True): - """ + r""" Return the CoM position (in the Cartesian world space coordinates) of the given link(s). Args: @@ -1245,7 +1245,7 @@ class Robot(ControllableBody): return pos # 2D array def get_link_positions(self, link_ids=None, wrt_link_id=None, flatten=True): - """ + r""" Return the link CoM position wrt the position of another link. By default, it is the base. Args: @@ -1269,12 +1269,12 @@ class Robot(ControllableBody): return p def get_link_world_orientations(self, link_ids=None, flatten=True): - """ + r""" Return the CoM orientation (in the Cartesian world space) of the given link(s). Args: - link_ids (int, int[N], None): link id, or list of desired link ids. If None, get the orientation of all links - associated to actuated joints. + link_ids (int, int[N], None): link id, or list of desired link ids. If None, get the orientation of all + links associated to actuated joints. flatten (bool): if True, it will return a 1D array of float numbers instead of an array of quaternion Returns: @@ -1293,12 +1293,12 @@ class Robot(ControllableBody): return orientation # 2D array def get_link_orientations(self, link_ids=None, wrt_link_id=None, flatten=True): - """ + r""" Return the link CoM orientation wrt the orientation of another link. By default, it is the base. Args: - link_ids (int, int[N], None): link id, or list of desired link ids. If None, get the orientation of all links - associated to actuated joints. + link_ids (int, int[N], None): link id, or list of desired link ids. If None, get the orientation of all + links associated to actuated joints. wrt_link_id (int, int[N], None): the other link id(s). If None, returns the orientation wrt to the base. flatten (bool): if True, it will return a 1D array instead of a 2D array @@ -1323,7 +1323,7 @@ class Robot(ControllableBody): return q def get_link_world_linear_velocities(self, link_ids=None, flatten=True): - """ + r""" Return the linear velocity of the link(s) expressed in the Cartesian world space coordinates. Args: @@ -1347,7 +1347,7 @@ class Robot(ControllableBody): return vel # 2D array def get_link_world_angular_velocities(self, link_ids=None, flatten=True): - """ + r""" Return the angular velocity of the link(s) in the Cartesian world space coordinates. Args: @@ -1371,7 +1371,7 @@ class Robot(ControllableBody): return vel # 2D array def get_link_world_velocities(self, link_ids=None, flatten=True): - """ + r""" Return the linear and angular velocities (expressed in the Cartesian world space coordinates) for the given link(s). @@ -1401,7 +1401,7 @@ class Robot(ControllableBody): return vel # 2D array def get_link_linear_velocities(self, link_ids=None, wrt_link_id=None, flatten=True): - """ + r""" Return the linear velocity of the given link(s) wrt the other specified link(s). Args: @@ -1425,13 +1425,14 @@ class Robot(ControllableBody): return v def get_link_angular_velocities(self, link_ids=None, wrt_link_id=None, flatten=True): - """ + r""" Return the angular velocity of the given link(s) wrt to the other specified link(s). Args: link_ids (int, int[N], None): link id, or list of desired link ids. If None, get the angular velocity of all links associated to actuated joints. - wrt_link_id (int, int[N], None): the other link id(s). If None, returns the angular velocity wrt to the base. + wrt_link_id (int, int[N], None): the other link id(s). If None, returns the angular velocity wrt to the + base. flatten (bool): if True, it will return a 1D array instead of a 2D array Returns: @@ -1449,13 +1450,14 @@ class Robot(ControllableBody): return w def get_link_velocities(self, link_ids=None, wrt_link_id=None, flatten=True): - """ + r""" Return the linear and angular velocity of the given link(s) wrt to the other specified link(s). Args: link_ids (int, int[N], None): link id, or list of desired link ids. If None, get the angular velocity of all links associated to actuated joints. - wrt_link_id (int, int[N], None): the other link id(s). If None, returns the angular velocity wrt to the base. + wrt_link_id (int, int[N], None): the other link id(s). If None, returns the angular velocity wrt to the + base. flatten (bool): if True, it will return a 1D array instead of a 2D array Returns: @@ -1602,8 +1604,9 @@ class Robot(ControllableBody): # Transforms # ############## - def get_homogeneous_transform(self, position, orientation): - """ + @staticmethod + def get_homogeneous_transform(position, orientation): + r""" Return the Homogeneous transform matrix given the position vector and the orientation. Args: @@ -1635,7 +1638,7 @@ class Robot(ControllableBody): # TODO: allow to slice the Jacobian to only get what interests the user def get_jacobian(self, link_id, q=None, local_position=None): - """ + r""" Return the full geometric Jacobian matrix :math:`J(q) = [J_{lin}(q), J_{ang}(q)]^T`, such that: .. math:: v = [\dot{p}, \omega]^T = J(q) \dot{q} @@ -1675,7 +1678,7 @@ class Robot(ControllableBody): return self.sim.calculate_jacobian(self.id, link_id, local_position=local_position, q=q, dq=dq, des_ddq=dq) def get_linear_jacobian(self, link_id, q=None, local_position=None): - """ + r""" Return the full linear (geometric) Jacobian matrix :math:`J_{lin}(q)`, such that: .. math:: \dot{p} = J_{lin}(q) \dot{q} @@ -1699,7 +1702,7 @@ class Robot(ControllableBody): return self.get_jacobian(link_id, q, local_position)[:3] def get_angular_jacobian(self, link_id, q=None, local_position=None): - """ + r""" Return the full angular (geometric) Jacobian matrix :math:`J_{ang}(q)`, such that: .. math:: \omega = J_{ang}(q) \dot{q} @@ -1722,17 +1725,18 @@ class Robot(ControllableBody): """ return self.get_jacobian(link_id, q, local_position)[3:] - def get_jacobian_derivative_rpy_to_angular_velocity(self, rpy_angle): - """ + @staticmethod + def get_jacobian_derivative_rpy_to_angular_velocity(rpy_angle): + r""" Return the Jacobian that maps RPY angle rates to angular velocities, i.e. :math:`\omega = T(\phi) \dot{\phi}`. Warnings: :math:`T` is singular when the pitch angle :math:`\theta_p = \pm \frac{\pi}{2}` Args: - rpy_angle (float[3]): RPY Euler angles [rad] + rpy_angle (np.float[3]): RPY Euler angles [rad] Returns: - float[3,3]: Jacobian matrix that maps RPY angle rates to angular velocities. + np.float[3,3]: Jacobian matrix that maps RPY angle rates to angular velocities. """ r, p, y = rpy_angle T = np.array([[1., 0., np.sin(p)], @@ -1740,17 +1744,18 @@ class Robot(ControllableBody): [0., np.sin(r), np.cos(p) * np.cos(r)]]) return T - def get_jacobian_derivative_zyz_to_angular_velocity(self, zyzAngle): - """ + @staticmethod + def get_jacobian_derivative_zyz_to_angular_velocity(zyzAngle): + r""" Return the Jacobian that maps ZYZ angle rates to angular velocities, i.e. :math:`\omega = T(\phi) \dot{\phi}`. Warnings: :math:`T` is singular when the angle associated with `Y` is :math:`0` or :math:`\pi`. Args: - rpyAngle (float[3]): ZYZ Euler angles [rad] + rpyAngle (np.float[3]): ZYZ Euler angles [rad] Returns: - float[3,3]: Jacobian matrix that maps ZYZ angle rates to angular velocities. + np.float[3,3]: Jacobian matrix that maps ZYZ angle rates to angular velocities. """ z, y = zyzAngle[:2] T = np.array([[0., -np.sin(z), np.cos(z) * np.sin(y)], @@ -1759,7 +1764,7 @@ class Robot(ControllableBody): return T def get_analytical_jacobian(self, jacobian, rpy_angle): - """ + r""" Return the analytical Jacobian :math:`J_{a}(q) = [J_{lin}(q), J_{\phi}(q)]^T`, which respects: .. math:: \dot{x} = [\dot{p}, \dot{\phi}]^T = J_{a}(q) \dot{q} @@ -1785,12 +1790,12 @@ class Robot(ControllableBody): Euler angles then T is singular when the pitch angle :math:`\theta_p = \pm \frac{\pi}{2}. Args: - jacobian (float[6,N], float[6,6+N]): full geometric Jacobian. - rpy_angle (float[3]): RPY Euler angles + jacobian (np.float[6,N], np.float[6,6+N]): full geometric Jacobian. + rpy_angle (np.float[3]): RPY Euler angles Returns: - float[6,N], foat[6,(6+N)]: the full analytical Jacobian. The number of columns depends if the base is fixed - or floating. + np.float[6,N], np.foat[6,(6+N)]: the full analytical Jacobian. The number of columns depends if the base + is fixed or floating. """ T = self.get_jacobian_derivative_rpy_to_angular_velocity(rpy_angle) Tinv = np.linalg.inv(T) @@ -1799,7 +1804,7 @@ class Robot(ControllableBody): return Ja def get_angular_velocities_from_derivative_rpy(self, rpy_angle, dRPY): - """ + r""" Return the angular velocities :math:`\omega` from the derivative of RPY Euler angles \math:`\dot{\phi}`. These 2 quantities are related by the following equation: @@ -1818,17 +1823,17 @@ class Robot(ControllableBody): Note that :math:`T` is singular when the pitch angle :math:`\theta_p = \pm \frac{\pi}{2}`. Args: - rpy_angle (float[3]): RPY Euler angles [rad] - dRPY (float[3]): time derivative of RPY Euler angles [rad/s] + rpy_angle (np.float[3]): RPY Euler angles [rad] + dRPY (np.float[3]): time derivative of RPY Euler angles [rad/s] Returns: - float[3]: angular velocities [rad/s] + np.float[3]: angular velocities [rad/s] """ T = self.get_jacobian_derivative_rpy_to_angular_velocity(rpy_angle) return T.dot(dRPY) def get_derivative_rpy_from_angular_velocities(self, rpy_angle, angular_velocity): - """ + r""" Return the time derivative of RPY Euler angles :math:`\dot{\phi}` given the angular velocities :math:`\omega`. . .math:: \dot{\phi} = T^{-1}(\phi) \omega @@ -1837,11 +1842,11 @@ class Robot(ControllableBody): corresponding angular velocities :math:`\omega` are not defined. Args: - rpy_angle (float[3]): RPY Euler angles [rad] - angular_velocity (float[3]): angular velocities [rad/s] + rpy_angle (np.float[3]): RPY Euler angles [rad] + angular_velocity (np.float[3]): angular velocities [rad/s] Returns: - float[3]: time derivative of RPY Euler angles [rad/s] + np.float[3]: time derivative of RPY Euler angles [rad/s] Raises: LinAlgError: if singular configuration. @@ -1850,20 +1855,22 @@ class Robot(ControllableBody): Tinv = np.linalg.inv(T) return Tinv.dot(angular_velocity) - def get_JJT(self, jacobian): - """ + @staticmethod + def get_JJT(jacobian): + r""" Given the Jacobian, it returns :math:`JJ^T`. This relation is used in many places in robotics. Args: - jacobian (float[D,N]): Jacobian matrix + jacobian (np.float[D,N]): Jacobian matrix Returns: - float[D,D]: :math:`JJ^T` + np.float[D,D]: :math:`JJ^T` """ return jacobian.dot(jacobian.T) - def get_damped_least_squares_inverse(self, jacobian, damping_factor=0.01): - """ + @staticmethod + def get_damped_least_squares_inverse(jacobian, damping_factor=0.01): + r""" Return the damped least-squares (DLS) inverse, given by: .. math:: \hat{J} = J^T (JJ^T + k^2 I)^{-1} @@ -1872,11 +1879,11 @@ class Robot(ControllableBody): :math:`\dot{q} = \hat{J} v`. Args: - jacobian (float[D,N]): Jacobian matrix + jacobian (np.float[D,N]): Jacobian matrix damping_factor (float): damping factor Returns: - float[N,D]: DLS inverse matrix + np.float[N,D]: DLS inverse matrix """ J, k = jacobian, damping_factor return (J.T).dot(np.linalg.inv(J.dot(J.T) + k**2 * np.identity(J.shape[0]))) @@ -1884,30 +1891,31 @@ class Robot(ControllableBody): # alias getDLSInverse = get_damped_least_squares_inverse - def get_pinv_jacobian(self, jacobian): - """ + @staticmethod + def get_pinv_jacobian(jacobian): + r""" Return the right pseudo-inverse of the jacobian, i.e. :math:`J^\dagger = J^T(JJ^T)^{-1}`. Args: - jacobian (float[D,N]): Jacobian matrix + jacobian (np.float[D,N]): Jacobian matrix Returns: - float[N,N]: right pseudo-inverse of the Jacobian + np.float[N,N]: right pseudo-inverse of the Jacobian """ return np.linalg.pinv(jacobian) def get_null_space_projector(self, jacobian): - """ + r""" The null space projector :math:`P` is the matrix that projects any vectors to the null space of :math:`J`. This is given by: :math:`P = (I - J^\dagger J)`, where :math:`J^\dagger = J^T(JJ^T)^{-1}` is the right pseudo-inverse of the jacobian :math:`J`. This is notably used to perform inverse kinematics, where :math:`\dot{q} = J^\dagger v + P \dot{q}_0` with :math:`\dot{q}_0` representing arbitrary joint velocities. Args: - jacobian (float[D,N]): Jacobian matrix + jacobian (np.float[D,N]): Jacobian matrix Returns: - float[N,N]: null space projector matrix + np.float[N,N]: null space projector matrix """ J = jacobian JJT = self.get_JJT(jacobian) @@ -1915,13 +1923,13 @@ class Robot(ControllableBody): return I - self.get_pinv_jacobian(J=J).dot(J) def compute_manipulability_measure(self, jacobian): - """ + r""" Compute the manipulability measure `w(q) = sqrt( det(J(q)J(q)^T) )`. This is useful to get a general sense about the manipulation ability of the manipulator. This term, for instance, vanishes at singular configurations (see [1]). Args: - jacobian (float[D,N]): Jacobian matrix + jacobian (np.float[D,N]): Jacobian matrix Returns: float: manipulability measure :math:`w(q)` @@ -1931,8 +1939,9 @@ class Robot(ControllableBody): """ return np.sqrt(np.linalg.det(self.get_JJT(jacobian))) - def in_singular_configuration(self, jacobian): - """ + @staticmethod + def in_singular_configuration(jacobian): + r""" Return True if we are in a singular configuration. Singularities are interesting because (see [1]): @@ -1941,7 +1950,7 @@ class Robot(ControllableBody): - around them, small velocities in the task/operational space may cause large velocities in the joint space Args: - jacobian (float[D,N]): Jacobian matrix + jacobian (np.float[D,N]): Jacobian matrix Returns: bool: True if in a singular configuration @@ -1956,7 +1965,7 @@ class Robot(ControllableBody): return r < m def get_joint_velocities_from_cartesian_velocities(self, jacobian, velocity): - """ + r""" Return the joint velocities :math:`\dot{q}` from the cartesian velocities :math:`v`. .. math:: \dot{q} = J^\dagger v @@ -1964,24 +1973,25 @@ class Robot(ControllableBody): where :math:`J^\dagger` is the right pseudo-inverse of J, i.e. :math:`J^\dagger = J^T(JJ^T)^{-1}`. Args: - jacobain (float[3,N], float[6,N]): Jacobian matrix - velocity (float[3], float[6]): linear and/or angular velocities + jacobain (np.float[3,N], np.float[6,N]): Jacobian matrix + velocity (np.float[3], np.float[6]): linear and/or angular velocities Returns: - float[N]: joint velocities + np.float[N]: joint velocities """ Jpinv = self.get_pinv_jacobian(jacobian) return Jpinv.dot(velocity) - def get_cartesian_velocities_from_joint_velocities(self, jacobian, dq): - """ + @staticmethod + def get_cartesian_velocities_from_joint_velocities(jacobian, dq): + r""" Return the Cartesian velocities :math:`v = [\dot{p}, \omega]^T` where :math:`\dot{p}` and :math:`\omega` are the linear and angular velocities, respectively. .. math:: v = J(q) \dot{q} Returns: - float[6]: Cartesian linear and angular velocities + np.float[6]: Cartesian linear and angular velocities """ return jacobian.dot(dq) @@ -1989,7 +1999,7 @@ class Robot(ControllableBody): def calculate_inverse_kinematics(self, link_id, position, orientation=None, lower_limits=None, upper_limits=None, joint_ranges=None, rest_poses=None, joint_dampings=None, max_iters=1, threshold=1e-4): - """ + r""" Compute the FULL Inverse kinematics; it will return a position for all the actuated joints. Args: @@ -2025,7 +2035,7 @@ class Robot(ControllableBody): threshold=threshold) def hard_priorities(self, jacobians, task_velocities, method='backtrack'): - """ + r""" Return dq. Args: diff --git a/pyrobolearn/simulators/bullet.py b/pyrobolearn/simulators/bullet.py index f21545a..05e225d 100644 --- a/pyrobolearn/simulators/bullet.py +++ b/pyrobolearn/simulators/bullet.py @@ -71,6 +71,8 @@ class Bullet(Simulator): sim = Bullet() References: + [1] "PyBullet, a Python module for physics simulation for games, robotics and machine learning", Erwin Coumans + and Yunfei Bai, 2016-2019 [1] PyBullet Quickstart Guide: https://docs.google.com/document/d/10sXEhzFRSnvFcl3XxNGhnD4N2SedqwdAvK3dsihxVUA Erwin Coumans and Yunfei Bai, 2017/2018 """