double InverseKinematicJacobian::iterationStepGravitation( KinematicTree const& tree , std::map<MotorID, double>& torques , Task const& task ) const { arma::mat jacobianRaw; arma::mat jacobian = task.getJacobianForTask(tree, jacobianRaw, false); arma::colvec antiGravVec({0., 0., 9.86}); arma::colvec torquesRaw = jacobian.t() * antiGravVec; std::map<NodeID, KinematicNode*> const& nodes = tree.getNodes(); for (std::pair<NodeID, KinematicNode*> const& node : nodes) { kinematics::Int2MotorMap const& int2MotorMap = node.second->getInt2MotorMap(); MotorValuesMap newValues; for (kinematics::Int2Motor const& i2m : int2MotorMap) { torques[i2m.second] = torquesRaw(i2m.first); } } return arma::norm(torquesRaw, 2); }
void KinematicEngine::fillTreeWithValues(KinematicTree &tree, kinematics::MotorValuesMap values, kinematics::MotorValuesMap speeds, bool addNoise) { std::uniform_real_distribution<double> distribution(-m_valueNoise, m_valueNoise); for (std::pair<const MotorID, double>& value : values) { double noise = 0.; if (addNoise) { noise = distribution(generator); } value.second += noise; } for (std::pair<const kinematics::NodeID, KinematicNode*> nodeP : tree.getNodes()) { KinematicNode * node = nodeP.second; kinematics::MotorIDs const& motors = node->getMotors(); kinematics::MotorValuesMap valuesForNode; kinematics::MotorValuesMap valueDerivativesForNode; for (MotorID const& id : motors) { if (values.find(id) != values.end()) { // this motor is accessible for inverse kinematics valuesForNode[id] = values.at(id); } if (speeds.find(id) != speeds.end()) { valueDerivativesForNode[id] = speeds.at(id); } } node->setValues(valuesForNode); node->setValueDerivatives(valueDerivativesForNode); } }
double InverseKinematicJacobian::iterationStep( KinematicTree const& tree , MotorValuesMap& o_values , TasksContainer const& alltasks , Constraints const& constraints , const TaskDefaultPosition* idleTask ) const { std::cout << "\x1B[2J\x1B[H"; double totalError = 0; const uint motorCnt = tree.getMotorCnt(); arma::colvec motorValuesVec = arma::zeros(motorCnt); std::map<NodeID, KinematicNode*> const& nodes = tree.getNodes(); for (std::pair<NodeID, KinematicNode*> const& node : nodes) { if (node.second->isServo()) { kinematics::Motor2IntMap const& motor2Int = node.second->getMotor2IntMap(); MotorValuesMap const& values = node.second->getValues(); for (std::pair<MotorID, double> const& value : values) { motorValuesVec(motor2Int.at(value.first)) = value.second; } } } arma::colvec summedJointAngleDiffs = arma::zeros(motorCnt); arma::mat nullspaceEyeMat = arma::eye(motorCnt, motorCnt); arma::mat nullspaceMat = nullspaceEyeMat; arma::mat bigJacobian; for (std::pair<uint, std::vector<const Task*>> const& group : alltasks) { std::vector<const Task*> const& tasks = group.second; if (tasks.size() > 0) { arma::mat jacobianRAW; const arma::mat jacobian = getJacobianForTasks(tree, tasks, jacobianRAW, false); const arma::colvec errorVec = getErrorForTasks(tree, tasks); const arma::mat pseudoInverseJacobian = buildPseudoInverse(jacobian, m_speedEpsilon); const arma::colvec jointDiffs = pseudoInverseJacobian * errorVec; const arma::colvec jointDiffsDecorr = nullspaceMat * jointDiffs; const arma::colvec preliminaryJointAngles = motorValuesVec + summedJointAngleDiffs + jointDiffsDecorr; arma::colvec jointDiffConstraintError = arma::zeros(motorCnt); arma::colvec correctedJointAngleDiffs = jointDiffsDecorr; for (const Constraint* constraint : constraints) { jointDiffConstraintError += constraint->getAngleErrorForConstraint(tree, preliminaryJointAngles); } // correct the constraint error for (uint i(0); i < motorCnt; ++i) { const double factor = nullspaceMat(i, i); if (factor > m_nullspaceEpsilon) { jointDiffConstraintError(i) = jointDiffConstraintError(i) / factor; } else { jointDiffConstraintError(i) = 0; } } correctedJointAngleDiffs += nullspaceMat * jointDiffConstraintError; summedJointAngleDiffs += correctedJointAngleDiffs; bigJacobian = arma::join_cols(bigJacobian, jacobianRAW); nullspaceMat = nullspaceEyeMat - buildPseudoInverse(bigJacobian, m_nullspaceEpsilon) * bigJacobian; totalError += arma::dot(errorVec, errorVec); // std::cout << "level " << group.first << std::endl; // std::cout.precision(7); // std::cout << std::fixed << std::setw(12); // bigJacobian.raw_print(std::cout, "bigJacobian = ["); printf("]\n"); // jacobian.raw_print(std::cout, std::string("jacobian") + std::to_string(group.first) + " = ["); printf("]\n"); // bigJacobian.raw_print(std::cout, std::string("bigJacobian") + std::to_string(group.first) + " = ["); printf("]\n"); // jacobianDOF.raw_print(std::cout, "jacobianDOF = ["); printf("]\n"); // arma::mat(jacobian * dofMat).raw_print(std::cout, "jacobianDOF2 = ["); printf("]\n"); // jointDiffs.t().raw_print(std::cout, std::string("jointDiffs") + std::to_string(group.first) + " = ["); printf("]\n"); // jointDiffsDecorr.t().raw_print(std::cout, std::string("jointDiffsDecorr") + std::to_string(group.first) + " = ["); printf("]\n"); // summedJointAngleDiffs.t().raw_print(std::cout, "summedJointAngleDiffs = ["); printf("]\n"); // jointDiffConstraintError.t().raw_print(std::cout, "jointDiffConstraintError = ["); printf("]\n"); // correctedJointAngleDiffs.t().raw_print(std::cout, "correctedJointAngleDiffs = ["); printf("]\n"); // errorVec.t().raw_print(std::cout, std::string("errorVec") + std::to_string(group.first) + " = ["); printf("]'\n"); // nullspaceMat.raw_print(std::cout, "nullspaceMat = ["); printf("]\n"); // std::cout << arma::norm(errorVec, 2) << std::endl; // printf("\n"); } } if (nullptr != idleTask) { arma::mat helper = arma::mat(nullspaceEyeMat - nullspaceMat); arma::colvec errorVec = idleTask->getErrors(tree); arma::colvec angleDiffVec = ((nullspaceEyeMat - nullspaceMat) * errorVec); summedJointAngleDiffs += angleDiffVec; } for (uint32_t i = 0; i < summedJointAngleDiffs.n_rows; ++i) { summedJointAngleDiffs(i) = utils::limited(summedJointAngleDiffs(i), -m_maxValueChange, m_maxValueChange); } motorValuesVec += summedJointAngleDiffs; for (std::pair<NodeID, KinematicNode*> const& node : nodes) { if (node.second->isServo()) { kinematics::Int2MotorMap const& int2MotorMap = node.second->getInt2MotorMap(); kinematics::MotorIDs const& motors = node.second->getMotors(); MotorValuesMap newValues; for (kinematics::Int2Motor const& i2m : int2MotorMap) { newValues[i2m.second] = motorValuesVec(i2m.first); } /* clip values */ newValues = node.second->clipValues(newValues); /* export */ for (MotorID const& motor : motors) { o_values[motor] = newValues[motor]; } } } return totalError; }
double InverseKinematicJacobian::calculateSpeeds( KinematicTree const& tree , MotorValuesMap& o_values , TasksContainer const& tasks , Constraints const& constraints , const TaskDefaultPosition* idleTask ) const { double totalError = 0; uint motorCnt = tree.getMotorCnt(); arma::colvec motorSpeedsVec = arma::zeros(motorCnt); arma::colvec motorValuesVec = arma::zeros(motorCnt); std::map<NodeID, KinematicNode*> const& nodes = tree.getNodes(); for (std::pair<NodeID, KinematicNode*> const& node : nodes) { if (node.second->isServo()) { kinematics::Motor2IntMap const& motor2Int = node.second->getMotor2IntMap(); MotorValuesMap const& values = node.second->getValues(); MotorValuesMap const& valueDerivatives = node.second->getValueDerivatives(); for (std::pair<MotorID, double> const& value : values) { motorValuesVec(motor2Int.at(value.first)) = value.second; } for (std::pair<MotorID, double> const& value : valueDerivatives) { motorSpeedsVec(motor2Int.at(value.first)) = value.second; } } } arma::colvec jointDiffConstraintError = arma::zeros(motorCnt); for (const Constraint* constraint : constraints) { jointDiffConstraintError += constraint->getAngleErrorForConstraint(tree, motorValuesVec); } arma::colvec summedJointSpeedDiffs = arma::zeros(motorCnt); arma::mat nullspaceEyeMat = arma::eye(motorCnt, motorCnt); arma::mat nullspaceMat = nullspaceEyeMat - jointDiffConstraintError * jointDiffConstraintError.t(); arma::mat bigJacobian; for (std::pair<uint, std::vector<const Task*>> const& group : tasks) { std::vector<const Task*> const& _tasks = group.second; if (_tasks.size() > 0) { arma::mat jacobianRAW; arma::mat jacobian = getJacobianForTasks(tree, _tasks, jacobianRAW, false); const arma::mat pseudoInverseJacobian = buildPseudoInverse(jacobian, m_speedEpsilon); // how much "error" (mother function) arma::colvec speedTarget = getSpeedTargetForTasks(tree, _tasks); // how fast does the target move arma::colvec speedVec = jacobian * motorSpeedsVec; // the actual error arma::colvec speedError = speedTarget - speedVec; const arma::colvec jointDiffs = nullspaceMat * pseudoInverseJacobian * speedError; summedJointSpeedDiffs += jointDiffs; bigJacobian = arma::join_cols(bigJacobian, jacobianRAW); // nullspaceMat += dofMat * (buildPseudoInverse(jacobianRAW, m_nullspaceEpsilon) * jacobianRAW); nullspaceMat = nullspaceEyeMat - buildPseudoInverse(bigJacobian, m_nullspaceEpsilon) * bigJacobian; totalError += arma::dot(speedError, speedError); // printf("level %d\n", group.first); // std::cout.precision(3); // std::cout << std::fixed << std::setw(7); // jacobian.raw_print(std::cout, "jacobian"); printf("\n"); // jacobianDOF.raw_print(std::cout, "jacobianDOF"); printf("\n"); // pseudoInverseJacobian.raw_print(std::cout, "pseudoInverseJacobianDOF"); printf("\n"); // buildPseudoInverse(jacobian, m_speedEpsilon).raw_print(std::cout, "pseudoInverseJacobian"); printf("\n"); // jointDiffs.t().raw_print(std::cout, "jointDiffs"); printf("\n"); // summedJointSpeedDiffs.t().raw_print(std::cout, "summedJointSpeedDiffs"); printf("\n"); // speedError.t().raw_print(std::cout, "speedError"); printf("\n"); // std::cout << arma::norm(speedError, 2) << std::endl; // printf("\n"); } } if (nullptr != idleTask) { arma::mat helper = arma::mat(nullspaceEyeMat - nullspaceMat); arma::colvec errorVec = idleTask->getErrors(tree); summedJointSpeedDiffs += (helper * errorVec) * idleTask->getSpeed(); } summedJointSpeedDiffs += motorSpeedsVec; for (std::pair<NodeID, KinematicNode*> const& node : nodes) { if (node.second->isServo()) { kinematics::Int2MotorMap const& int2MotorMap = node.second->getInt2MotorMap(); kinematics::MotorIDs const& motors = node.second->getMotors(); MotorValuesMap newValues; for (kinematics::Int2Motor const& i2m : int2MotorMap) { newValues[i2m.second] = summedJointSpeedDiffs(i2m.first); } /* export */ for (MotorID const& motor : motors) { o_values[motor] = newValues[motor]; } } } return totalError; }