pyhpp.constraints
BySubstitution
Inherits: HierarchicalIterative
Solve a non-linear system equations with explicit and implicit constraints
This solver is defined in paper https://hal.archives-ouvertes.fr/hal-01804774/file/paper.pdf. We give here only a brief description
The unknows (denoted by ) of the system of equations is a Lie group. It is usually a robot configuration space or the Cartesian product of robot configuration spaces.
The solver stores a set of implicit numerical constraints: . These implicit constraints are added using method HierarchicalIterative::add.
The solver also stores explicit numerical constraints (constraints where some configuration variables depend on others) in an instance of class ExplicitConstraintSet. This instance is accessible via method BySubstitution::explicitConstraintSet.
When an explicit constraint is added using method ExplicitConstraintSet::add, this method checks that the explicit constraint is compatible with the previously added ones. If so, the constraint is stored in the explicit constraint set. Otherwise, it has to be added as an implicit constraint.
See Section III of the above mentioned paper for the description of the constraint resolution.
| def | Description |
|---|---|
def init(self, arg2: pyhpp.pinocchio.bindings.LiegroupSpace) -> None | |
def describeError(self, arg2: numpy.ndarray) -> tuple | Describe the constraint error for configuration q. Returns a list of (constraint_name, error_norm) pairs. |
def explicitConstraintSet(self) -> ExplicitConstraintSet | Get explicit constraint set. |
def explicitConstraintSetHasChanged(self) -> None | Should be called whenever explicit solver is modified. |
| Set right hand side of a constraint. |
| Compute right hand side of equality constraints from a configuration. |
def solve(self, arg2: numpy.ndarray) -> tuple | Solve the constraints from configuration q. Returns (output_config, status). |
| Get error threshold. |
ComparisonType
Inherits: int
ComparisonTypes
| def | Description |
|---|---|
def contains(self, arg2: object) -> bool | |
def delitem(self, arg2: object) -> None | |
def getitem(self, arg2: object) -> object | |
def init(self) -> None | |
def iter(self) -> object | |
def len(self) -> int | |
def setitem(self, arg2: object, arg3: object) -> None | |
def append(self, arg2: object) -> None | |
def extend(self, arg2: object) -> None |
DifferentiableFunction
Differentiable function from a Lie group, for instance the configuration space of a robot (hpp::pinocchio::Device) to a another Lie group.
Note that the input Lie group is only represented by the sizes of the elements and of the velocities: methods inputSize and inputDerivativeSize
The output space can be accessed by method outputSpace.
The value of the function for a given input can be accessed by method value . The Jacobian of the function for a given input can be accessed by method jacobian .
| def | Description |
|---|---|
def J(self, arg2: numpy.ndarray) -> numpy.ndarray | Compute Jacobian matrix and return as a numpy array. |
def call(self, arg2: numpy.ndarray) -> pyhpp.pinocchio.bindings.LiegroupElement | Evaluate the function at a given parameter. |
def init(self, arg2: int, arg3: int, arg4: int, arg5: str) -> None | |
def str(self) -> str | |
| |
| |
def inputDerivativeSize(self) -> int | |
def inputSize(self) -> int | Get dimension of input vector. |
def jacobian(self, jacobian: numpy.ndarray, argument: numpy.ndarray) -> None | :param :jacobian will be stored in this argument argument — point at which the jacobian will be computed |
| Get function name. |
def outputDerivativeSize(self) -> int | Get dimension of output derivative vector. |
def outputSize(self) -> int | Get dimension of output vector. |
def outputSpace(self) -> pyhpp.pinocchio.bindings.LiegroupSpace | Get output space. |
def value(self, result: pyhpp.pinocchio.bindings.LiegroupElement, argument: numpy.ndarray) -> None | |
| Get dimension of input derivative vector. |
| Get dimension of output derivative vector. |
| Get dimension of input vector. |
| Get dimension of output vector. |
Explicit
Explicit numerical constraint
DefinitionAn explicit numerical constraint is a constraint such that some configuration variables called output are function of the others called input.
Let
be the list of indices corresponding to ordered input configuration variables,
be the list of indices corresponding to ordered output configuration variables,
be the list of indices corresponding to ordered input degrees of freedom,
be the list of indices corresponding to ordered output degrees of freedom.
Recall that degrees of freedom refer to velocity vectors.
Let us notice that is less than the robot configuration size, and is less than the velocity size. Some degrees of freedom may indeed be neither input nor output.
Then the differential function is of the form
It is straightforward that an equality constraint with this function can be solved explicitely:
If function takes values in a Lie group (SO(2), SO(3)), the above “+” between a Lie group element and a tangent vector has to be undestood as the integration of the constant velocity from the Lie group element:
where is a Lie group element and is a tangent vector.
Considered as an Implicit instance, the expression of the Jacobian of the DifferentiableFunction above depends on the output space of function . The rows corresponding to values in a vector space are expressed as follows.
for any index between 0 and the size of velocity vectors, either
is an input degree of freedom: integer, such that ,
is an output degree of freedom: integer, such that , or
neither input nor output. In this case, the corresponding column is equal to 0.
The rows corresponding to values in SO(3) have the following expression.
where
is the rotation matrix corresponding to unit quaternion ,
is the rotation matrix corresponding to the part of the output value of corresponding to SO(3),
is the Jacobian matrix of function that associates to a rotation matrix the vector such that
“Domain ofdefinition” Some explicit constraints might be defined over only a subspace of the input
space. If the input value is not in the definition subspace, the explicit constraint will throw an exception of type FunctionNotDefinedForThisValue.
| def | Description |
|---|---|
def init(self, arg2: pyhpp.pinocchio.bindings.LiegroupSpace, arg3: DifferentiableFunction, arg4: list, arg5: list, arg6: list, arg7: list, arg8: ComparisonTypes) -> object | Create an explicit constraint mapping output DOF from input DOF. |
ExplicitConstraintSet
Set of explicit constraints
This class combines compatible explicit constraints as defined in the following paper published in Robotics Science and System 2018: https://hal.archives-ouvertes.fr/hal-01804774/file/paper.pdf, Section II-B Definition 4.
An explicit constraint on a robot configuration space is defined by
a subset of input indices ,
a subset of output indices ,
a smooth mapping from to , satisfying the following properties:
,
for any , is defined by
Right hand side.
For manipulation planning, it is useful to handle a parameterizable right hand side . The expression above thus becomes
The right hand side may be set using the various methods ExplicitConstraintSet::rightHandSide and ExplicitConstraintSet::rightHandSideFromInput.
For some applications like manipulation planning, an invertible function (of known inverse ) can be specified for each explicit constraint . The above expression then becomes:
To add explicit constraints, use methods ExplicitConstraintSet::add. If the constraint to add is not compatible with the previous one, this method returns -1.
Method ExplicitConstraintSet::solve solves the explicit constraints.
The combination of compatible explicit constraints is an explicit constraint. As such this class can be considered as an explicit constraint.
We will therefore use the following notation
for the set of indices of input variables,
for the set of indices of output variables.
| def | Description |
|---|---|
def init(self, arg2: pyhpp.pinocchio.bindings.LiegroupSpace) -> None | |
def str(self) -> str | |
def add(self, constraint: Explicit) -> int | constraint — explicit constraint |
def errorSize(self) -> int |
HierarchicalIterative
Solve a system of non-linear equations on a robot configuration
The non-linear system of equations is built by adding equations with method HierarchicalIterative::add.
Note that a hierarchy between the equations can be provided. In this case, the solver will try to solve the highest priority equations first, and then to solve the lower priority equations. Note that priorities are in decreasing order: 0 has higher priority than 1.
The algorithm used is a Newton-Raphson like algorithm that works as follows: for a single level of priority, let be the system of equations where is a mapping from the robot configuration space to a Lie group space .
Starting from initial guess , the method HierarchicalIterative::solve builds a sequence of configurations as follows:
where
is the Moore-Penrose pseudo-inverse of the system Jacobian,
is a sequence of real numbers depending on the line search strategy. Possible line-search strategies are lineSearch::Constant, lineSearch::Backtracking, lineSearch::FixedSequence, lineSearch::ErrorNormBased. until
the residual is below an error threshold, or
the maximal number of iterations has been reached.
The computation of the direction of descent in the case of multiple level of hierarchy is described in this paper.
The error threshold can be accessed by methods HierarchicalIterative::errorThreshold. The maximal number of iterations can be accessed by methods HierarchicalIterative::maxIterations.
Solving equations one after the other
For some applications, it can be more efficient to solve a set of equations one after the other. In other words, an equation is ignored until the previous one is solved (norm below the threshold). To do so, introduce the equations using method HierarchicalIterative::add with increasing value of priority, and call method HierarchicalIterative::solveLevelByLevel(true). Lie group
The unknowns may take values in a more general set than the configuration space of a robot. This set should be a Cartesian product of Lie groups: hpp::pinocchio::LiegroupSpace.
Saturation
Right hand side and comparison types
Instead of , other constraints can be defined. Several comparison types are available:
Equality — , where is a parameterizable right hand side,
EqualToZero — ,
Superior —
Inferior — If several constraint are of type equality, the right hand side of the system of equations can be modified by methods HierarchicalIterative::rightHandSideFromInput, HierarchicalIterative::rightHandSide.
Free variables
Some variables can be locked, or computed explicitely. In this case, the iterative resolution will only change the other variables called free variables. methods
freeVariables (const Indices_t& indices) and
freeVariables (const Indices_t& indices).
| def | Description |
|---|---|
def init(self, arg2: pyhpp.pinocchio.bindings.LiegroupSpace) -> None | |
def str(self) -> str | |
def add(self, constraint: Implicit, priority: int) -> bool | constraint — implicit constraint priority — level of priority of the constraint: priority are in decreasing order: 0 is the highest priority level, |
def constraintsForPriority(self, arg2: int) -> list | Return list of constraints at the given priority level. |
def dimension(self) -> int | Return total dimension of the active constraints. |
def numberStacks(self) -> int | Return the number of priority stacks. |
| Set right hand side of a constraint. |
| Compute right hand side of equality constraints from a configuration. |
| |
| Whether the last priority level is treated as optional. |
| Get maximal number of iterations in config projector. |
| Whether to solve constraints one priority level at a time. |
Implicit
This class represents a parameterizable numerical constraint that compares the output of a function to a right hand side Lie group element.
Definition
The function takes input in a configuration space and output in a Lie group ,
the dimensions of and of its tangent space are respectively .
The comparison is represented by a vector of dimension with values in enum hpp::constraints::ComparisonType = { , , , }.
The right hand side is Lie group element of dimension .
Error
A configuration is said to satisfy the constraint for a given right hand side if and only if the error as computed below is smaller in norm than a given threshold.
Let
for each component ,
if is , ,
if is , ,
if is , ,
if is , .
Mask
A mask is a vector of Boolean values of size . Values set to false means that the corresponding component of the error defined above is not taken into account to determine whether the constraint is satisfied. The active rows of the constraint may be accessed via method activeRows.
Parameterizable right hand side
Lines with comparator in the above definition of the error need a parameter, while lines with comparators , , or do not. As a consequence, the right hand side of the constraint is defined by a vector of parameters of size the number of occurences in vector . The right hand side is then defined as in the following example:
To retrieve the size of vector , call method Implicit::parameterSize (). To set and get the right hand side value, use method Implicit::rightHandSide.
Time varying right hand side
The right hand side of the constraint may depend on time, for instance if the constraint is associated to a trajectory following task. In this case, the right hand side is a function from to .
| def | Description |
|---|---|
def init(self, arg2: DifferentiableFunction, arg3: ComparisonTypes, arg4: pinocchio.pinocchio_pywrap_default.StdVec_Bool) -> object | Create an implicit constraint from a differentiable function and comparison types. |
| Return the ComparisonType. |
def function(self) -> DifferentiableFunction | Return a reference to function . |
def getFunctionOutputSize(self) -> int | Return the output size of the underlying differentiable function. |
def parameterSize(self) -> int | |
def rightHandSideSize(self) -> int |
LockedJoint
Inherits: Implicit
Implementation of constraint specific to a locked joint.
The implicit formulation as defined in class Implicit is given by
where is an element of the configuration space of the locked joint passed to method create.
Note that takes values in where is the dimension of the joint tangent space.
The explicit formulation is given by
where coordinates of corresponding to comparison types different from Equality are set to 0.
As such, the relation between the explicit formulation and the implicit formulation is the default one.
| def | Description |
|---|---|
| Create a locked joint constraint fixing the named joint to the given configuration. |
Manipulability
Inherits: DifferentiableFunction
| def | Description |
|---|---|
def init(self, arg2: DifferentiableFunction, arg3: object, arg4: str) -> object | Create a manipulability function for the given robot. |
def lockJoint(self, arg2: str) -> None | Lock a joint by name so it is excluded from the Jacobian. |
MinManipulability
Inherits: DifferentiableFunction
| def | Description |
|---|---|
def init(self, arg2: DifferentiableFunction, arg3: object, arg4: str) -> object | Create a minimum-manipulability function for the given robot. |
def lockJoint(self, arg2: str) -> None | Lock a joint by name so it is excluded from the Jacobian. |
Orientation
Inherits: DifferentiableFunction
| def | Description |
|---|---|
def init(self, arg2: str, arg3: object, arg4: int, arg5: pinocchio.pinocchio_pywrap_default.SE3, arg6: pinocchio.pinocchio_pywrap_default.SE3, arg7: pinocchio.pinocchio_pywrap_default.StdVec_Bool) -> object | name — name of the constraint, robot — device the constraint applies to, j2 — index of joint that holds frame 2, frame2 (SE3): pose of frame 2 in joint 2, frame1 (SE3): pose of frame 1 in world frame, mask — tuple of Boolean. |
Position
Inherits: DifferentiableFunction
| def | Description |
|---|---|
def init(self, arg2: str, arg3: object, arg4: int, arg5: pinocchio.pinocchio_pywrap_default.SE3, arg6: pinocchio.pinocchio_pywrap_default.SE3, arg7: pinocchio.pinocchio_pywrap_default.StdVec_Bool) -> object | name — name of the constraint, robot — device the constraint applies to, j2 — index of joint that holds frame 2, frame2 (SE3): pose of frame 2 in joint 2, frame1 (SE3): pose of frame 1 in world frame, mask — tuple of Boolean. |
RelativeCom
Inherits: DifferentiableFunction
Constraint on the relative position of the center of mass
The value of the function is defined as the position of the center of mass in the reference frame of a joint.
where
is the position of the joint,
is the position of the center of mass,
is the desired position of the center of mass expressed in joint frame.
| def | Description |
|---|---|
| Return a shared pointer to a new instance. |
RelativeOrientation
Inherits: DifferentiableFunction
| def | Description |
|---|---|
def init(self, arg2: str, arg3: object, arg4: int, arg5: int, arg6: pinocchio.pinocchio_pywrap_default.SE3, arg7: pinocchio.pinocchio_pywrap_default.SE3, arg8: pinocchio.pinocchio_pywrap_default.StdVec_Bool) -> object | name — name of the constraint, robot — device the constraint applies to, j1 — index of joint that holds frame 1, j2 — index of joint that holds frame 2, frame1 (SE3): pose of frame 1 in joint 1, frame2 (SE3): pose of frame 2 in joint 2, mask — tuple of Boolean. |
RelativePosition
Inherits: DifferentiableFunction
| def | Description |
|---|---|
def init(self, arg2: str, arg3: object, arg4: int, arg5: int, arg6: pinocchio.pinocchio_pywrap_default.SE3, arg7: pinocchio.pinocchio_pywrap_default.SE3, arg8: pinocchio.pinocchio_pywrap_default.StdVec_Bool) -> object | name — name of the constraint, robot — device the constraint applies to, j1 — index of joint that holds frame 1, j2 — index of joint that holds frame 2, frame1 (SE3): pose of frame 1 in joint 1, frame2 (SE3): pose of frame 2 in joint 2, mask — tuple of Boolean. |
RelativeTransformation
Inherits: DifferentiableFunction
| def | Description |
|---|---|
def init(self, arg2: str, arg3: object, arg4: int, arg5: int, arg6: pinocchio.pinocchio_pywrap_default.SE3, arg7: pinocchio.pinocchio_pywrap_default.SE3, arg8: pinocchio.pinocchio_pywrap_default.StdVec_Bool) -> object | name — name of the constraint, robot — device the constraint applies to, j1 — index of joint that holds frame 1, j2 — index of joint that holds frame 2, frame1 (SE3): pose of frame 1 in joint 1, frame2 (SE3): pose of frame 2 in joint 2, mask — tuple of Boolean. |
RelativeTransformationR3xSO3
Inherits: DifferentiableFunction
| def | Description |
|---|---|
def init(self, arg2: str, arg3: object, arg4: int, arg5: int, arg6: pinocchio.pinocchio_pywrap_default.SE3, arg7: pinocchio.pinocchio_pywrap_default.SE3, arg8: pinocchio.pinocchio_pywrap_default.StdVec_Bool) -> object | name — name of the constraint, robot — device the constraint applies to, j1 — index of joint that holds frame 1, j2 — index of joint that holds frame 2, frame1 (SE3): pose of frame 1 in joint 1, frame2 (SE3): pose of frame 2 in joint 2, mask — tuple of Boolean. |
SolverStatus
Inherits: int
Transformation
Inherits: DifferentiableFunction
| def | Description |
|---|---|
def init(self, arg2: str, arg3: object, arg4: int, arg5: pinocchio.pinocchio_pywrap_default.SE3, arg6: pinocchio.pinocchio_pywrap_default.SE3, arg7: pinocchio.pinocchio_pywrap_default.StdVec_Bool) -> object | name — name of the constraint, robot — device the constraint applies to, j2 — index of joint that holds frame 2, frame2 (SE3): pose of frame 2 in joint 2, frame1 (SE3): pose of frame 1 in world frame, mask — tuple of Boolean. |
segment
| def | Description |
|---|---|
| |
| |
|