Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

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.

defDescription
def init(self, arg2: pyhpp.pinocchio.bindings.LiegroupSpace) -> None
def describeError(self, arg2: numpy.ndarray) -> tupleDescribe the constraint error for configuration q. Returns a list of (constraint_name, error_norm) pairs.
def explicitConstraintSet(self) -> ExplicitConstraintSetGet explicit constraint set.
def explicitConstraintSetHasChanged(self) -> NoneShould be called whenever explicit solver is modified.
@typing.overload
def rightHandSide(self, arg2: Implicit, arg3: numpy.ndarray) -> bool

@typing.overload
def rightHandSide(self, arg2: numpy.ndarray) -> None

@typing.overload
def rightHandSide(self) -> numpy.ndarray
Set right hand side of a constraint.
@typing.overload
def rightHandSideFromConfig(self, arg2: numpy.ndarray) -> numpy.ndarray

@typing.overload
def rightHandSideFromConfig(self, arg2: Implicit, arg3: numpy.ndarray) -> bool
Compute right hand side of equality constraints from a configuration.
def solve(self, arg2: numpy.ndarray) -> tupleSolve the constraints from configuration q. Returns (output_config, status).
@property
def errorThreshold(*args, **kwargs)

@errorThreshold.setter
def errorThreshold(*args, **kwargs)
Get error threshold.

ComparisonType

Inherits: int


ComparisonTypes

defDescription
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 .

defDescription
def J(self, arg2: numpy.ndarray) -> numpy.ndarrayCompute Jacobian matrix and return as a numpy array.
def call(self, arg2: numpy.ndarray) -> pyhpp.pinocchio.bindings.LiegroupElementEvaluate the function at a given parameter.
def init(self, arg2: int, arg3: int, arg4: int, arg5: str) -> None
def str(self) -> str
@typing.overload
def impl_compute(self, arg2: pyhpp.pinocchio.bindings.LiegroupElementRef, arg3: numpy.ndarray) -> None

@typing.overload
def impl_compute(self, arg2: pyhpp.pinocchio.bindings.LiegroupElementRef, arg3: numpy.ndarray) -> None
@typing.overload
def impl_jacobian(self, arg2: numpy.ndarray, arg3: numpy.ndarray) -> None

@typing.overload
def impl_jacobian(self, arg2: numpy.ndarray, arg3: numpy.ndarray) -> None
def inputDerivativeSize(self) -> int
def inputSize(self) -> intGet 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
@typing.overload
def name(self) -> str

@typing.overload
def name(self) -> str
Get function name.
def outputDerivativeSize(self) -> intGet dimension of output derivative vector.
def outputSize(self) -> intGet dimension of output vector.
def outputSpace(self) -> pyhpp.pinocchio.bindings.LiegroupSpaceGet output space.
def value(self, result: pyhpp.pinocchio.bindings.LiegroupElement, argument: numpy.ndarray) -> None
@property
def ndi(*args, **kwargs)
Get dimension of input derivative vector.
@property
def ndo(*args, **kwargs)
Get dimension of output derivative vector.
@property
def ni(*args, **kwargs)
Get dimension of input vector.
@property
def no(*args, **kwargs)
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.

defDescription
def init(self, arg2: pyhpp.pinocchio.bindings.LiegroupSpace, arg3: DifferentiableFunction, arg4: list, arg5: list, arg6: list, arg7: list, arg8: ComparisonTypes) -> objectCreate 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.

defDescription
def init(self, arg2: pyhpp.pinocchio.bindings.LiegroupSpace) -> None
def str(self) -> str
def add(self, constraint: Explicit) -> intconstraint — 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).

defDescription
def init(self, arg2: pyhpp.pinocchio.bindings.LiegroupSpace) -> None
def str(self) -> str
def add(self, constraint: Implicit, priority: int) -> boolconstraint — 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) -> listReturn list of constraints at the given priority level.
def dimension(self) -> intReturn total dimension of the active constraints.
def numberStacks(self) -> intReturn the number of priority stacks.
@typing.overload
def rightHandSide(self, arg2: Implicit, arg3: numpy.ndarray) -> bool

@typing.overload
def rightHandSide(self, arg2: numpy.ndarray) -> None

@typing.overload
def rightHandSide(self) -> numpy.ndarray
Set right hand side of a constraint.
@typing.overload
def rightHandSideFromConfig(self, arg2: numpy.ndarray) -> numpy.ndarray

@typing.overload
def rightHandSideFromConfig(self, arg2: Implicit, arg3: numpy.ndarray) -> bool
Compute right hand side of equality constraints from a configuration.
@property
def errorThreshold(self) -> float

@errorThreshold.setter
def errorThreshold(self, arg2: float) -> None
@property
def lastIsOptional(*args, **kwargs)

@lastIsOptional.setter
def lastIsOptional(*args, **kwargs)
Whether the last priority level is treated as optional.
@property
def maxIterations(*args, **kwargs)

@maxIterations.setter
def maxIterations(*args, **kwargs)
Get maximal number of iterations in config projector.
@property
def solveLevelByLevel(*args, **kwargs)

@solveLevelByLevel.setter
def solveLevelByLevel(*args, **kwargs)
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 .

defDescription
def init(self, arg2: DifferentiableFunction, arg3: ComparisonTypes, arg4: pinocchio.pinocchio_pywrap_default.StdVec_Bool) -> objectCreate an implicit constraint from a differentiable function and comparison types.
@typing.overload
def comparisonType(self) -> ComparisonTypes

@typing.overload
def comparisonType(self, arg2: ComparisonTypes) -> None
Return the ComparisonType.
def function(self) -> DifferentiableFunctionReturn a reference to function .
def getFunctionOutputSize(self) -> intReturn 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.

defDescription
@typing.overload
def init(self, arg2: object, arg3: str, arg4: numpy.ndarray) -> object

@typing.overload
def init(self, arg2: object, arg3: str, arg4: numpy.ndarray, arg5: ComparisonTypes) -> object
Create a locked joint constraint fixing the named joint to the given configuration.

Manipulability

Inherits: DifferentiableFunction

defDescription
def init(self, arg2: DifferentiableFunction, arg3: object, arg4: str) -> objectCreate a manipulability function for the given robot.
def lockJoint(self, arg2: str) -> NoneLock a joint by name so it is excluded from the Jacobian.

MinManipulability

Inherits: DifferentiableFunction

defDescription
def init(self, arg2: DifferentiableFunction, arg3: object, arg4: str) -> objectCreate a minimum-manipulability function for the given robot.
def lockJoint(self, arg2: str) -> NoneLock a joint by name so it is excluded from the Jacobian.

Orientation

Inherits: DifferentiableFunction

defDescription
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) -> objectname — 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

defDescription
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) -> objectname — 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.

defDescription
@typing.overload
def init(self, robot: object, joint: object, reference: numpy.ndarray, mask: pinocchio.pinocchio_pywrap_default.StdVec_Bool) -> RelativeCom

@typing.overload
def init(self, arg2: object, arg3: object, arg4: numpy.ndarray, arg5: pinocchio.pinocchio_pywrap_default.StdVec_Bool) -> RelativeCom

@typing.overload
def init(self, arg2: object, arg3: object, arg4: object, arg5: numpy.ndarray, arg6: pinocchio.pinocchio_pywrap_default.StdVec_Bool) -> RelativeCom
Return a shared pointer to a new instance.

RelativeOrientation

Inherits: DifferentiableFunction

defDescription
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) -> objectname — 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

defDescription
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) -> objectname — 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

defDescription
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) -> objectname — 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

defDescription
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) -> objectname — 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

defDescription
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) -> objectname — 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

defDescription
@typing.overload
def init(self) -> None

@typing.overload
def init(self, arg2: int, arg3: int) -> None
@property
def first(self) -> int

@first.setter
def first(self, arg2: int) -> None
@property
def second(self) -> int

@second.setter
def second(self, arg2: int) -> None