OCS2::ocs2_centroidal_model_质心动量模型

news/2024/12/19 17:24:15/文章来源:https://www.cnblogs.com/penuel/p/18605204

1. ModelHelperFunctions.cpp

1.1 updateCentroidalDynamics() : 质心动力学更新

template <typename SCALAR_T>
void updateCentroidalDynamics(PinocchioInterfaceTpl<SCALAR_T>& interface, const CentroidalModelInfoTpl<SCALAR_T>& info,const Eigen::Matrix<SCALAR_T, Eigen::Dynamic, 1>& q) {using vector3_t = Eigen::Matrix<SCALAR_T, 3, 1>;using matrix3_t = Eigen::Matrix<SCALAR_T, 3, 3>;using matrix6_t = Eigen::Matrix<SCALAR_T, 6, 6>;const auto& model = interface.getModel();auto& data = interface.getData();switch (info.centroidalModelType) {case CentroidalModelType::FullCentroidalDynamics: {pinocchio::computeCentroidalMap(model, data, q);pinocchio::updateFramePlacements(model, data);break;}case CentroidalModelType::SingleRigidBodyDynamics: {//从广义坐标 q 中提取的欧拉角const vector3_t eulerAnglesZyx = q.template segment<3>(3);// 将欧拉角导数映射到全局角速度的映射矩阵const matrix3_t mappingZyx = getMappingFromEulerAnglesZyxDerivativeToGlobalAngularVelocity(eulerAnglesZyx);//基坐标系到世界坐标系的旋转矩阵const matrix3_t rotationBaseToWorld = getRotationMatrixFromZyxEulerAngles(eulerAnglesZyx);//质心相对于基坐标系的位置信息,变换到世界坐标系const vector3_t comToBasePositionInWorld = rotationBaseToWorld * info.comToBasePositionNominal;//质心位置的反对称矩阵,用于计算惯性耦合项const matrix3_t skewSymmetricMap = skewSymmetricMatrix(comToBasePositionInWorld);//用于计算角动量相关的中间矩阵const matrix3_t mat1 = rotationBaseToWorld * info.centroidalInertiaNominal;const matrix3_t mat2 = rotationBaseToWorld.transpose() * mappingZyx;//刚体动力学下的质心动量映射矩阵,6x6 矩阵matrix6_t Ab = matrix6_t::Zero();//template显性的指定矩阵块大小//topLeftCorner左上角3*3块,diagonal:提取对角线元素,array:将对角线视为数组逐元素操作Ab.template topLeftCorner<3, 3>().diagonal().array() = info.robotMass;//noalias():优化矩阵赋值操作Ab.template topRightCorner<3, 3>().noalias() = info.robotMass * skewSymmetricMap * mappingZyx;Ab.template bottomRightCorner<3, 3>().noalias() = mat1 * mat2;//Ag前3行是线动量部分,后3行是角动量部分data.Ag = Eigen::Matrix<SCALAR_T, -1, -1>::Zero(6, info.generalizedCoordinatesNum);//左侧6列赋值为Abdata.Ag.template leftCols<6>() = Ab;data.com[0] = q.template head<3>() - comToBasePositionInWorld;pinocchio::forwardKinematics(model, data, q);pinocchio::updateFramePlacements(model, data);break;}default: {throw std::runtime_error("The chosen centroidal model type is not supported.");break;}}
}

1.2 updateCentroidalDynamicsDerivatives() : 更新质心动力学导数

data.dFdq.setZero(6, info.generalizedCoordinatesNum);
data.dFdq.template middleCols<3>(3) = getCentroidalMomentumZyxGradient(interface, info, q, v);
pinocchio::computeJointJacobians(model, data, q);
pinocchio::updateFramePlacements(model, data);
template <typename SCALAR_T>
Eigen::Matrix<SCALAR_T, 6, 3> getCentroidalMomentumZyxGradient(const PinocchioInterfaceTpl<SCALAR_T>& interface,const CentroidalModelInfoTpl<SCALAR_T>& info,const Eigen::Matrix<SCALAR_T, Eigen::Dynamic, 1>& q,const Eigen::Matrix<SCALAR_T, Eigen::Dynamic, 1>& v) {using matrix_t = Eigen::Matrix<SCALAR_T, Eigen::Dynamic, Eigen::Dynamic>;using vector3_t = Eigen::Matrix<SCALAR_T, 3, 1>;using matrix3_t = Eigen::Matrix<SCALAR_T, 3, 3>;const auto& data = interface.getData();const auto m = info.robotMass;const vector3_t eulerAngles = q.template segment<3>(3);const vector3_t eulerAnglesDerivatives = v.template segment<3>(3);//从欧拉角导数到全局角速度的映射矩阵const auto T = getMappingFromEulerAnglesZyxDerivativeToGlobalAngularVelocity(eulerAngles);//从基座到世界坐标系的旋转矩阵const auto R = getRotationMatrixFromZyxEulerAngles(eulerAngles);matrix3_t Ibaseframe, Iworldframe;vector3_t rbaseframe, rworldframe;switch (info.centroidalModelType) {case CentroidalModelType::FullCentroidalDynamics: {Iworldframe = data.Ig.inertia().matrix();Ibaseframe.noalias() = R.transpose() * (Iworldframe * R);rworldframe = q.template head<3>() - data.com[0];rbaseframe.noalias() = R.transpose() * rworldframe;break;}case CentroidalModelType::SingleRigidBodyDynamics: {Ibaseframe = info.centroidalInertiaNominal;  //归一化的基座惯性张量Iworldframe.noalias() = R * (Ibaseframe * R.transpose()); //世界坐标惯性张量rbaseframe = info.comToBasePositionNominal; //质心位置rworldframe.noalias() = R * rbaseframe;   //世界坐标质心位置break;}default: {throw std::runtime_error("The chosen centroidal model type is not supported.");}}const auto S = skewSymmetricMatrix(rworldframe); //r_com 反对称矩阵const auto dT = getMappingZyxGradient(eulerAngles); //映射矩阵 T 的梯度const auto dR = getRotationMatrixZyxGradient(eulerAngles);// 旋转矩阵R的梯度std::array<matrix3_t, 3> dS;for (size_t i = 0; i < 3; i++) {const vector3_t dr = dR[i] * rbaseframe;dS[i] = skewSymmetricMatrix(dr); //世界坐标质心位置关于欧拉角的梯度}matrix_t dhdq = matrix_t::Zero(6, 3);for (size_t i = 0; i < 3; i++) {const vector3_t T_eulerAnglesDev = T * eulerAnglesDerivatives; const vector3_t dT_eulerAnglesDev = dT[i] * eulerAnglesDerivatives; const matrix3_t dR_I_Rtrans = dR[i] * Ibaseframe * R.transpose();dhdq.template block<3, 1>(0, i).noalias() = m * (S * dT_eulerAnglesDev);dhdq.template block<3, 1>(0, i).noalias() += m * (dS[i] * T_eulerAnglesDev);dhdq.template block<3, 1>(3, i).noalias() = (dR_I_Rtrans + dR_I_Rtrans.transpose()) * T_eulerAnglesDev;dhdq.template block<3, 1>(3, i).noalias() += Iworldframe * dT_eulerAnglesDev;}if (info.centroidalModelType == CentroidalModelType::FullCentroidalDynamics) {const auto jointVelocities = v.tail(info.actuatedDofNum);const vector3_t comLinearVelocityInWorldFrame = (1.0 / m) * (data.Ag.topRightCorner(3, info.actuatedDofNum) * jointVelocities);const vector3_t comAngularVelocityInWorldFrame =Iworldframe.inverse() * (data.Ag.bottomRightCorner(3, info.actuatedDofNum) * jointVelocities);const vector3_t linearMomentumInBaseFrame = m * (R.transpose() * comLinearVelocityInWorldFrame);const vector3_t angularMomentumInBaseFrame = Ibaseframe * (R.transpose() * comAngularVelocityInWorldFrame);for (size_t i = 0; i < 3; i++) {dhdq.template block<3, 1>(0, i).noalias() += dR[i] * linearMomentumInBaseFrame;dhdq.template block<3, 1>(3, i).noalias() += dR[i] * angularMomentumInBaseFrame;}}return dhdq;
}
  • 其中dh/dq的公式为:


1.3 质心(CoM)到特定接触点的平移雅可比矩阵

template <typename SCALAR_T>
Eigen::Matrix<SCALAR_T, 3, Eigen::Dynamic> getTranslationalJacobianComToContactPointInWorldFrame(const PinocchioInterfaceTpl<SCALAR_T>& interface, const CentroidalModelInfoTpl<SCALAR_T>& info, size_t contactIndex) {const auto& model = interface.getModel();auto data = interface.getData();Eigen::Matrix<SCALAR_T, 6, Eigen::Dynamic> jacobianWorldToContactPointInWorldFrame;jacobianWorldToContactPointInWorldFrame.setZero(6, info.generalizedCoordinatesNum);pinocchio::getFrameJacobian(model, data, info.endEffectorFrameIndices[contactIndex], pinocchio::LOCAL_WORLD_ALIGNED,jacobianWorldToContactPointInWorldFrame);Eigen::Matrix<SCALAR_T, 3, Eigen::Dynamic> J_com = getCentroidalMomentumMatrix(interface).template topRows<3>() / info.robotMass;return (jacobianWorldToContactPointInWorldFrame.template topRows<3>() - J_com);
}

1.4 动量的变化率,也就是一阶导

/**********************动量的变化率,也就是一阶导,这里就是求的h_{com}的导数*********************************************************/
template <typename SCALAR_T>
Eigen::Matrix<SCALAR_T, 6, 1> getNormalizedCentroidalMomentumRate(const PinocchioInterfaceTpl<SCALAR_T>& interface,const CentroidalModelInfoTpl<SCALAR_T>& info,const Eigen::Matrix<SCALAR_T, Eigen::Dynamic, 1>& input) {const Eigen::Matrix<SCALAR_T, 3, 1> gravityVector(SCALAR_T(0.0), SCALAR_T(0.0), SCALAR_T(-9.81));Eigen::Matrix<SCALAR_T, 6, 1> centroidalMomentumRate;centroidalMomentumRate << info.robotMass * gravityVector, Eigen::Matrix<SCALAR_T, 3, 1>::Zero();for (size_t i = 0; i < info.numThreeDofContacts; i++) {const auto contactForceInWorldFrame = centroidal_model::getContactForces(input, i, info); //获取接触力const auto positionComToContactPointInWorldFrame = getPositionComToContactPointInWorldFrame(interface, info, i); //r_fcentroidalMomentumRate.template head<3>() += contactForceInWorldFrame;centroidalMomentumRate.template tail<3>().noalias() += positionComToContactPointInWorldFrame.cross(contactForceInWorldFrame);}  // end of i loopfor (size_t i = info.numThreeDofContacts; i < info.numThreeDofContacts + info.numSixDofContacts; i++) {const auto contactForceInWorldFrame = centroidal_model::getContactForces(input, i, info);const auto contactTorqueInWorldFrame = centroidal_model::getContactTorques(input, i, info);const auto positionComToContactPointInWorldFrame = getPositionComToContactPointInWorldFrame(interface, info, i);centroidalMomentumRate.template head<3>() += contactForceInWorldFrame;centroidalMomentumRate.template tail<3>().noalias() +=positionComToContactPointInWorldFrame.cross(contactForceInWorldFrame) + contactTorqueInWorldFrame;}  // end of i loop// normalize by the total masscentroidalMomentumRate /= info.robotMass;return centroidalMomentumRate;
}

2. CentroidalModelPinocchioMapping.cpp

2.1 getPinocchioJointVelocity 获取浮动基座速度

/********************获取浮动基座速度**********************************************************/
template <typename SCALAR>
auto CentroidalModelPinocchioMappingTpl<SCALAR>::getPinocchioJointVelocity(const vector_t& state, const vector_t& input) const -> vector_t {const auto& model = pinocchioInterfacePtr_->getModel();const auto& data = pinocchioInterfacePtr_->getData();const auto& info = centroidalModelInfo_;assert(info.stateDim == state.rows());assert(info.inputDim == input.rows());const auto& A = getCentroidalMomentumMatrix(*pinocchioInterfacePtr_);const Eigen::Matrix<SCALAR, 6, 6> Ab = A.template leftCols<6>(); //取左侧6列关于浮动基座的部分const auto Ab_inv = computeFloatingBaseCentroidalMomentumMatrixInverse(Ab);const auto jointVelocities = centroidal_model::getJointVelocities(input, info).head(info.actuatedDofNum);Eigen::Matrix<SCALAR, 6, 1> momentum = info.robotMass * centroidal_model::getNormalizedMomentum(state, info);if (info.centroidalModelType == CentroidalModelType::FullCentroidalDynamics) {momentum.noalias() -= A.rightCols(info.actuatedDofNum) * jointVelocities;}vector_t vPinocchio(info.generalizedCoordinatesNum);vPinocchio.template head<6>().noalias() = Ab_inv * momentum;vPinocchio.tail(info.actuatedDofNum) = jointVelocities;return vPinocchio;
}
  • computeFloatingBaseCentroidalMomentumMatrixInverse():

2.2 getOcs2Jacobian 动力学公式内的关节速度和浮动速度对状态和输入的偏导

/****主要动力学公式内的关节速度和浮动速度对状态和输入的偏导**************************************************************************/
template <typename SCALAR>
auto CentroidalModelPinocchioMappingTpl<SCALAR>::getOcs2Jacobian(const vector_t& state, const matrix_t& Jq, const matrix_t& Jv) const-> std::pair<matrix_t, matrix_t> {const auto& model = pinocchioInterfacePtr_->getModel();const auto& data = pinocchioInterfacePtr_->getData();const auto& info = centroidalModelInfo_;assert(info.stateDim == state.rows());// Partial derivatives of joint velocities//关节角速度对输入的偏导matrix_t jointVelocitiesDerivativeInput = matrix_t::Zero(info.actuatedDofNum, info.inputDim);jointVelocitiesDerivativeInput.rightCols(info.actuatedDofNum).setIdentity();// Partial derivatives of the floating base variables//浮动基座速度对状态和输入的偏导// TODO: move getFloatingBaseCentroidalMomentumMatrixInverse(Ab) to PreComputationmatrix_t floatingBaseVelocitiesDerivativeState = matrix_t::Zero(6, info.stateDim);matrix_t floatingBaseVelocitiesDerivativeInput = matrix_t::Zero(6, info.inputDim);const auto& A = getCentroidalMomentumMatrix(*pinocchioInterfacePtr_);const Eigen::Matrix<SCALAR, 6, 6> Ab = A.template leftCols<6>();const auto Ab_inv = computeFloatingBaseCentroidalMomentumMatrixInverse(Ab);floatingBaseVelocitiesDerivativeState.leftCols(6) = info.robotMass * Ab_inv;using matrix6x_t = Eigen::Matrix<SCALAR, 6, Eigen::Dynamic>;matrix6x_t dhdq(6, info.generalizedCoordinatesNum);switch (info.centroidalModelType) {case CentroidalModelType::FullCentroidalDynamics: {pinocchio::translateForceSet(data.dHdq, data.com[0], dhdq.const_cast_derived());for (size_t k = 0; k < model.nv; ++k) {dhdq.template block<3, 1>(pinocchio::Force::ANGULAR, k) +=data.hg.linear().cross(data.dFda.template block<3, 1>(pinocchio::Force::LINEAR, k)) / data.Ig.mass();}dhdq.middleCols(3, 3) = data.dFdq.middleCols(3, 3);const auto Aj = A.rightCols(info.actuatedDofNum);floatingBaseVelocitiesDerivativeState.rightCols(info.generalizedCoordinatesNum).noalias() = -Ab_inv * dhdq;floatingBaseVelocitiesDerivativeInput.rightCols(info.actuatedDofNum).noalias() = -Ab_inv * Aj;break;}case CentroidalModelType::SingleRigidBodyDynamics: {dhdq = data.dFdq;floatingBaseVelocitiesDerivativeState.middleCols(6, 6).noalias() = -Ab_inv * dhdq.leftCols(6);break;}default: {throw std::runtime_error("The chosen centroidal model type is not supported.");}}matrix_t dvdx = matrix_t::Zero(info.generalizedCoordinatesNum, info.stateDim);dvdx.template topRows<6>() = floatingBaseVelocitiesDerivativeState;matrix_t dvdu = matrix_t::Zero(info.generalizedCoordinatesNum, info.inputDim);dvdu << floatingBaseVelocitiesDerivativeInput, jointVelocitiesDerivativeInput;matrix_t dfdx = matrix_t::Zero(Jq.rows(), centroidalModelInfo_.stateDim);dfdx.middleCols(6, info.generalizedCoordinatesNum) = Jq;dfdx.noalias() += Jv * dvdx;const matrix_t dfdu = Jv * dvdu;return {dfdx, dfdu};
}

3. CentroidalModelRbdConversions.cpp

3.1 computeBaseKinematicsFromCentroidalModel 计算机体运动学

输入:状态state;输入input;关节角加速度jointAccelerations,
输出:基座位置basePose(从state获取);基座速度baseVelocity(getPinocchioJointVelocity获取);基座加速度
基座加速度公式:
\(A_b \ddot{q}_b = \dot{h}_{com} - \dot{A_b} \dot{q_b} - A_j \ddot{q_j}\)
\(\ddot{q_j}\)一般不考虑,等0

void CentroidalModelRbdConversions::computeBaseKinematicsFromCentroidalModel(const vector_t& state, const vector_t& input,const vector_t& jointAccelerations, Vector6& basePose,Vector6& baseVelocity, Vector6& baseAcceleration) {const auto& model = pinocchioInterface_.getModel();auto& data = pinocchioInterface_.getData();const auto& info = mapping_.getCentroidalModelInfo();const auto qPinocchio = mapping_.getPinocchioJointPosition(state);updateCentroidalDynamics(pinocchioInterface_, info, qPinocchio);// Base Pose in world framebasePose = qPinocchio.head<6>();const auto basePosition = basePose.head<3>();const auto baseOrientation = basePose.tail<3>();// Base Velocity in world frameconst auto& A = getCentroidalMomentumMatrix(pinocchioInterface_); //获取动量矩阵Abconst Matrix6 Ab = A.template leftCols<6>();const auto Ab_inv = computeFloatingBaseCentroidalMomentumMatrixInverse(Ab);const auto Aj = A.rightCols(info.actuatedDofNum);const vector_t vPinocchio = mapping_.getPinocchioJointVelocity(state, input); //获取基座速度baseVelocity.head<3>() = vPinocchio.head<3>();const Vector3 derivativeEulerAnglesZyx = vPinocchio.segment<3>(3);baseVelocity.tail<3>() = getGlobalAngularVelocityFromEulerAnglesZyxDerivatives<scalar_t>(baseOrientation, derivativeEulerAnglesZyx);const auto Adot = pinocchio::dccrba(model, data, qPinocchio, vPinocchio); // 获取动量矩阵A的导数Vector6 centroidalMomentumRate = info.robotMass * getNormalizedCentroidalMomentumRate(pinocchioInterface_, info, input);centroidalMomentumRate.noalias() -= Adot * vPinocchio;centroidalMomentumRate.noalias() -= Aj * jointAccelerations.head(info.actuatedDofNum);const Vector6 qbaseDdot = Ab_inv * centroidalMomentumRate;// Base Acceleration in world framebaseAcceleration.head<3>() = qbaseDdot.head<3>();baseAcceleration.tail<3>() =getGlobalAngularAccelerationFromEulerAnglesZyxDerivatives<scalar_t>(baseOrientation, derivativeEulerAnglesZyx, qbaseDdot.tail<3>());
}

3.2 computeCentroidalStateFromRbdModel 将刚体模型rbdState转成质心模型state

输入rbdState:

  • 基座的位置、欧拉角
  • 关节角度
  • 基座的线速度、角速度
  • 关节速度
    输出state:
  • 归一化动量
  • 广义坐标(基座位置和关节角度)
/*******将刚体模型转换为质心模型****************/
vector_t CentroidalModelRbdConversions::computeCentroidalStateFromRbdModel(const vector_t& rbdState) {const auto& model = pinocchioInterface_.getModel();auto& data = pinocchioInterface_.getData();const auto& info = mapping_.getCentroidalModelInfo();vector_t qPinocchio(info.generalizedCoordinatesNum);qPinocchio.head<3>() = rbdState.segment<3>(3); //基座位置qPinocchio.segment<3>(3) = rbdState.head<3>(); //基座姿态qPinocchio.tail(info.actuatedDofNum) = rbdState.segment(6, info.actuatedDofNum);//关节角度vector_t vPinocchio(info.generalizedCoordinatesNum);vPinocchio.head<3>() = rbdState.segment<3>(info.generalizedCoordinatesNum + 3); //基座线速度vPinocchio.segment<3>(3) = getEulerAnglesZyxDerivativesFromGlobalAngularVelocity<scalar_t>(qPinocchio.segment<3>(3), rbdState.segment<3>(info.generalizedCoordinatesNum)); //基座欧拉角导数//关节速度vPinocchio.tail(info.actuatedDofNum) = rbdState.segment(info.generalizedCoordinatesNum + 6, info.actuatedDofNum);updateCentroidalDynamics(pinocchioInterface_, info, qPinocchio);const auto& A = getCentroidalMomentumMatrix(pinocchioInterface_); //获得动量矩阵vector_t state(info.stateDim);centroidal_model::getNormalizedMomentum(state, info).noalias() = A * vPinocchio / info.robotMass; //得到规划化后的动量centroidal_model::getGeneralizedCoordinates(state, info) = qPinocchio; //状态位置赋值return state;
}


3.3 computeRbdTorqueFromCentroidalModelPD 根据期望计算最终的控制力矩

/***根据期望计算最终控制的力矩*************************************************************************/
vector_t CentroidalModelRbdConversions::computeRbdTorqueFromCentroidalModelPD(const vector_t& desiredState, const vector_t& desiredInput,const vector_t& desiredJointAccelerations,const vector_t& measuredRbdState, const vector_t& pGains,const vector_t& dGains) {// handlesconst auto& info = mapping_.getCentroidalModelInfo();const auto& model = pinocchioInterface_.getModel();auto& data = pinocchioInterface_.getData();// desiredVector6 desiredBasePose, desiredBaseVelocity, desiredBaseAcceleration;//将质心模型的期望状态和输入转换为基座的期望位姿、速度、加速度computeBaseKinematicsFromCentroidalModel(desiredState, desiredInput, desiredJointAccelerations, desiredBasePose, desiredBaseVelocity,desiredBaseAcceleration);vector_t qDesired(info.generalizedCoordinatesNum), vDesired(info.generalizedCoordinatesNum), aDesired(info.generalizedCoordinatesNum);qDesired << desiredBasePose, centroidal_model::getJointAngles(desiredState, info);vDesired << desiredBaseVelocity, centroidal_model::getJointVelocities(desiredInput, info);aDesired << desiredBaseAcceleration, desiredJointAccelerations;//将世界坐标期望力转到末端坐标系的力和力矩pinocchio::container::aligned_vector<pinocchio::Force> fextDesired(model.njoints, pinocchio::Force::Zero());for (size_t i = 0; i < info.numThreeDofContacts; i++) {const auto frameIndex = info.endEffectorFrameIndices[i];const auto jointIndex = model.frames[frameIndex].parent;const Vector3 translationJointFrameToContactFrame = model.frames[frameIndex].placement.translation();const Matrix3 rotationWorldFrameToJointFrame = data.oMi[jointIndex].rotation().transpose();const Vector3 contactForce = rotationWorldFrameToJointFrame * centroidal_model::getContactForces(desiredInput, i, info);fextDesired[jointIndex].linear() = contactForce;fextDesired[jointIndex].angular() = translationJointFrameToContactFrame.cross(contactForce);}for (size_t i = info.numThreeDofContacts; i < info.numThreeDofContacts + info.numSixDofContacts; i++) {const auto frameIndex = info.endEffectorFrameIndices[i];const auto jointIndex = model.frames[frameIndex].parent;const Vector3 translationJointFrameToContactFrame = model.frames[frameIndex].placement.translation();const Matrix3 rotationWorldFrameToJointFrame = data.oMi[jointIndex].rotation().transpose();const Vector3 contactForce = rotationWorldFrameToJointFrame * centroidal_model::getContactForces(desiredInput, i, info);const Vector3 contactTorque = rotationWorldFrameToJointFrame * centroidal_model::getContactTorques(desiredInput, i, info);fextDesired[jointIndex].linear() = contactForce;fextDesired[jointIndex].angular() = translationJointFrameToContactFrame.cross(contactForce) + contactTorque;}// measuredvector_t qMeasured(info.generalizedCoordinatesNum), vMeasured(info.generalizedCoordinatesNum);qMeasured.head<3>() = measuredRbdState.segment<3>(3);qMeasured.segment<3>(3) = measuredRbdState.head<3>();qMeasured.tail(info.actuatedDofNum) = measuredRbdState.segment(6, info.actuatedDofNum);vMeasured.head<3>() = measuredRbdState.segment<3>(info.generalizedCoordinatesNum + 3);vMeasured.segment<3>(3) = getEulerAnglesZyxDerivativesFromGlobalAngularVelocity<scalar_t>(qMeasured.segment<3>(3), measuredRbdState.segment<3>(info.generalizedCoordinatesNum));vMeasured.tail(info.actuatedDofNum) = measuredRbdState.segment(info.generalizedCoordinatesNum + 6, info.actuatedDofNum);// PD feedback augmentationconst vector_t pdFeedback = pGains.cwiseProduct(qDesired - qMeasured) + dGains.cwiseProduct(vDesired - vMeasured);// feedforward plus PD on acceleration levelconst vector_t aAugmented = aDesired + pdFeedback;return pinocchio::rnea(model, data, qDesired, vDesired, aAugmented, fextDesired);
}
  1. 将质心模型的期望状态和输入转换为基座的期望位姿、速度、加速度
  2. 将世界坐标期望力转到末端坐标系的力和力矩
  3. PD控制器补偿到关节加速度
  4. 运动动力学公式计算各关节的控制力矩

4 PinocchioCentroidalDynamics.cpp

4.1 获取质心动力学的f值:

vector_t PinocchioCentroidalDynamics::getValue(scalar_t time, const vector_t& state, const vector_t& input) {const auto& interface = *pinocchioInterfacePtr_;const auto& info = mapping_.getCentroidalModelInfo();assert(info.stateDim == state.rows());vector_t f(info.stateDim);f << getNormalizedCentroidalMomentumRate(interface, info, input), mapping_.getPinocchioJointVelocity(state, input);return f;
}

4.2 computeNormalizedCentroidalMomentumRateGradients 计算质心动量导数对状态和输入的偏导


/*******计算质心动量导数对状态和输入的偏导**********************************************************************/
void PinocchioCentroidalDynamics::computeNormalizedCentroidalMomentumRateGradients(const vector_t& state, const vector_t& input) {const auto& interface = *pinocchioInterfacePtr_;const auto& info = mapping_.getCentroidalModelInfo();assert(info.stateDim == state.rows());assert(info.inputDim == input.rows());// compute partial derivatives of the center of robotMass acceleration and normalized angular momentumnormalizedLinearMomentumRateDerivativeQ_.setZero(3, info.generalizedCoordinatesNum); //线动量率对状态的偏导normalizedAngularMomentumRateDerivativeQ_.setZero(3, info.generalizedCoordinatesNum);//角动量率对状态的偏导normalizedLinearMomentumRateDerivativeInput_.setZero(3, info.inputDim); //线动量率对输入的偏导normalizedAngularMomentumRateDerivativeInput_.setZero(3, info.inputDim);//角动量率对输入的偏导Matrix3 f_hat, p_hat;for (size_t i = 0; i < info.numThreeDofContacts; i++) {const Vector3 contactForceInWorldFrame = centroidal_model::getContactForces(input, i, info);f_hat = skewSymmetricMatrix(contactForceInWorldFrame) / info.robotMass;const auto J = getTranslationalJacobianComToContactPointInWorldFrame(interface, info, i);normalizedAngularMomentumRateDerivativeQ_.noalias() -= f_hat * J;normalizedLinearMomentumRateDerivativeInput_.block<3, 3>(0, 3 * i).diagonal().array() = 1.0 / info.robotMass;p_hat = skewSymmetricMatrix(getPositionComToContactPointInWorldFrame(interface, info, i)) / info.robotMass;normalizedAngularMomentumRateDerivativeInput_.block<3, 3>(0, 3 * i) = p_hat;}for (size_t i = info.numThreeDofContacts; i < info.numThreeDofContacts + info.numSixDofContacts; i++) {const size_t inputIdx = 3 * info.numThreeDofContacts + 6 * (i - info.numThreeDofContacts);const Vector3 contactForceInWorldFrame = centroidal_model::getContactForces(input, i, info);f_hat = skewSymmetricMatrix(contactForceInWorldFrame) / info.robotMass;const auto J = getTranslationalJacobianComToContactPointInWorldFrame(interface, info, i);normalizedAngularMomentumRateDerivativeQ_.noalias() -= f_hat * J;normalizedLinearMomentumRateDerivativeInput_.block<3, 3>(0, inputIdx).diagonal().array() = 1.0 / info.robotMass;p_hat = skewSymmetricMatrix(getPositionComToContactPointInWorldFrame(interface, info, i)) / info.robotMass;normalizedAngularMomentumRateDerivativeInput_.block<3, 3>(0, 3 * inputIdx) = p_hat;normalizedAngularMomentumRateDerivativeInput_.block<3, 3>(0, 3 * inputIdx + 3).diagonal().array() = 1.0 / info.robotMass;}
}

4.3 getLinearApproximation 线性化近似

/****线性近似,求df/dx,df/du*******************************************************************************/
VectorFunctionLinearApproximation PinocchioCentroidalDynamics::getLinearApproximation(scalar_t time, const vector_t& state,const vector_t& input) {const auto& info = mapping_.getCentroidalModelInfo();assert(info.stateDim == state.rows());assert(info.inputDim == input.rows());auto dynamics = ocs2::VectorFunctionLinearApproximation::Zero(info.stateDim, info.stateDim, info.inputDim);dynamics.f = getValue(time, state, input); // Partial derivatives of the normalized momentum ratescomputeNormalizedCentroidalMomentumRateGradients(state, input);matrix_t dfdq = matrix_t::Zero(info.stateDim, info.generalizedCoordinatesNum);  //对状态求偏导matrix_t dfdv = matrix_t::Zero(info.stateDim, info.generalizedCoordinatesNum);  //对输入求偏导//先将动量一阶导对状态的偏导赋值dfdq.topRows<6>() << normalizedLinearMomentumRateDerivativeQ_, normalizedAngularMomentumRateDerivativeQ_;dfdv.bottomRows(info.generalizedCoordinatesNum).setIdentity();//计算关节角速度和浮动基座速度对状态和输入的偏导std::tie(dynamics.dfdx, dynamics.dfdu) = mapping_.getOcs2Jacobian(state, dfdq, dfdv);// Add partial derivative of f with respect to u since part of f depends explicitly on the inputs (contact forces + torques)//将动量一阶导对输入的偏导加入矩阵中dynamics.dfdu.topRows<3>() += normalizedLinearMomentumRateDerivativeInput_;dynamics.dfdu.middleRows(3, 3) += normalizedAngularMomentumRateDerivativeInput_;return dynamics;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/855484.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

密码学-古典密码

密码学-古典密码 前言 古典密码学(Classic cryptography)和现代密码学(Modern cryptography)的主要差别在于计算机的使用,一般来说,古典密码学是基于字符的,而现代密码学是基于二进制位的。 代换 代换密码是将明文中的字符替代成其他字符,即替代转换,若整个加密过程中…

【笔记】组合数学初步

一些初等的组合数学知识二项式系数 定义: 我们在高中时常见的二项式系数的形式是 \[C_{n}^{k} = \frac{n!}{k!(n-k)!} \]但下文将采用如下的定义: \[\binom{n}{k} = \begin{cases}\dfrac{n^{\underline{k}}}{k!} & k \ge 0\\\\0 & k < 0\end{cases} \]注意这里对 …

翻转字符串翻转单词

一、翻转字符串问题描述 请实现⼀个算法,在不使⽤额外数据结构和储存空间的情况下,翻转⼀个给定的字符串(可以使⽤单个过程变量)。 解题思路 由于不允许使用额外的数据接口和存储空间,所以我们将⼀个字符串以中间字符为轴,前后翻转,也就是将str[len]赋值给str[0],将str[0…

拒绝 Helm? 如何在 K8s 上部署 KRaft 模式 Kafka 集群?

首发:运维有术 今天分享的主题是:不使用 Helm、Operator,如何在 K8s 集群上手工部署一个开启 SASL 认证的 KRaft 模式的 Kafka 集群? 本文,我将为您提供一份全面的实战指南,逐步引导您完成以下关键任务:配置 Kafka Secret:管理用户密码和集群 ID 配置 Kafka Service:使…

Vulnhub 靶场 Jetty: 1

前期准备 靶机地址:https://www.vulnhub.com/entry/jetty-1,621/ Description Back to the Top The company Aquarium Life S.L. has contacted you to perform a pentest against one of their machines. They suspect that one of their employees has been committing frau…

人车防碰撞识别智慧矿山一体机矿山监控系统中的平台一体机和解码器如何选型?

在构建高效、可靠的视频监控系统时,选择合适的平台一体机和解码器是至关重要的一步。这不仅关系到监控系统的稳定性和可靠性,还直接影响到监控画面的清晰度和系统的扩展性。以下是在选择过程中需要考虑的关键因素,以确保您的监控系统能够满足特定场景的需求,并在未来几年内…

2024年项目管理软件对比:14款高效工具帮你提升工作效率

在快节奏的现代社会,项目管理的重要性日益凸显。为了提高工作效率,各类项目管理软件应运而生。本文将为您介绍14款高效的项目管理工具,包括禅道、Trello、Jira、Asana、Teambition、Wrike、Monday.com、ClickUp、ProjectManager、Basecamp、Zoho Projects、Smartsheet、Liqu…

2024年项目管理软件对比:14款高效工具帮你提升工作效

在快节奏的现代社会,项目管理的重要性日益凸显。为了提高工作效率,各类项目管理软件应运而生。本文将为您介绍14款高效的项目管理工具,包括禅道、Trello、Jira、Asana、Teambition、Wrike、Monday.com、ClickUp、ProjectManager、Basecamp、Zoho Projects、Smartsheet、Liqu…

vb编译环境运行没问题,生成exe运行时报错,错误48加载dll错误,右键以管理员身份运行可以但麻烦,其解决办法如下。

解决办法(推荐): 打开vb后,弹出新建工程标准exe,要点打开。 然后再打开已建的工程,这样生成的exe可以直接双击运行,就不会报错了。2、如需重装vb,要记得“数据访问”点“更改选项”去掉ADO和RDS前面的勾选,不然会一直停在更新状态。 1.打开安装包点击SETUP.EXE(如果会…

Java项目实战之Java小游戏-俄罗斯方块设计与实现(附项目源代码地址)

该项目gitee地址:https://gitee.com/lsy_loren/loren-tetris.git一、游戏概述 本游戏是一款经典的俄罗斯方块游戏,使用Java语言开发,具有图形用户界面(GUI)。玩家通过操作方块的移动、旋转和下落,使其填满一行或多行来消除得分,并随着得分的增加提升等级。游戏还具备暂停…

charles中map local改写接口返回参数

先找到接口-》右键-》save response -》存入桌面然后文件的返回参数 右键-》map local 即可修改返回结果