SideConfidenceProvider::BallModelSideConfidence SideConfidenceProvider::computeCurrentBallConfidence() { // Some constant parameters const float distanceObserved = lastBallObservation.norm(); const float angleObserved = lastBallObservation.angle(); const float& camZ = theCameraMatrix.translation.z(); const float distanceAsAngleObserved = (pi_2 - std::atan2(camZ,distanceObserved)); // Weighting for original pose float originalWeighting = computeAngleWeighting(angleObserved, theLocalizationTeamBall.position, theRobotPose, standardDeviationBallAngle); originalWeighting *= computeDistanceWeighting(distanceAsAngleObserved, theLocalizationTeamBall.position, theRobotPose, camZ, standardDeviationBallDistance); // Weighting for mirrored pose const Pose2f mirroredPose = Pose2f(pi) + (Pose2f)(theRobotPose); float mirroredWeighting = computeAngleWeighting(angleObserved, theLocalizationTeamBall.position, mirroredPose, standardDeviationBallAngle); mirroredWeighting *= computeDistanceWeighting(distanceAsAngleObserved, theLocalizationTeamBall.position, mirroredPose, camZ, standardDeviationBallDistance); PLOT("module:SideConfidenceProvider:originalWeighting", originalWeighting); PLOT("module:SideConfidenceProvider:mirroredWeighting", mirroredWeighting); // Decide state based on weights if((mirroredWeighting < minWeighting) && (originalWeighting < minWeighting)) return UNKNOWN; if((mirroredWeighting > weightingFactor * originalWeighting) || (originalWeighting > weightingFactor * mirroredWeighting)) return mirroredWeighting > originalWeighting ? MIRROR : OK; return UNKNOWN; }
bool GoalFramePerceptor::calcGoalFrame(const Pose2f& prePose, const float yTranslation, GoalFrame& goalFrame) const { static const float borderToGroundLineDistance = theFieldDimensions.xPosOpponentFieldBorder - theFieldDimensions.xPosOpponentGroundline; const Pose2f prePoseInverse(prePose.inverse()); int positive = 0, negative = 0; for(const Vector2f& p : theFieldBoundary.boundaryOnField) { Vector2f pInField = prePoseInverse * p; if(std::abs(std::abs(pInField.x()) - borderToGroundLineDistance) < allowedFieldBoundaryDivergence) { if(pInField.x() > 0) positive++; else negative++; } } if(neededConvexBoundaryPoints > positive && neededConvexBoundaryPoints > negative) return false; const float sign = (positive < negative) ? -1.f : 1.f; goalFrame = Pose2f(prePose).rotate(-pi_2 + sign * pi_2); goalFrame.translation = goalFrame * Vector2f(0.f, (goalFrame.inverse().translation.y() > 0.f ? 1.f : -1.f)).normalized(yTranslation); return true; }
void AutomaticCameraCalibrator::optimize() { if(optimizer == nullptr) { // since the parameters for the robot pose are correction parameters, // an empty RobotPose is used instead of theRobotPose optimizationParameters = pack(theCameraCalibration, Pose2f()); optimizer = new GaussNewtonOptimizer<numOfParameterTranslations>(functor); successiveConvergations = 0; framesToWait = 0; } else { // only do an iteration after some frames have passed if(framesToWait <= 0) { framesToWait = numOfFramesToWait; const float delta = optimizer->iterate(optimizationParameters, Parameters::Constant(0.0001f)); if(!std::isfinite(delta)) { OUTPUT_TEXT("Restart optimize! An optimization error occured!"); delete optimizer; optimizer = nullptr; state = Accumulate; } OUTPUT_TEXT("AutomaticCameraCalibrator: delta = " << delta); // the camera calibration is refreshed from the current optimizer state Pose2f robotPoseCorrection; unpack(optimizationParameters, nextCameraCalibration, robotPoseCorrection); if(std::abs(delta) < terminationCriterion) ++successiveConvergations; else successiveConvergations = 0; if(successiveConvergations >= minSuccessiveConvergations) { OUTPUT_TEXT("AutomaticCameraCalibrator: converged!"); OUTPUT_TEXT("RobotPoseCorrection: " << robotPoseCorrection.translation.x() * 1000.0f << " " << robotPoseCorrection.translation.y() * 1000.0f << " " << robotPoseCorrection.rotation.toDegrees() << "deg"); currentRobotPose.translation.x() += robotPoseCorrection.translation.x() * 1000.0f; currentRobotPose.translation.y() += robotPoseCorrection.translation.y() * 1000.0f; currentRobotPose.rotation = Angle::normalize(currentRobotPose.rotation + robotPoseCorrection.rotation); abort(); if(setJointOffsets) invert(theCameraCalibration); } } --framesToWait; } }
void FieldFeatureOverviewProvider::update(FieldFeatureOverview& fieldFeatureOverview) { const FieldFeature* fieldFeatures[FieldFeatureOverview::numOfFeatures]; fieldFeatures[FieldFeatureOverview::GoalFeature] = &theGoalFeature; fieldFeatures[FieldFeatureOverview::GoalFrame] = &theGoalFrame; fieldFeatures[FieldFeatureOverview::MidCircle] = &theMidCircle; fieldFeatures[FieldFeatureOverview::MidCorner] = &theMidCorner; fieldFeatures[FieldFeatureOverview::OuterCorner] = &theOuterCorner; fieldFeatures[FieldFeatureOverview::PenaltyArea] = &thePenaltyArea; fieldFeatureOverview.combinedStatus.isValid = false; FOREACH_ENUM((FieldFeatureOverview) Feature, i) if(((fieldFeatureOverview.statuses[i] = Pose2f(*fieldFeatures[i])).isValid = fieldFeatures[i]->isValid) && (fieldFeatureOverview.combinedStatus.isValid = true)) fieldFeatureOverview.combinedStatus.lastSeen = fieldFeatureOverview.statuses[i].lastSeen = theFrameInfo.time; fieldFeatureOverview.statuses[FieldFeatureOverview::OuterCorner].isRightSided = theOuterCorner.isRightCorner; }
void KickEngineData::calcOdometryOffset(KickEngineOutput& output, const RobotModel& theRobotModel) { Pose3f ankleInAnkle; //quickhack to compute support foot, could be worng if the motion is using the right foot as support foot as default //could use theTorsoMatrix.leftSupportFoot, but if the swing foot steps into the ground the odometry jumps if(currentKickRequest.mirror) ankleInAnkle = theRobotModel.limbs[Limbs::ankleRight].inverse() * theRobotModel.limbs[Limbs::ankleLeft]; else ankleInAnkle = theRobotModel.limbs[Limbs::ankleLeft].inverse() * theRobotModel.limbs[Limbs::ankleRight]; Pose2f currentOdometry(ankleInAnkle.translation.x() * 0.5f, ankleInAnkle.translation.y() * 0.5f); output.odometryOffset = currentOdometry - lastOdometry; if(phase == 0) output.odometryOffset += Pose2f(currentParameters.phaseParameters[phaseNumber].odometryOffset.x(), currentParameters.phaseParameters[phaseNumber].odometryOffset.y()); lastOdometry = currentOdometry; }
bool GoalFramePerceptor::searchByTT(GoalFrame& goalFrame) const { std::vector<const IntersectionsPercept::Intersection*> useTIntersections; for(const IntersectionsPercept::Intersection& intersection : theIntersectionsPercept.intersections) if(intersection.type == IntersectionsPercept::Intersection::T) useTIntersections.push_back(&intersection); static const float diffTT = theFieldDimensions.yPosLeftPenaltyArea - theFieldDimensions.yPosLeftGoal; static const float yTTPos = diffTT / 2.f + theFieldDimensions.yPosLeftGoal; for(unsigned i = 0u; i < useTIntersections.size(); i++) for(unsigned j = i + 1u; j < useTIntersections.size(); j++) if(std::abs((useTIntersections[i]->pos - useTIntersections[j]->pos).norm() - diffTT) < tTDistanceThreshold) if(Angle(useTIntersections[i]->dir1.angle()).diffAbs(useTIntersections[j]->dir1.angle()) < allowedTTAngleDivergence) if(calcGoalFrame(Pose2f(Angle(useTIntersections[i]->dir2.angle() + pi_2).normalize(), useTIntersections[i]->pos + 0.5f * (useTIntersections[j]->pos - useTIntersections[i]->pos)), yTTPos, goalFrame)) return true; return false; }
void SpecialActions::update(SpecialActionsOutput& specialActionsOutput) { if(!motionNetData.nodeArray) { specialActionsOutput.angles.fill(0); specialActionsOutput.stiffnessData.stiffnesses.fill(0); return; } float speedFactor = 1.0f; MODIFY("parameters:SpecialActions:speedFactor", speedFactor); if(theMotionSelection.specialActionMode != MotionSelection::deactive) { specialActionsOutput.isLeavingPossible = true; if(dataRepetitionCounter <= 0) { if(!wasActive) { //entered from external motion currentNode = 0; for(int i = 0; i < Joints::numOfJoints; ++i) lastRequest.angles[i] = theJointAngles.angles[i]; lastSpecialAction = SpecialActionRequest::numOfSpecialActionIDs; } // this is need when a special actions gets executed directly after another without // switching to a different motion for interpolating the stiffness if(wasEndOfSpecialAction) { specialActionsOutput.stiffnessData.resetToDefault(); if(!mirror) lastStiffnessRequest = currentStiffnessRequest; else lastStiffnessRequest.mirror(currentStiffnessRequest); currentStiffnessRequest.resetToDefault(); } wasEndOfSpecialAction = false; // search next data, leave on transition to external motion if(!getNextData(theMotionSelection.specialActionRequest, specialActionsOutput)) { wasActive = true; wasEndOfSpecialAction = true; specialActionsOutput.odometryOffset = Pose2f(); return; } } else { dataRepetitionCounter -= int(theFrameInfo.cycleTime * 1000 * speedFactor); stiffnessInterpolationCounter -= int(theFrameInfo.cycleTime * 1000 * speedFactor); } //set current joint values calculateJointRequest(specialActionsOutput); //odometry update if(currentInfo.type == SpecialActionInfo::homogeneous || currentInfo.type == SpecialActionInfo::once) if(mirror) specialActionsOutput.odometryOffset = Pose2f(-currentInfo.odometryOffset.rotation, currentInfo.odometryOffset.translation.x(), -currentInfo.odometryOffset.translation.y()); else specialActionsOutput.odometryOffset = currentInfo.odometryOffset; else specialActionsOutput.odometryOffset = Pose2f(); if(currentInfo.type == SpecialActionInfo::once) currentInfo.type = SpecialActionInfo::none; //store value if current data line finished if(dataRepetitionCounter <= 0) { if(!mirror) lastRequest = currentRequest; else lastRequest.mirror(currentRequest); } specialActionsOutput.isLeavingPossible = false; if(deShakeMode) for(int i = Joints::lShoulderPitch; i <= Joints::rElbowRoll; ++i) if(randomFloat() < 0.25) specialActionsOutput.angles[i] = JointAngles::off; } wasActive = theMotionSelection.specialActionMode != MotionSelection::deactive; }
void MotionCombinator::update(JointRequest& jointRequest) { specialActionOdometry += theSpecialActionsOutput.odometryOffset; copy(theLegJointRequest, jointRequest, theStiffnessSettings, Joints::headYaw, Joints::headPitch); copy(theArmJointRequest, jointRequest, theStiffnessSettings, Joints::firstArmJoint, Joints::rHand); copy(theLegJointRequest, jointRequest, theStiffnessSettings, Joints::firstLegJoint, Joints::rAnkleRoll); ASSERT(jointRequest.isValid()); // Find fully active motion and set MotionInfo if(theLegMotionSelection.ratios[theLegMotionSelection.targetMotion] == 1.f) { // default values motionInfo.motion = theLegMotionSelection.targetMotion; motionInfo.isMotionStable = true; motionInfo.upcomingOdometryOffset = Pose2f(); Pose2f odometryOffset; switch(theLegMotionSelection.targetMotion) { case MotionRequest::walk: odometryOffset = theWalkingEngineOutput.odometryOffset; motionInfo.walkRequest = theWalkingEngineOutput.executedWalk; motionInfo.upcomingOdometryOffset = theWalkingEngineOutput.upcomingOdometryOffset; break; case MotionRequest::kick: odometryOffset = theKickEngineOutput.odometryOffset; motionInfo.kickRequest = theKickEngineOutput.executedKickRequest; motionInfo.isMotionStable = theKickEngineOutput.isStable; break; case MotionRequest::specialAction: odometryOffset = specialActionOdometry; specialActionOdometry = Pose2f(); motionInfo.specialActionRequest = theSpecialActionsOutput.executedSpecialAction; motionInfo.isMotionStable = theSpecialActionsOutput.isMotionStable; break; case MotionRequest::getUp: motionInfo.isMotionStable = false; odometryOffset = theGetUpEngineOutput.odometryOffset; break; case MotionRequest::stand: default: break; } if(theRobotInfo.hasFeature(RobotInfo::zGyro) && (theFallDownState.state == FallDownState::upright || theLegMotionSelection.targetMotion == MotionRequest::getUp)) { Vector3f rotatedGyros = theInertialData.orientation * theInertialData.gyro.cast<float>(); odometryOffset.rotation = rotatedGyros.z() * theFrameInfo.cycleTime; } odometryData += odometryOffset; } if(emergencyOffEnabled && motionInfo.motion != MotionRequest::getUp) { if(theFallDownState.state == FallDownState::falling && motionInfo.motion != MotionRequest::specialAction) { safeFall(jointRequest); centerHead(jointRequest); currentRecoveryTime = 0; ASSERT(jointRequest.isValid()); } else if(theFallDownState.state == FallDownState::onGround && motionInfo.motion != MotionRequest::specialAction) { centerHead(jointRequest); } else { if(theFallDownState.state == FallDownState::upright) { headYawInSafePosition = false; headPitchInSafePosition = false; } if(currentRecoveryTime < recoveryTime) { currentRecoveryTime += 1; float ratio = (1.f / float(recoveryTime)) * currentRecoveryTime; for(int i = 0; i < Joints::numOfJoints; i++) { jointRequest.stiffnessData.stiffnesses[i] = 30 + int(ratio * float(jointRequest.stiffnessData.stiffnesses[i] - 30)); } } } } if(debugArms) debugReleaseArms(jointRequest); eraseStiffness(jointRequest); float sum = 0; int count = 0; for(int i = Joints::lHipYawPitch; i < Joints::numOfJoints; i++) { if(jointRequest.angles[i] != JointAngles::off && jointRequest.angles[i] != JointAngles::ignore && lastJointRequest.angles[i] != JointAngles::off && lastJointRequest.angles[i] != JointAngles::ignore) { sum += std::abs(jointRequest.angles[i] - lastJointRequest.angles[i]); count++; } } PLOT("module:MotionCombinator:deviations:JointRequest:legsOnly", sum / count); for(int i = 0; i < Joints::lHipYawPitch; i++) { if(jointRequest.angles[i] != JointAngles::off && jointRequest.angles[i] != JointAngles::ignore && lastJointRequest.angles[i] != JointAngles::off && lastJointRequest.angles[i] != JointAngles::ignore) { sum += std::abs(jointRequest.angles[i] - lastJointRequest.angles[i]); count++; } } PLOT("module:MotionCombinator:deviations:JointRequest:all", sum / count); sum = 0; count = 0; for(int i = Joints::lHipYawPitch; i < Joints::numOfJoints; i++) { if(lastJointRequest.angles[i] != JointAngles::off && lastJointRequest.angles[i] != JointAngles::ignore) { sum += std::abs(lastJointRequest.angles[i] - theJointAngles.angles[i]); count++; } } PLOT("module:MotionCombinator:differenceToJointData:legsOnly", sum / count); for(int i = 0; i < Joints::lHipYawPitch; i++) { if(lastJointRequest.angles[i] != JointAngles::off && lastJointRequest.angles[i] != JointAngles::ignore) { sum += std::abs(lastJointRequest.angles[i] - theJointAngles.angles[i]); count++; } } lastJointRequest = jointRequest; PLOT("module:MotionCombinator:differenceToJointData:all", sum / count); #ifndef NDEBUG if(!jointRequest.isValid()) { { std::string logDir = ""; #ifdef TARGET_ROBOT logDir = "../logs/"; #endif OutMapFile stream(logDir + "jointRequest.log"); stream << jointRequest; OutMapFile stream2(logDir + "motionSelection.log"); stream2 << theLegMotionSelection; } ASSERT(false); } #endif }