Forked from an inaccessible project.
-
roberto rossi authoredroberto rossi authored
eepos.cpp 6.20 KiB
// Own
#include "eepos.h"
#include "common_fc.h"
#include "kinematics.h"
// MISC
#include <iostream> /* input, output operations */
namespace UAM {
CTaskEEPOS::CTaskEEPOS(){}
CTaskEEPOS::~CTaskEEPOS(){}
Eigen::Vector3d CTaskEEPOS::RToEulerMin(const Eigen::Matrix3d& Rot)
{
Eigen::Vector3d ang;
if (Rot(2,0)!=-1.0 && Rot(2,0)!=1.0)
{
double phi1, theta1, psi1;
double phi2, theta2, psi2;
theta1 = -asin(Rot(2,0));
theta2 = 3.141592653589793 - theta1;
psi1 = atan2(Rot(2,1)/cos(theta1),Rot(2,2)/cos(theta1));
psi2 = atan2(Rot(2,1)/cos(theta2),Rot(2,2)/cos(theta2));
phi1 = atan2(Rot(1,0)/cos(theta1),Rot(0,0)/cos(theta1));
phi2 = atan2(Rot(1,0)/cos(theta2),Rot(0,0)/cos(theta2));
// TODO: This statement can cause big discontinuities in the obtained angles when
// the two norms are similar.
if (sqrt(std::pow(theta1,2)+std::pow(psi1,2)+std::pow(phi1,2)) < sqrt(std::pow(theta2,2)+std::pow(psi2,2)+std::pow(phi2,2)))
ang << psi1, theta1, phi1;
else
ang << psi2, theta2, phi2; // ZYX Euler convention.
}
else
{
double phi, theta, psi;
phi = 0.0;
if (Rot(2,0)==-1.0)
{
theta = 3.141592653589793/2;
psi = phi + atan2(Rot(0,1),Rot(0,2));
}
else
{
theta = -3.141592653589793/2;
psi = -phi + atan2(-Rot(0,1),-Rot(0,2));
}
ang << phi, theta, psi;
}
return ang;
}
Eigen::Vector3d CTaskEEPOS::RToEulerContinuous(const Eigen::Matrix3d& Rot, const Eigen::Vector3d& rpy_old)
{
Eigen::Vector3d ang;
if (Rot(2,0)!=-1.0 && Rot(2,0)!=1.0)
{
double phi1, theta1, psi1;
double phi2, theta2, psi2;
Eigen::Vector3d ang1;
Eigen::Vector3d ang2;
theta1 = -asin(Rot(2,0));
theta2 = 3.141592653589793 - theta1;
psi1 = atan2(Rot(2,1)/cos(theta1),Rot(2,2)/cos(theta1));
psi2 = atan2(Rot(2,1)/cos(theta2),Rot(2,2)/cos(theta2));
phi1 = atan2(Rot(1,0)/cos(theta1),Rot(0,0)/cos(theta1));
phi2 = atan2(Rot(1,0)/cos(theta2),Rot(0,0)/cos(theta2));
ang1 << psi1, theta1, phi1;
ang2 << psi2, theta2, phi2;
if ( (rpy_old-ang1).norm() < (rpy_old-ang2).norm())
ang = ang1;
else
ang = ang2; // ZYX Euler convention.
}
else
{
double phi, theta, psi;
phi = 0.0;
if (Rot(2,0)==-1.0)
{
theta = 3.141592653589793/2;
psi = phi + atan2(Rot(0,1),Rot(0,2));
}
else
{
theta = -3.141592653589793/2;
psi = -phi + atan2(-Rot(0,1),-Rot(0,2));
}
ang << phi, theta, psi;
}
return ang;
}
void CTaskEEPOS::TaskErrorJac(const UAM::CHT& HT, UAM::CArm& arm, const Eigen::MatrixXd& vs_delta_gain, const double& vs_alpha_min, const Eigen::MatrixXd& eepos_des, Eigen::MatrixXd& sigmaEEPOS, Eigen::MatrixXd& JEEPOS_reduced, Eigen::MatrixXd& JEEPOS_pseudo_reduced)
{
// Initialize sizes
sigmaEEPOS = Eigen::MatrixXd::Zero(6,1);
Eigen::MatrixXd JEEPOS = Eigen::MatrixXd::Zero(6,6+arm.nj);
Eigen::MatrixXd JEEPOS_pseudo = Eigen::MatrixXd::Zero(6+arm.nj,6);
// Task Error ________________________________________________
// End-Effector Position Error
sigmaEEPOS.block(0,0,3,1) = eepos_des.block(0,0,3,1) - HT.cam_in_w.block(0,3,3,1);
// End-Effector Orientation Error
sigmaEEPOS.block(3,0,3,1) = eepos_des.block(3,0,3,1) - RToEulerContinuous(HT.cam_in_w.block(0,0,3,3),eepos_des.block(3,0,3,1));
// Task Jacobian _____________________________________________
// Quadrotor
Eigen::Matrix3d Rb_in_w = HT.baselink_in_w.block(0,0,3,3);
Eigen::Matrix3d Re_in_w = HT.cam_in_w.block(0,0,3,3);
Eigen::Matrix3d Re_in_b = HT.cam_in_baselink.block(0,0,3,3);
Eigen::Vector3d pe_in_b = HT.cam_in_baselink.block(0,3,3,1);
Eigen::Vector3d euRb_in_w = RToEulerMin(Rb_in_w);
Eigen::Vector3d euRe_in_w = RToEulerMin(Re_in_w);
Eigen::Matrix3d wTb = UAM::CCommon_Fc::GetWronskian(euRb_in_w(0),euRb_in_w(1));
Eigen::Matrix3d wTb_inv = wTb.inverse();
Eigen::Matrix3d wTe = UAM::CCommon_Fc::GetWronskian(euRe_in_w(0),euRe_in_w(1));
// TODO: Remove
// Eigen::Matrix3d Aux_Frame_Matrix1 = Eigen::Vector3d(1,-1,1).asDiagonal();
// Eigen::Matrix3d Aux_Frame_Matrix1 = Eigen::Matrix3d::Zero();
// Aux_Frame_Matrix1(0,2) = 1.0;
// Aux_Frame_Matrix1(1,1) = -1.0;
// Aux_Frame_Matrix1(2,0) = 1.0;
//JEEPOS_omw.block(0,3,3,3) = -Rb_in_w*(UAM::CCommon_Fc::Skew(Aux_Frame_Matrix1*pe_in_b))*wTb_inv;
Eigen::MatrixXd JEEPOS_omw = Eigen::MatrixXd::Zero(6,6+arm.nj);
JEEPOS_omw.block(0,0,3,3) = Eigen::MatrixXd::Identity(3,3);
JEEPOS_omw.block(3,0,3,3) = Eigen::MatrixXd::Zero(3,3);
JEEPOS_omw.block(0,3,3,3) = -Rb_in_w*(UAM::CCommon_Fc::Skew(pe_in_b))*wTb_inv;
JEEPOS_omw.block(3,3,3,3) = Re_in_w*Re_in_b.transpose()*wTb_inv;
// Arm
Eigen::MatrixXd ArmJac = UAM::CKinematics::ArmJac(arm);
Eigen::MatrixXd RRb_in_w = Eigen::MatrixXd::Zero(6,6);
Eigen::Matrix3d Rarmb_in_b = HT.armbase_in_baselink.block(0,0,3,3);
Eigen::Matrix3d Rl1_in_armb = HT.link1_in_armbase.block(0,0,3,3);
// TODO: resolve why these blocks are different
RRb_in_w.block(0,0,3,3) = Rb_in_w;
RRb_in_w.block(3,3,3,3) = Rb_in_w * Rarmb_in_b * Rl1_in_armb;
// RRb_in_w.block(0,0,3,3) = Rb_in_w * Rarmb_in_b * Rl1_in_armb;
// RRb_in_w.block(3,3,3,3) = RRb_in_w.block(0,0,3,3);
JEEPOS_omw.block(0,6,6,arm.nj) = RRb_in_w * ArmJac;
Eigen::MatrixXd omega2euldiff_in_w = Eigen::MatrixXd::Zero(6,6);
omega2euldiff_in_w.block(0,0,3,3) = Eigen::MatrixXd::Identity(3,3);
omega2euldiff_in_w.block(3,3,3,3) = wTe*Re_in_w.transpose();
JEEPOS.block(0,0,6,6) = omega2euldiff_in_w*JEEPOS_omw.block(0,0,6,6);
JEEPOS.block(0,6,6,arm.nj) = omega2euldiff_in_w*JEEPOS_omw.block(0,6,6,arm.nj);
// task jacobian pseudo inverse
//JEEPOS_pseudo = UAM::CCommon_Fc::WeightInvJac(JEEPOS,vs_delta_gain,vs_alpha_min,sigmaEEPOS.block(0,0,3,1).norm());
JEEPOS_pseudo = JEEPOS.transpose();
// Return reduced Jacobians (without roll and pitch columns)
JEEPOS_reduced = Eigen::MatrixXd::Zero(6,4+arm.nj);
JEEPOS_reduced.block(0,0,6,3) = JEEPOS.block(0,0,6,3);
JEEPOS_reduced.block(0,3,6,1+arm.nj) = JEEPOS.block(0,5,6,1+arm.nj);
JEEPOS_pseudo_reduced = Eigen::MatrixXd::Zero(4+arm.nj,6);
JEEPOS_pseudo_reduced.block(0,0,3,6) = JEEPOS_pseudo.block(0,0,3,6);
JEEPOS_pseudo_reduced.block(3,0,1+arm.nj,6) = JEEPOS_pseudo.block(5,0,1+arm.nj,6);
}
} // End of UAM namespace