Files
KDL_WORK/kdl_install/include/kdl/chainhdsolver_vereshchagin.hpp
2026-06-27 09:25:04 -04:00

536 lines
31 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// Copyright (C) 2009 Ruben Smits <ruben dot smits at intermodalics dot eu>
// Version: 1.0
// Author: Ruben Smits <ruben dot smits at intermodalics dot eu>
// Author: Herman Bruyninckx
// Author: Azamat Shakhimardanov
// Maintainer: Ruben Smits <ruben dot smits at intermodalics dot eu>
// URL: http://www.orocos.org/kdl
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#ifndef KDL_CHAINHDSOLVER_VERESHCHAGIN_HPP
#define KDL_CHAINHDSOLVER_VERESHCHAGIN_HPP
#include "chainidsolver.hpp"
#include "frames.hpp"
#include "articulatedbodyinertia.hpp"
#include<Eigen/StdVector>
namespace KDL
{
/**
* \brief **Abstract**: Acceleration constrained hybrid dynamics calculations for a chain, based on Vereshchagin 1989.
* This class creates an instance of the hybrid dynamics solver. The solver analytically calculates the joint space
* constraint torques and acceleration in a chain when a constraint force(s) is applied to the chain's end-effector
* (task space / cartesian space). In the robotics literature, this algorithm is also known under the following names:
* Acceleration Constrained Hybrid Dynamics (ACHD) and Popov-Vereshchagin solver.
*
* ## INTRODUCTION
*
* In 1970', researchers [1], [2] have developed a hybrid dynamics algorithm for evaluating robot behavior
* based on the input specification that is defined by the Cartesian acceleration constraints,
* feed-forward joint torques and external Cartesian wrenches. The solver is derived from a well-known
* principle of mechanics - **Gauss' principle of least constraint** [6] and provides an analytical (closed-form)
* solution to the hybrid dynamics problem with linear-time, **O(n)** complexity [3].
*
* In general, the Gauss' principle states that the true motion (acceleration) of a system/body is defined
* by the minimum of a quadratic function that is subject to linear geometric motion constraints [7], [6].
* The result of this Gauss function represents the **acceleration energy** of a body, which is defined by
* the product of its mass and the squared distance between its allowed (constrained) acceleration and its free
* (unconstrained) acceleration [10], [11]. In the case of originally derived Popov-Vereshchagin algorithm [1],
* geometric motion constraints are Cartesian acceleration constraints imposed on the robot's end-effector.
* This domain-specific solver minimizes the acceleration energy by performing computational (outward and inward)
* sweeps along the robot's kinematic chain [3]. Furthermore, by computing the minimum of Gauss function,
* the Popov-Vereshchagin solver resolves the kinematic redundancy of the robot, when a partial motion (task)
* specification is provided [2]. A necessary condition that enables this type of closed-form algorithm
* (an analytical solution to the above-described optimization problem) defines that the robots kinematic
* chain does not consist of closed loops, i.e. the robots kinematic chain must be constructed in a serial
* or tree structure [11]. However, it is always possible to cut these loops and introduce explicit constrains.
*
* For evaluating robot dynamics, i.e. resolving its constrained motion, the Popov-Vereshchagin solver is
* performing three computational sweeps (recursions), along the kinematic chain [3]. More specifically,
* two sweeps in **outward** and one sweep in **inward** direction. In the case of robot dynamics algorithms,
* the outward sweep refers to a recursion that is covering a kinematic chain from proximal to distal segments,
* while the inward sweep is covering a kinematic chain from distal to proximal segments [5]. Additionally,
* after completing the recursion in the second sweep and before starting the recursion in the last sweep,
* the solver is computing magnitudes of constraint forces, i.e. the Langrage multiplier (noted as **nu** in
* the KDL's solver implementation and original solver's publication[2]). More specifically, this operation is
* performed when the algorithm reaches segment (link) **{0}**, namely the base segment. In this formulation
* of the solver, the gravity effects are taken into account by setting the base-link's acceleration equal
* to gravitational acceleration [3].
*
* For more detailed description of the algorithm and its representation, the reader can refer to [3], [5], [11].
*
* ## INTERFACES
*
* ### Solver's Input
*
* For computing solutions to the constrained hybrid dynamics problem, this original derivation of
* the Popov-Vereshchagin solver [3] takes into account the following inputs:
*
* * Robot's **model** defined by: kinematic parameters of the chain, segments' mass and rigid-body
* inertia, and effective inertia of each joint rotor -> **chain** parameter in solver's constructor
*
* * **Root** acceleration of the robot's base segment (usually gravitational) -> **root_acc** parameter
* in solver's constructor
*
* * Current joint configuration (angles) -> **q** parameter in the **CartToJnt** function
*
* * Current joint velocities -> **q_dot** parameter in the **CartToJnt** function
*
* * Motion drivers:
* * - **Cartesian Acceleration Constraints** imposed on the end-effector segment -> **alpha** and
* **beta** parameters in the **CartToJnt** function
* * - **Cartesian External Wrench** acting on each segment -> **f_ext** parameter in the **CartToJnt** function
* * - **Feed-Forward Torque** acting on each joint -> **ff_torques** parameter in the **CartToJnt** function
*
* The following outlines the above-listed task interfaces in more detail.
*
* #### Cartesian Acceleration Constraints: alpha & beta
*
* This first type of motion driver can be used for specifying **physical** constraints such as contacts with environment [3],
* or **artificial** (i.e. task-imposed) constraints defined by the operational space task definition for the end-effector
* (tool-tip) segment. **Note**: the Vereshchagin solver expects that the input Cartesian Acceleration Constraints, i.e.
* unit constraint forces in alpha parameters, are expressed w.r.t. robot's base frame. However, the acceleration energy
* setpoints, i.e. beta parameters, are expressed w.r.t. above-defined unit constraint forces. More specifically, each DOF
* (element) in beta parameter corresponds to its respective DOF (column) of the unit constraint force matrix (alpha) [11].
*
* To use this interface, a user should define **i)** the active constraint directions via **alpha** parameter, which is
* a **6 x m** matrix of spatial unit constraint forces, and **ii)** acceleration energy setpoints via **beta**, which is
* a **m x 1** vector. Here, the number of constraints **m**, or in another words number of spatial unit constraint forces
* is not required to always be equal to **6**, which means that a human programmer can leave some of the degrees of freedom
* unspecified [2] for this motion driver, and still produce valid joint control commands [5]. For example, if we want to
* constrain the motion of the end-effector segment in only one direction, namely linear **x**-direction, we can define
* the constraint as [3]:
*
* **alpha** =
* | |
* | --|
* | 1 |
* | 0 |
* | 0 |
* | 0 |
* | 0 |
* | 0 |
*
* **beta** = | 0 |
*
* Note that here, the first three rows of matrix **alpha** represent linear elements and the last three rows represent
* angular elements, of the spatial unit force defined in Plücker coordinates [4]. By giving zero value to acceleration
* energy setpoint (**beta**), we are defining that the end-effector is not allowed to have linear acceleration in **x**
* direction. Or in other words, we are restricting the robot from producing any acceleration energy in that specified direction.
*
* Another example includes the specification of constraints in **5 DOFs**. We can constrain the motion of robot's end-effector
* such that it is only allowed to **freely** move in the linear **z**-direction, without performing linear motions in **x**
* and **y** and angular motions in **x**, **y** and **z** directions:
*
* **alpha** =
* | | | | | |
* | --| --| --| --| --|
* | 1 | 0 | 0 | 0 | 0 |
* | 0 | 1 | 0 | 0 | 0 |
* | 0 | 0 | 0 | 0 | 0 |
* | 0 | 0 | 1 | 0 | 0 |
* | 0 | 0 | 0 | 1 | 0 |
* | 0 | 0 | 0 | 0 | 1 |
*
* **beta** =
* | |
* | --|
* | 0 |
* | 0 |
* | 0 |
* | 0 |
* | 0 |
*
* For both above-described task examples, the Acceleration Constrained Hybrid Dynamics (ACHD) solver will compute
* valid control (constraint) joint torques, even though some of the Cartesian DOFs are left unspecified
* (e.g. in the case of the second example that would be end-effector's **z**-direction). More specifically:
* ``Underconstrained motion specifications are naturally resolved using Gauss' principle of least constraint`` [5].
* This means that in those directions in which the robot is not constrained by the task definition, its motions will
* be controlled by the nature. For instance, in the second example, natural resolution of the robot motion would define
* that the end-effector "**falls**" in the linear **z** direction due to effects of gravity, with the assumption that
* gravity forces are acting along $z$-direction.
*
* Moreover, the motion specification in the second example is equivalent to:
*
* **alpha** =
* | | | | | | |
* | --| --| --| --| --| --|
* | 1 | 0 | 0 | 0 | 0 | 0 |
* | 0 | 1 | 0 | 0 | 0 | 0 |
* | 0 | 0 | 0 | 0 | 0 | 0 |
* | 0 | 0 | 0 | 1 | 0 | 0 |
* | 0 | 0 | 0 | 0 | 1 | 0 |
* | 0 | 0 | 0 | 0 | 0 | 1 |
* (note that elements in the third column are all zeros, meaning z-linear constraint is deactivated)
*
* **beta** =
* | |
* | --|
* | 0 |
* | 0 |
* | 0 |
* | 0 |
* | 0 |
* | 0 |
*
* The last example involves the full specification of the desired end-effector motion (in this case,
* not necessarily zero accelerations), i.e. specification of constraints in all 6 **DOFs**:
*
* **alpha** =
* | | | | | | |
* | --| --| --| --| --| --|
* | 1 | 0 | 0 | 0 | 0 | 0 |
* | 0 | 1 | 0 | 0 | 0 | 0 |
* | 0 | 0 | 1 | 0 | 0 | 0 |
* | 0 | 0 | 0 | 1 | 0 | 0 |
* | 0 | 0 | 0 | 0 | 1 | 0 |
* | 0 | 0 | 0 | 0 | 0 | 1 |
*
* **beta** = **alpha^T * X_dotdot_N**
*
* Here, **N** stands for the index of the last robot's segment, end-effector (tool-tip). The reader should note
* that we can directly assign values (magnitudes) of the desired (task-defined) spatial acceleration **6 x 1**
* vector **X_dotdot_N** to the **6 x 1** vector of acceleration energy (**beta**) [3]. Even though physical
* dimensions (units) of these two vectors are not the same, the property of matrix **alpha** (it contains
* **unit** vectors), permits that we can assign values of desired accelerations to acceleration energy setpoints,
* in respective directions. Namely, each column of matrix **alpha** has the value of **1** in the respective
* direction in which constraint force works, thus it follows that the value of acceleration energy setpoint is
* the same as the value of Cartesian acceleration, in the respective direction.
*
* #### External Forces: f_ext
*
* This type of driver can be used for specifying **physical** (but not artificial, i.e. not task-introduced)
* Cartesian wrenches acting on each of the robot's segments [11]. Examples for a **physical** force on a segment can be:
* **i)** a known weight at the robot's gripper, for instance, a grasped cup or **ii)** a force from a human pushing
* the robot [5]. Note that the implementation of Vereshchagin solver in KDL expects the provided **f_ext** is
* expressed w.r.t. robot's base frame, which is in contrast to the case of KDL's RNE solver.
*
* ### Feed-Forward Joint Torques: ff_torque
*
* This type of motion driver can be used for specifying **physical** (but not artificial, i.e. not task-introduced)
* joint torques, for example, spring and/or damper-based torques (e.g. friction effects) in robot's joints [11].
*
* Additional examples on using these input interfaces can be found in "../tests/solvertest.cpp":
*
* * VereshchaginTest() function - an example on how to use all interfaces of this solver for computing
* the solution to the Hybrid Dynamics (HD) problem.
*
* * FdAndVereshchaginSolversConsistencyTest() function - an example on how to only use this solver for
* computing the solution to the Featherstone's (i.e. Articulated Body Algorithm (ABA)) version of
* the Forward Dynamics (FD) problem.
*
* ### Solver's Output
*
* This recursive dynamics solver is computing several quantities that represent solutions to both, inverse and
* forward dynamics problems, or in other words solutions to the constrained hybrid dynamics problem.
* More specifically, the output interface of the original Popov-Vereshchagin algorithm consists of [3], [5]:
*
* * Magnitudes of constraint forces that act on the end-effector, denoted by the Lagrange multiplier **nu**
* in the solver's implementation and original solver's publication[2].
*
* * Joint constraint torques required for achieving the desired (acceleration-constraints-defined) behavior of
* the robot: **constraint_torque**. These torques represent control commands that should be sent to robot's joint drivers.
*
* * Argument that defines the solution to the originally formulated optimization problem in **Gauss' principle**.
* In other words, the joint accelerations **q_dotdot** resulting from the total torque acting on each joint (**total_torque**),
* i.e. from the aforementioned constraint torques and all natural and external forces acting on the system.
*
* * The resulting and complete spatial accelerations of each segment in the kinematic chain: **X_dotdot**
*
* Furthermore, if necessary, a complete spatial vector of imposed constraint forces can be computed [3],
* from the following relation: **alpha * nu**.
*
* The reader should note that this **constraint_torque** is the **necessary** control command that a user is supposed
* to send to robot's joints, to achieve the motion that is computed (resolved) by the Popov-Vereshchagin solver.
* More specifically, here **constraint_torque** represent solution to the **Inverse Dynamics (ID)** problem.
* Nevertheless, the reason why a user is not supposed to use the **total_torque** values as the control commands
* for robot's joints, is the fact that the torque contributions that represent the difference between **total_torque**
* and **constraint_torque** already exist (act) on robot joints. More specifically, these **additional (residual)**
* contributions are produced on the joints by the already existing natural forces that act on the system [11].
*
* On the other side, joint accelerations, namely **q_dotdot** provide solution to the **Forward Dynamics (FD)** problem
* and these quantities can be used for both control (integrate to joint positions/velocities) and simulation purposes [11].
*
* ## PRACTICAL INSIGHTS/CONSIDERATIONS
*
* The Popov-Vereshchagin hybrid dynamics solver enables a user to achieve many types of operational space tasks [11].
* In other words, various controllers can be implemented **around** the aforementioned interfaces of the algorithm.
* Examples can be controllers for hybrid force/position control, impedance control, etc. However, there are some practical
* insights about this algorithm that need to taken into account.
*
* ### Prioritizations between motion drivers (interfaces)
*
* The original derivation of this solver, which is considered in this library, prioritizes Cartesian acceleration constrains
* (specified for the end-effector segment) over other two motion drivers (Cartesian external wrenches and feedforward joint torques) [11].
* In practice, this means the following:
*
* * If the external wrenches and/or feedforward joint torques contribute positively (i.e. assist) in producing Cartesian accelerations
* (specified via acceleration constraint interface), the Vereshchagin solver will take advantage of these forces to compute
* (acceleration-) energy optimal motions.
*
* * On the other hand, if the aforementioned external wrenches and/or feedforward joint torques contribute negatively (i.e. interfere)
* the Cartesian accelerations, the Vereshchagin solver will compensate all of those forces to correctly produce constrained
* accelerations of the end-effector. More specifically, additional torque commands will be computed under
* **constrained joint torques** (**ctrl_torques** in this implementation), to overcome those "disturbances".
*
* Nevertheless, the above-described prioritization can be changed (see [3] & [5] for more details) but those features are not implemented in KDL.
*
* ### Using the algorithm for solving forward dynamics (FD) problem
*
* The reader should note that the Popov-Vereshchagin solver represents an extension to the well-known forward-dynamics
* Articulated Body Algorithm (ABA) developed by Featherstone and described in [4] (moreover, Featherstone mentioned Vereshchagin solver
* in his book [4], page 117). This means that the Popov-Vereshchagin solver can also be purely used as this Articulated Body Algorithm
* forward-dynamics algorithm. In that case, it is necessary for the user to deactivate all Cartesian acceleration constraints (it is sufficient
* to set all elements in **alpha** matrix to zero) and proceed using other two interfaces as in the case of standard FD solver. More specifically,
* use **f_ext** input to define **physical** external wrenches acting on the robot's body (should be expressed w.r.t. robot's base frame) and
* **ff_torque** input to define command torques acting in robot's joints. The resulting robot's motion can be taken from **q_dotdot** and
* **X_dotdot** solver's outputs.
*
* Nevertheless, the Popov-Vereshchagin solver can also be used for solving more advanced forward dynamics problems, than those solved by ABA [4].
* More specifically, if this solver is used in a certain simulation environment for the use-case of simulating robot behaviors, all three
* interfaces can be exploited for defining a more descriptive robot's state. Here, a user can exploit the Cartesian acceleration constraint
* interface to specify different constraints imposed on the end-effector, along with other interfaces, and simulate what would be the robot's
* behavior due to these constraints and environmental impacts. Here, the resulting robot's motion can, as well, be taken from **q_dotdot** and
* **X_dotdot** solver's outputs. For example, MuJoCo framework (see MuJoCo's documentation) also uses Gauss' principle of least constraint to
* simulate constraint forces in certain situations, however, there, final derivation of this principle in the software is different. However, in
* the case of this more advanced forward dynamics computations, the user needs to be aware of prioritizations between input interfaces
* (mentioned in "Prioritizations" section above) and internal policies on
* handling singularities (mentioned in "Singularities and matrix inversions" section below).
*
* ### Singularities and matrix inversions
*
* To find the minimal-energy solution to the Inverse Dynamics (ID) problem, i.e. find the Langrage multiplier **nu**, the solver needs to compute
* the inverse of a so-called "acceleration constraint coupling matrix"[3] in the balance equation before starting the third sweep.
* However, the robot's configuration has a direct impact on this matrix and its inversion. Namely, if the robot is in a singular configuration for
* the task specified via acceleration constraints, this matrix will become rank-deficient. This means that it is not possible to find a feasible
* solution for that particular end-effector's DOF that is (or DOFs that are) lost due to the singular configuration. In other words, it is not
* possible to find **constraint torques** that will satisfy imposed acceleration constraints in that DOF/DOFs. Nevertheless, in this situation,
* it is still possible to find the (energy-optimal) solution for other "non-singular" DOFs. For that reason, in KDL's implementation of the solver,
* matrix inverse is found by using the SVD technique to construct a pseudo inverse. Additionally, in this implementation, a control policy is
* introduced via the truncated-SVD method to deactivate, i.e. more specifically **ignore**, acceleration constraints for the DOFs that are lost due
* to robot's singular configuration. Of course, this is a choice (control policy), i.e. only one option for solving the singularity problem and
* producing safe joint commands. It is left for the user to explore other control policies (options) for this particular problem if of course,
* the user is not satisfied with the current control policy.
*
* ### Supported robot models
*
* KDL's current implementation of the Vereshchagin HD solver supports only robot chains that have equal number of joints and segments.
* Moreover, this implementation can only compute dynamics for **serial** type of chains, i.e. currently, **tree** robot structures are not supported
* in this solver. Nevertheless, the original solver's derivation has been extended in [3] to account for multiple motion constraints imposed
* on a **tree** robot structure. This extension does not only account for acceleration constraints imposed on multiple end-effectors but also for
* acceleration constraints imposed on more proximal segments. However, the above-mentioned extensions are currently not implemented in this version of KDL.
*
* ## REFERENCES
*
* [1] E. P. Popov, A. F. Vereshchagin, and S. L. Zenkevich, "Manipulyatsionnye roboty: Dinamika i algoritmy", Nauka, Moscow, 1978.
*
* [2] A. F. Vereshchagin, “Modelling and control of motion of manipulation robots”, Soviet Journal of Computer and Systems Sciences, vol. 27, pp. 2938, 1989.
*
* [3] A. Shakhimardanov, “Composable robot motion stack: Implementing constrained hybrid dynamics using semantic models of kinematic chains”, PhD thesis, KU Leuven, 2015.
*
* [4] R. Featherstone, Rigid body dynamics algorithms. Springer, 2008.
*
* [5] S. Schneider and H. Bruyninckx, “Exploiting linearity in dynamics solvers for the design of composable robotic manipulation architectures”, in IEEE/RSJ International Conference on Intelligent Robots and Systems (IROS), 2019.
*
* [6] H. Bruyninckx and O. Khatib, "Gauss principle and the dynamics of redundant and constrained manipulators", in IEEE International Conference on Robotics and Automation, 2000.
*
* [7] C. F. Gauß, "Über ein neues allgemeines Grundgesetz der Mechanik.", Journal für die reine und angewandte Mathematik, vol. 4, pp. 232235, 1829.
*
* [8] A. F. Vereshchagin, “Computer simulation of the dynamics of complicated mechanisms of robot-manipulators”, Engineering Cybernetics, 12(6), pp. 6570, 1974.
*
* [9] E. P. Popov, "Control of robots-manipulators", Engineering Cybernetics, 1974.
*
* [10] E. Ramm, “Principles of least action and of least constraint”, GAMM-Mitteilungen, vol. 34, pp. 164182, 2011.
*
* [11] D. Vukcevic, "Lazy Robot Control by Relaxation of Motion and Force Constraints." Technical Report/Hochschule Bonn-Rhein-Sieg University of Applied Sciences, Department of Computer Science, 2020.
*
* @ingroup KinematicFamily
*/
class ChainHdSolver_Vereshchagin : KDL::SolverI
{
typedef std::vector<Twist> Twists;
typedef std::vector<Frame> Frames;
typedef Eigen::Matrix<double, 6, 1 > Vector6d;
typedef Eigen::Matrix<double, 6, 6 > Matrix6d;
typedef Eigen::Matrix<double, 6, Eigen::Dynamic> Matrix6Xd;
public:
/**
* Constructor for the solver, it will allocate all the necessary memory
* \param chain The kinematic chain to calculate the hybrid dynamics for. An internal copy will be made.
* \param root_acc The acceleration twist of the root segment to use during the calculation (usually contains gravity).
* Note: This solver takes gravity acceleration with opposite sign comparead to the KDL's FD and RNE solvers
* \param nc Number of constraints imposed on the robot's end-effector (maximum is 6).
*/
ChainHdSolver_Vereshchagin(const Chain& chain, const Twist &root_acc, const unsigned int nc);
~ChainHdSolver_Vereshchagin()
{
};
/**
* This method calculates joint space constraint torques and accelerations.
* It returns 0 when it succeeds, otherwise -1 or -2 for nonmatching matrix and array sizes.
* Input parameters:
* \param q The current joint positions
* \param q_dot The current joint velocities
* \param alpha The active constraint directions (unit constraint forces expressed w.r.t. robot's base frame)
* \param beta The acceleration energy setpoints (expressed w.r.t. above-defined unit constraint forces)
* \param f_ext The external forces (no gravity, it is given in root acceleration) on the segments
* \param ff_torques The feed-forward joint space torques
*
* Output parameters:
* \param q_dotdot The resulting joint accelerations
* \param constraint_torques The resulting joint constraint torques (what each joint feels due to the constraint forces acting on the end-effector)
*
* @return error/success code
*/
int CartToJnt(const JntArray &q, const JntArray &q_dot, JntArray &q_dotdot, const Jacobian& alfa, const JntArray& beta, const Wrenches& f_ext, const JntArray &ff_torques, JntArray &constraint_torques);
/// @copydoc KDL::SolverI::updateInternalDataStructures
virtual void updateInternalDataStructures();
//Returns cartesian acceleration of links in base coordinates
void getTransformedLinkAcceleration(Twists& x_dotdot);
// Returns total torque acting on each joint (constraints + nature + external forces)
void getTotalTorque(JntArray &total_tau);
// Returns magnitude of the constraint forces acting on the end-effector: Lagrange Multiplier
void getContraintForceMagnitude(Eigen::VectorXd &nu_);
/*
//Returns cartesian positions of links in base coordinates
void getLinkCartesianPose(Frames& x_base);
//Returns cartesian velocities of links in base coordinates
void getLinkCartesianVelocity(Twists& xDot_base);
//Returns cartesian acceleration of links in base coordinates
void getLinkCartesianAcceleration(Twists& xDotDot_base);
//Returns cartesian positions of links in link tip coordinates
void getLinkPose(Frames& x_local);
//Returns cartesian velocities of links in link tip coordinates
void getLinkVelocity(Twists& xDot_local);
//Returns cartesian acceleration of links in link tip coordinates
void getLinkAcceleration(Twists& xDotdot_local);
//Acceleration energy due to unit constraint forces at the end-effector
void getLinkUnitForceAccelerationEnergy(Eigen::MatrixXd& M);
//Acceleration energy due to arm configuration: bias force plus input joint torques
void getLinkBiasForceAcceleratoinEnergy(Eigen::VectorXd& G);
void getLinkUnitForceMatrix(Matrix6Xd& E_tilde);
void getLinkBiasForceMatrix(Wrenches& R_tilde);
void getJointBiasAcceleration(JntArray &bias_q_dotdot);
*/
private:
/**
* This method calculates all cartesian space poses, twists, bias accelerations.
* External forces are also taken into account in this outward sweep.
*/
void initial_upwards_sweep(const JntArray &q, const JntArray &q_dot, const JntArray &q_dotdot, const Wrenches& f_ext);
/**
* This method is a force balance sweep. It calculates articulated body inertias and bias forces.
* Additionally, acceleration energies generated by bias forces and unit forces are calculated here.
*/
void downwards_sweep(const Jacobian& alfa, const JntArray& ff_torques);
/**
* This method calculates constraint force magnitudes.
*
*/
void constraint_calculation(const JntArray& beta);
/**
* This method puts all acceleration contributions (constraint, bias, nullspace and parent accelerations) together.
*
*/
void final_upwards_sweep(JntArray &q_dotdot, JntArray &constraint_torques);
private:
const Chain& chain;
unsigned int nj;
unsigned int ns;
unsigned int nc;
Twist acc_root;
Jacobian alfa_N;
Jacobian alfa_N2;
Eigen::MatrixXd M_0_inverse;
Eigen::MatrixXd Um;
Eigen::MatrixXd Vm;
JntArray beta_N;
Eigen::VectorXd nu;
Eigen::VectorXd nu_sum;
Eigen::VectorXd Sm;
Eigen::VectorXd tmpm;
Eigen::VectorXd total_torques; // all the contributions that are felt at the joint: constraints + nature + external forces
Wrench qdotdot_sum;
Frame F_total;
struct segment_info
{
Frame F; //local pose with respect to previous link in segments coordinates
Frame F_base; // pose of a segment in root coordinates
Twist Z; //Unit twist
Twist v; //twist
Twist acc; //acceleration twist
Wrench U; //wrench p of the bias forces (in cartesian space)
Wrench R; //wrench p of the bias forces
Wrench R_tilde; //vector of wrench p of the bias forces (new) in matrix form
Twist C; //constraint
Twist A; //constraint
ArticulatedBodyInertia H; //I (expressed in 6*6 matrix)
ArticulatedBodyInertia P; //I (expressed in 6*6 matrix)
ArticulatedBodyInertia P_tilde; //I (expressed in 6*6 matrix)
Wrench PZ; //vector U[i] = I_A[i]*S[i]
Wrench PC; //vector E[i] = I_A[i]*c[i]
double D; //vector D[i] = S[i]^T*U[i]
Matrix6Xd E; //matrix with virtual unit constraint force due to acceleration constraints
Matrix6Xd E_tilde;
Eigen::MatrixXd M; //acceleration energy already generated at link i
Eigen::VectorXd G; //magnitude of the constraint forces already generated at link i
Eigen::VectorXd EZ; //K[i] = Etiltde'*Z
double nullspaceAccComp; //Azamat: constribution of joint space u[i] forces to joint space acceleration
double constAccComp; //Azamat: constribution of joint space constraint forces to joint space acceleration
double biasAccComp; //Azamat: constribution of joint space bias forces to joint space acceleration
double totalBias; //Azamat: R+PC (centrepital+coriolis) in joint subspace
double u; //vector u[i] = torques(i) - S[i]^T*(p_A[i] + I_A[i]*C[i]) in joint subspace. Azamat: In code u[i] = torques(i) - s[i].totalBias
segment_info(unsigned int nc):
D(0),nullspaceAccComp(0),constAccComp(0),biasAccComp(0),totalBias(0),u(0)
{
E.resize(6, nc);
E_tilde.resize(6, nc);
G.resize(nc);
M.resize(nc, nc);
EZ.resize(nc);
E.setZero();
E_tilde.setZero();
M.setZero();
G.setZero();
EZ.setZero();
};
};
std::vector<segment_info, Eigen::aligned_allocator<segment_info> > results;
};
}
#endif // KDL_CHAINHDSOLVER_VERESHCHAGIN_HPP