SideConfidenceProvider::BallModelSideConfidence SideConfidenceProvider::computeCurrentBallConfidence()
{
  // Some constant parameters
  const float distanceObserved = lastBallObservation.abs();
  const float angleObserved = lastBallObservation.angle();
  const float& camZ = theCameraMatrix.translation.z;
  const float distanceAsAngleObserved = (pi_2 - atan2(camZ,distanceObserved));

  // Weighting for original pose
  float originalWeighting = computeAngleWeighting(angleObserved, theCombinedWorldModel.ballStateOthers.position, theRobotPose, 
    parameters.standardDeviationBallAngle);
  originalWeighting *= computeDistanceWeighting(distanceAsAngleObserved, theCombinedWorldModel.ballStateOthers.position, theRobotPose,
    camZ, parameters.standardDeviationBallDistance);

  // Weighting for mirrored pose
  const Pose2D  mirroredPose = Pose2D(pi) + (Pose2D)(theRobotPose);
  float mirroredWeighting = computeAngleWeighting(angleObserved, theCombinedWorldModel.ballStateOthers.position, mirroredPose, 
    parameters.standardDeviationBallAngle);
  mirroredWeighting *= computeDistanceWeighting(distanceAsAngleObserved, theCombinedWorldModel.ballStateOthers.position, mirroredPose,
    camZ, parameters.standardDeviationBallDistance);

  // Decide state based on weights
  if((mirroredWeighting > parameters.weightingFactor * originalWeighting) || (originalWeighting > parameters.weightingFactor * mirroredWeighting))
    return mirroredWeighting > originalWeighting ? MIRROR : OK;
  return UNKNOWN;
}
Esempio n. 2
0
Pose2D Pose2D::random(const Range<>& x,
                      const Range<>& y,
                      const Range<>& angle)
{
  // angle should even work in wrap around case!
  return Pose2D(float(::randomFloat() * (angle.max - angle.min) + angle.min),
                Vector2<>(float(::randomFloat() * (x.max - x.min) + x.min),
                          float(::randomFloat() * (y.max - y.min) + y.min)));
}
Esempio n. 3
0
void SelfLocator::motionUpdate(bool noise)
{
  Pose2D odometryOffset = bb->theOdometryData - lastOdometry;

  const float transNoise = noise ? parameter->translationNoise : 0;
  const float rotNoise = noise ? parameter->rotationNoise : 0;
  const int transX = (int) odometryOffset.translation.x;
  const int transY = (int) odometryOffset.translation.y;
  const float dist = odometryOffset.translation.abs();
  const float angle = abs(odometryOffset.rotation);

  lastOdometry += Pose2D(odometryOffset.rotation, (float) transX, (float) transY);

  // precalculate rotational error that has to be adapted to all samples
  const float rotError = max(rotNoise,
                             max(dist * parameter->movedDistWeight,
                                 angle * parameter->movedAngleWeight));

  // precalculate translational error that has to be adapted to all samples
  const int transXError = (int) max(transNoise,
                                    (float) max(abs(transX * parameter->majorDirTransWeight),
                                        abs(transY * parameter->minorDirTransWeight)));
  const int transYError = (int) max(transNoise,
                                    (float) max(abs(transY * parameter->majorDirTransWeight),
                                        abs(transX * parameter->minorDirTransWeight)));
  for(int i = 0; i < samples->size(); i++)
  {
    Sample& s(samples->at(i));

    // the translational error vector
    const Vector2<int> transOffset((((transX - transXError) << 10) + (transXError << 1) * ((rand() & 0x3ff) + 1) + 512) >> 10,
                                   (((transY - transYError) << 10) + (transYError << 1) * ((rand() & 0x3ff) + 1) + 512) >> 10);

    // update the sample
    s.translation = Vector2<int>(((s.translation.x << 10) + transOffset.x * s.rotation.x - transOffset.y * s.rotation.y + 512) >> 10,
                                 ((s.translation.y << 10) + transOffset.x * s.rotation.y + transOffset.y * s.rotation.x + 512) >> 10);
    s.angle += odometryOffset.rotation + (randomFloat() * 2 - 1) * rotError;
    s.angle = normalize(s.angle);
    s.rotation = Vector2<int>(int(cos((float)s.angle) * 1024), int(sin((float)s.angle) * 1024));

    // clip to field boundary
    Vector2<> translationAsDouble((float) s.translation.x, (float) s.translation.y);
    bb->theFieldDimensions.clipToCarpet(translationAsDouble);
    s.translation.x = static_cast<int>(translationAsDouble.x);
    s.translation.y = static_cast<int>(translationAsDouble.y);
  }
}
Esempio n. 4
0
void SelfLocator::preExecution(RobotPose& robotPose)
{
  sampleTemplateGenerator.bufferNewPerceptions();

  // Reset all weightings to 1.0f
  for(int i = 0; i < samples->size(); ++i)
    samples->at(i).weighting = 1.0f;

  //DEBUG_RESPONSE("module:SelfLocator:createFieldModel", fieldModel.create(););

  // Table for checking point / line validity:
  //DEBUG_RESPONSE("module:SelfLocator:PerceptValidityChecker:saveGoalNetTable", perceptValidityChecker->saveGoalNetTable(););
  //DEBUG_RESPONSE("module:SelfLocator:PerceptValidityChecker:recomputeGoalNetTable", perceptValidityChecker->computeGoalNetTable(););

  // change module for pose calculation or use debug request to reload the pose calculator
  PoseCalculatorType newPoseCalculatorType(poseCalculatorType);
  //MODIFY_ENUM("module:SelfLocator:poseCalculatorType", newPoseCalculatorType);

  bool reloadPoseCalculator = (newPoseCalculatorType != poseCalculatorType);
  //DEBUG_RESPONSE("module:SelfLocator:reloadPoseCalculator", reloadPoseCalculator = true;);

  if(reloadPoseCalculator)
  {
    delete poseCalculator;
    switch(newPoseCalculatorType)
    {
    case POSE_CALCULATOR_2D_BINNING:
      poseCalculator = new PoseCalculator2DBinning< Sample, SampleSet<Sample>, 10 >
      (*samples, bb->theFieldDimensions);
      break;
    case POSE_CALCULATOR_PARTICLE_HISTORY:
      poseCalculator = new PoseCalculatorParticleHistory< Sample, SampleSet<Sample> >(*samples);
      poseCalculator->init();
      break;
    case POSE_CALCULATOR_BEST_PARTICLE:
      poseCalculator = new PoseCalculatorBestParticle< Sample, SampleSet<Sample> >(*samples);
      break;
    case POSE_CALCULATOR_OVERALL_AVERAGE:
      poseCalculator = new PoseCalculatorOverallAverage< Sample, SampleSet<Sample> >(*samples);
      break;
    case POSE_CALCULATOR_K_MEANS_CLUSTERING:
      poseCalculator = new PoseCalculatorKMeansClustering< Sample, SampleSet<Sample>, 5, 1000 >
      (*samples, bb->theFieldDimensions);
      break;
    default:
      ASSERT(false);
    }
    poseCalculatorType = newPoseCalculatorType;
  }

  // if the considerGameState flag is set, reset samples when necessary
  if(parameter->considerGameState)
  {
    // penalty shoot: if game state switched to playing reset samples to start pos
    if(bb->theGameInfo.secondaryState == STATE2_PENALTYSHOOT)
    {
      if((gameInfoGameStateLastFrame == STATE_SET && bb->theGameInfo.state == STATE_PLAYING) ||
         (gameInfoPenaltyLastFrame != PENALTY_NONE && bb->theRobotInfo.penalty == PENALTY_NONE))
      {
        vector<Pose2D> poses;
        vector<Pose2D> stdDevs;
        //this only works for the penalty shootout, but since there's no
        //way to detect a penalty shootout from within the game..... =|
        if(bb->theOwnTeamInfo.teamColour == TEAM_RED)
        {
          //striker pose (center of the pitch)
          poses.push_back(Pose2D(0.0f, 0.0f, 0.0f));
          stdDevs.push_back(Pose2D(0.2f, 200, 200));
        }
        else
        {
          //goalie pose (in the center of the goal)
          poses.push_back(Pose2D(0.0f, static_cast<float>(bb->theFieldDimensions.xPosOwnGoalpost), 0.0f));
          stdDevs.push_back(Pose2D(0.2f, 200, 200));
        }
        initSamplesAtGivenPositions(poses, stdDevs);
      }
    }
    // normal game: if penalty is over reset samples to reenter positions
    else if(bb->theGameInfo.secondaryState == STATE2_NORMAL)
    {
      if(gameInfoPenaltyLastFrame != PENALTY_NONE && bb->theRobotInfo.penalty == PENALTY_NONE)
      {
        vector<Pose2D> poses;
        vector<Pose2D> stdDevs;
        poses.push_back(Pose2D(-pi / 2.0f, 0.0f, (float) bb->theFieldDimensions.yPosLeftSideline));
        poses.push_back(Pose2D(pi / 2.0f, 0.0f, (float) bb->theFieldDimensions.yPosRightSideline));
        stdDevs.push_back(Pose2D(0.2f, 200, 200));
        stdDevs.push_back(Pose2D(0.2f, 200, 200));
        initSamplesAtGivenPositions(poses, stdDevs);
      }
    }
    gameInfoPenaltyLastFrame = bb->theRobotInfo.penalty;
    gameInfoGameStateLastFrame = bb->theGameInfo.state;
  }

  // Initialize sample set again:
  //DEBUG_RESPONSE("module:SelfLocator:resetSamples", init(););
  // Set team color in robot pose
  //robotPose.ownTeamColorForDrawing = theOwnTeamInfo.teamColor == TEAM_BLUE ? ColorRGBA(0, 0, 255) : ColorRGBA(255, 0, 0);
}
void ArmContactModelProvider::update(ArmContactModel& model)
{
  MODIFY("module:ArmContactModelProvider:parameters", p);
  DECLARE_PLOT("module:ArmContactModelProvider:errorLeftX");
  DECLARE_PLOT("module:ArmContactModelProvider:errorRightX");
  DECLARE_PLOT("module:ArmContactModelProvider:errorLeftY");
  DECLARE_PLOT("module:ArmContactModelProvider:errorRightY");
  DECLARE_PLOT("module:ArmContactModelProvider:errorDurationLeft");
  DECLARE_PLOT("module:ArmContactModelProvider:errorDurationRight");
  DECLARE_PLOT("module:ArmContactModelProvider:errorYThreshold");
  DECLARE_PLOT("module:ArmContactModelProvider:errorXThreshold");
  DECLARE_PLOT("module:ArmContactModelProvider:contactLeft");
  DECLARE_PLOT("module:ArmContactModelProvider:contactRight");

  DECLARE_DEBUG_DRAWING("module:ArmContactModelProvider:armContact", "drawingOnField");

  CIRCLE("module:ArmContactModelProvider:armContact", 0, 0, 200, 30, Drawings::ps_solid, ColorClasses::blue, Drawings::ps_null, ColorClasses::blue);
  CIRCLE("module:ArmContactModelProvider:armContact", 0, 0, 400, 30, Drawings::ps_solid, ColorClasses::blue, Drawings::ps_null, ColorClasses::blue);
  CIRCLE("module:ArmContactModelProvider:armContact", 0, 0, 600, 30, Drawings::ps_solid, ColorClasses::blue, Drawings::ps_null, ColorClasses::blue);
  CIRCLE("module:ArmContactModelProvider:armContact", 0, 0, 800, 30, Drawings::ps_solid, ColorClasses::blue, Drawings::ps_null, ColorClasses::blue);
  CIRCLE("module:ArmContactModelProvider:armContact", 0, 0, 1000, 30, Drawings::ps_solid, ColorClasses::blue, Drawings::ps_null, ColorClasses::blue);
  CIRCLE("module:ArmContactModelProvider:armContact", 0, 0, 1200, 30, Drawings::ps_solid, ColorClasses::blue, Drawings::ps_null, ColorClasses::blue);


  /* Buffer arm angles */
  struct ArmAngles angles;
  angles.leftX = theJointRequest.angles[JointData::LShoulderPitch];
  angles.leftY = theJointRequest.angles[JointData::LShoulderRoll];
  angles.rightX = theJointRequest.angles[JointData::RShoulderPitch];
  angles.rightY = theJointRequest.angles[JointData::RShoulderRoll];
  angleBuffer.add(angles);
  
  /* Reset in case of a fall or penalty */
  if(theFallDownState.state == FallDownState::onGround || theRobotInfo.penalty != PENALTY_NONE)
  {
    leftErrorBuffer.init();
    rightErrorBuffer.init();
  }

  Pose2D odometryOffset = theOdometryData - lastOdometry;
  lastOdometry = theOdometryData;
  
  const Vector3<>& leftHandPos3D = theRobotModel.limbs[MassCalibration::foreArmLeft].translation;
  Vector2<> leftHandPos(leftHandPos3D.x, leftHandPos3D.y);
  Vector2<> leftHandSpeed = (odometryOffset + Pose2D(leftHandPos) - Pose2D(lastLeftHandPos)).translation / theFrameInfo.cycleTime;
  float leftFactor = std::max(0.f, 1.f - leftHandSpeed.abs() / p.speedBasedErrorReduction);
  lastLeftHandPos = leftHandPos;

  const Vector3<>& rightHandPos3D = theRobotModel.limbs[MassCalibration::foreArmRight].translation;
  Vector2<> rightHandPos(rightHandPos3D.x, rightHandPos3D.y);
  Vector2<> rightHandSpeed = (odometryOffset + Pose2D(rightHandPos) - Pose2D(lastRightHandPos)).translation / theFrameInfo.cycleTime;
  float rightFactor = std::max(0.f, 1.f - rightHandSpeed.abs() / p.speedBasedErrorReduction);
  lastRightHandPos = rightHandPos;
  
  /* Check for arm contact */
  // motion types to take into account: stand, walk (if the robot is upright)
  if((theMotionInfo.motion == MotionInfo::stand || theMotionInfo.motion == MotionInfo::walk) &&
     (theFallDownState.state == FallDownState::upright || theFallDownState.state == FallDownState::staggering) &&
     (theGameInfo.state == STATE_PLAYING || theGameInfo.state == STATE_READY) &&
     (theRobotInfo.penalty == PENALTY_NONE)) // TICKET 897: ArmContact only if robot is not penalized
  {
    checkArm(LEFT, leftFactor);
    checkArm(RIGHT, rightFactor);

    //left and right are projections of the 3 dimensional shoulder-joint vector
    //onto the x-y plane.
    Vector2f left = leftErrorBuffer.getAverageFloat();
    Vector2f right = rightErrorBuffer.getAverageFloat();

    
    //Determine if we are being pushed or not
    bool leftX  = fabs(left.x) > fromDegrees(p.errorXThreshold);
    bool leftY  = fabs(left.y) > fromDegrees(p.errorYThreshold);
    bool rightX = fabs(right.x)> fromDegrees(p.errorXThreshold);
    bool rightY = fabs(right.y)> fromDegrees(p.errorYThreshold);

    // update the model
    model.contactLeft  = leftX || leftY;
    model.contactRight = rightX || rightY;

    // The duration of the contact is counted upwards as long as the error
    //remains. Otherwise it is reseted to 0.
    model.durationLeft  = model.contactLeft  ? model.durationLeft + 1 : 0;
    model.durationRight = model.contactRight ? model.durationRight + 1 : 0;

    model.contactLeft &= model.durationLeft < p.malfunctionThreshold;
    model.contactRight &= model.durationRight < p.malfunctionThreshold;


    if(model.contactLeft)
    {
      model.timeOfLastContactLeft = theFrameInfo.time;
    }
    if(model.contactRight)
    {
      model.timeOfLastContactRight = theFrameInfo.time;
    }
    
    model.pushDirectionLeft = getDirection(LEFT, leftX, leftY, left);
    model.pushDirectionRight = getDirection(RIGHT, rightX, rightY, right);

    model.lastPushDirectionLeft = model.pushDirectionLeft != ArmContactModel::NONE ? model.pushDirectionLeft : model.lastPushDirectionLeft;
    model.lastPushDirectionRight = model.pushDirectionRight != ArmContactModel::NONE ? model.pushDirectionRight : model.lastPushDirectionRight;

    PLOT("module:ArmContactModelProvider:errorLeftX",         toDegrees(left.x));
    PLOT("module:ArmContactModelProvider:errorRightX",        toDegrees(right.x));
    PLOT("module:ArmContactModelProvider:errorLeftY",         toDegrees(left.y));
    PLOT("module:ArmContactModelProvider:errorRightY",        toDegrees(right.y));
    PLOT("module:ArmContactModelProvider:errorDurationLeft",  model.durationLeft);
    PLOT("module:ArmContactModelProvider:errorDurationRight", model.durationRight);
    PLOT("module:ArmContactModelProvider:errorYThreshold",    toDegrees(p.errorYThreshold));
    PLOT("module:ArmContactModelProvider:errorXThreshold",    toDegrees(p.errorXThreshold));
    PLOT("module:ArmContactModelProvider:contactLeft",        model.contactLeft ? 10.0 : 0.0);
    PLOT("module:ArmContactModelProvider:contactRight",       model.contactRight ? 10.0 : 0.0);

    ARROW("module:ArmContactModelProvider:armContact", 0, 0, -(toDegrees(left.y) * SCALE), toDegrees(left.x) * SCALE, 20, Drawings::ps_solid, ColorClasses::green);
    ARROW("module:ArmContactModelProvider:armContact", 0, 0, toDegrees(right.y) * SCALE, toDegrees(right.x) * SCALE, 20, Drawings::ps_solid, ColorClasses::red);

    COMPLEX_DRAWING("module:ArmContactModelProvider:armContact",
    {
      DRAWTEXT("module:ArmContactModelProvider:armContact", -2300, 1300, 20, ColorClasses::black, "LEFT");
      DRAWTEXT("module:ArmContactModelProvider:armContact", -2300, 1100, 20, ColorClasses::black, "ErrorX: " << toDegrees(left.x));
      DRAWTEXT("module:ArmContactModelProvider:armContact", -2300, 900, 20, ColorClasses::black,  "ErrorY: " << toDegrees(left.y));
      DRAWTEXT("module:ArmContactModelProvider:armContact", -2300, 500, 20, ColorClasses::black,  ArmContactModel::getName(model.pushDirectionLeft));
      DRAWTEXT("module:ArmContactModelProvider:armContact", -2300, 300, 20, ColorClasses::black,  "Time: " << model.timeOfLastContactLeft);

      DRAWTEXT("module:ArmContactModelProvider:armContact", 1300, 1300, 20, ColorClasses::black, "RIGHT");
      DRAWTEXT("module:ArmContactModelProvider:armContact", 1300, 1100, 20, ColorClasses::black, "ErrorX: " << toDegrees(right.x));
      DRAWTEXT("module:ArmContactModelProvider:armContact", 1300, 900, 20, ColorClasses::black,  "ErrorY: " << toDegrees(right.y));
      DRAWTEXT("module:ArmContactModelProvider:armContact", 1300, 500, 20, ColorClasses::black,  ArmContactModel::getName(model.pushDirectionRight));
      DRAWTEXT("module:ArmContactModelProvider:armContact", 1300, 300, 20, ColorClasses::black,  "Time: " << model.timeOfLastContactRight);

      if (model.contactLeft)
      {
        CROSS("module:ArmContactModelProvider:armContact", -2000, 0, 100, 20, Drawings::ps_solid, ColorClasses::red);
      }
      if (model.contactRight)
      {
        CROSS("module:ArmContactModelProvider:armContact", 2000, 0, 100, 20, Drawings::ps_solid, ColorClasses::red);
      }
  });
void ObstacleCombinator::generateObstacleFromCurrentCluster(std::vector<ObstacleModel::Obstacle>& obstacles)
{
  Vector2<int>& c = currentCluster.cells[0];
  int xMin(c.x);
  int yMin(c.y);
  int xMax(c.x);
  int yMax(c.y);
  float rightAngle = 10.0;
  float leftAngle = -10.0;
  Vector2<int> rightCorner;
  Vector2<int> leftCorner;
  Vector2<> centerCells;
  Vector2<int> robotPosition(USObstacleGrid::GRID_LENGTH / 2, USObstacleGrid::GRID_LENGTH / 2);
  Vector2<int> closestPoint(USObstacleGrid::GRID_LENGTH, USObstacleGrid::GRID_LENGTH);
  int closestPointSqrDist(USObstacleGrid::GRID_SIZE * 2);
  for(unsigned int i = 0; i < currentCluster.cells.size(); ++i)
  {
    c = currentCluster.cells[i];
    centerCells.x += c.x;
    centerCells.y += c.y;
    Vector2<int> point(c.x - robotPosition.x, c.y - robotPosition.y);
    int sqrDistToRobot = sqr(point.x) + sqr(point.y);
    float angleToRobot = atan2(static_cast<float>(point.y), static_cast<float>(point.x));
    if(angleToRobot < rightAngle)
    {
      rightAngle = angleToRobot;
      rightCorner = Vector2<int>(c.x, c.y);
    }
    if(angleToRobot > leftAngle)
    {
      leftAngle = angleToRobot;
      leftCorner = Vector2<int>(c.x, c.y);
    }
    if(sqrDistToRobot < closestPointSqrDist)
    {
      closestPoint = c;
      closestPointSqrDist = sqrDistToRobot;
    }
    if(c.x < xMin)
      xMin = c.x;
    else if(c.x > xMax)
      xMax = c.x;
    if(c.y < yMin)
      yMin = c.y;
    else if(c.y > yMax)
      yMax = c.y;
  }
  centerCells /= static_cast<float>(currentCluster.cells.size());

  const float angleToCenterPoint = Geometry::angleTo(Pose2D(USObstacleGrid::GRID_LENGTH / 2, USObstacleGrid::GRID_LENGTH / 2), centerCells); //calculates the angle to the center of the cluster in grid coordinate system (independent of robot rotation)
  const float cosinus = cos(-angleToCenterPoint);
  const float sinus = sin(-angleToCenterPoint);
  float newX;
  float newY;

  //initializing of the rectangle
  float xMinRotated(FLT_MAX);
  float yMinRotated(FLT_MAX);
  float xMaxRotated(-FLT_MAX);
  float yMaxRotated(-FLT_MAX);

  for(unsigned int i = 0; i < currentCluster.cells.size(); ++i)
  {
    newX = cosinus * currentCluster.cells[i].x - sinus * currentCluster.cells[i].y; // rotates each cell of the cluster
    newY = sinus * currentCluster.cells[i].x + cosinus * currentCluster.cells[i].y;
    //sets new values for rectangle
    if(newX < xMinRotated)
      xMinRotated = newX;
    else if(newX > xMaxRotated)
      xMaxRotated = newX;
    if(newY < yMinRotated)
      yMinRotated = newY;
    else if(newY > yMaxRotated)
      yMaxRotated = newY;
  }

  Vector2<> closestPointWorld = gridToWorld(Vector2<>(closestPoint.x + 0.5f, closestPoint.y + 0.5f));
  Vector2<> centerWorld = gridToWorld(centerCells);

  //expansion (length of x- and y-axis through the center point) and orientation (dependent on robot rotation) of the cluster
  Vector3<> covarianceEllipse(((xMaxRotated - xMinRotated) * USObstacleGrid::CELL_SIZE) * parameters.covarianceFactor, ((yMaxRotated - yMinRotated) * USObstacleGrid::CELL_SIZE) * parameters.covarianceFactor, atan2(centerWorld.y, centerWorld.x));
  Matrix2x2<> covariance(covarianceEllipse.x, 0, 0, covarianceEllipse.y); // covariance is initialised with uncorrelated values (only expansion of cluster as variances)
  rotateMatrix(covariance, covarianceEllipse.z); // rotates the covariance so that it fits to the orientation and expansion of the cluster

  obstacles.push_back(ObstacleModel::Obstacle(gridToWorld(Vector2<>((float)(leftCorner.x), (float)(leftCorner.y))),
                      gridToWorld(Vector2<>((float)(rightCorner.x), (float)(rightCorner.y))), centerWorld, closestPointWorld,
                      static_cast<int>(currentCluster.cells.size()), covariance));
}
Esempio n. 7
0
Vector2<> Geometry::vectorTo(const Pose2D& from, const Vector2<>& to)
{
  return (Pose2D(to) - from).translation;
}
Esempio n. 8
0
float Geometry::distanceTo(const Pose2D& from, const Vector2<>& to)
{
  return (Pose2D(to) - from).translation.abs();
}
Esempio n. 9
0
float Geometry::angleTo(const Pose2D& from, const Vector2<>& to)
{
  Pose2D relPos = Pose2D(to) - from;
  return atan2(relPos.translation.y, relPos.translation.x);
}
Esempio n. 10
0
// Pose is the average of all the particles
const Pose2D& ParticleFilter::pose() const {
  if(dirty_) {

	typedef Point2D Centroid;

	// k means clustering
	//
	// Initialize random centroids
	set<Centroid, centroid_comp_> centroids;
	for (int i = 0; i < NUM_CLUSTERS; i++) {
		Centroid centroid;
	    centroid.x = (rand() % (2*2500)) - 2500;
	    centroid.y = (rand() % (2*1250)) - 1250;

	    centroids.insert(centroid);
	}

//	Centroid centroid;
//	centroid.x = -1000;
//	centroid.y = 0;
//	centroids.insert(centroid);
//
//	centroid.x = 1000;
//	centroid.y = 0;
//	centroids.insert(centroid);

//	cout << "========> BEGIN K-MEANS <========" << endl;

//	cout << "PARTICLES" << endl;
//	for (auto p : particles())
//		cout << p.x << " " << p.y << endl;
//	cout << endl;
////
//	cout << "Random Centroids" << endl;
//	for (auto centroid : centroids)
//		cout << centroid.x << " " << centroid.y << endl;
//	cout << endl;

	// Iterate until convergence
	map<Centroid, set<Particle, particle_comp_>, centroid_comp_> closest_particles;
	set<Point2D, centroid_comp_> new_centroids = centroids;
	map<Centroid, int, centroid_comp_> cluster_size;
	int i = 0;
	do {
//		cout << "PARTICLES" << endl;
//		for (auto p : particles())
//			cout << p.x << " " << p.y << endl;
//		cout << endl;

		centroids = new_centroids;
		new_centroids.clear();
		cluster_size.clear();
		// Compute the closest centroid to each particle
		double closest_centroid_distance = 50000;
		Centroid closest_centroid = NULL;
		for (Particle p : particles()) {
			for (Centroid centroid : centroids) {
//				cout << "Current closest distance: " << closest_centroid_distance << endl;
				double distance = sqrt(pow(p.x-centroid.x, 2) + pow(p.y-centroid.y, 2));
				// Record the closest centroid
//				cout << "Particle " << p.x << " " << p.y << endl;
//				cout << "Comparing centroid: " << centroid.x << " " << centroid.y << endl;
//				cout << "Proposal Distance: " << distance << endl;
				if (distance < closest_centroid_distance) {
//					cout << "Proposed distance is closer!!!" << endl;
					closest_centroid_distance = distance;
					closest_centroid = centroid;
				}
			}

//			cout << "C(" << closest_centroid.x << " " << closest_centroid.y << ") -> P(" << p.x << " " << p.y << ")" << endl;
			closest_particles[closest_centroid].insert(p);

			// Record the closest centroid
//			cout << "Particle " << p.x << " " << p.y << endl;
//			cout << "Closest centroid: " << closest_centroid.x << " " << closest_centroid.y << endl;
//			cout << "Centroid distance: " << closest_centroid_distance << endl << endl;
//			for (auto c : closest_particles) {
//				cout << "CENTROID " << c.first.x << " " << c.first.y << " at this point..." << endl;
//				for (auto pp : c.second) {
//					cout << pp.x << " " << pp.y << endl;
//				}
//				cout << endl;
//			}
//			cout << endl;

			closest_centroid = NULL;
			closest_centroid_distance = 50000;
		}

//		// Print closest particles
//		for (auto elem : closest_particles) {
//			cout << "Centroid: " << elem.first.x << " " << elem.first.y << endl;
//
//			for (auto p : elem.second) {
//				cout << "Particle: " << p.x << " " << p.y << endl;
//			}
//
//			cout << endl;
//		}

		// Recompute the centroids based on the mean of all the closest particles
		for (Centroid centroid : centroids) {
			double sum_x = 0;
			double sum_y = 0;
			for (Particle p : closest_particles[centroid]) {
				sum_x += p.x;
				sum_y += p.y;
			}

			int num_particles = closest_particles[centroid].size();
			if (num_particles > 0) {
				new_centroids.insert(Centroid(sum_x/num_particles, sum_y/num_particles));
				cluster_size[centroid] = num_particles;
			}
		}

//		cout << "Centroids" << endl;
//		for (auto centroid : centroids)
//			cout << centroid.x << " " << centroid.y << " (" << cluster_size[centroid] << ")" << endl;
//		cout << endl;
//
//		cout << "New Centroids" << endl;
//		for (auto centroid : new_centroids)
//			cout << centroid.x << " " << centroid.y << " (" << cluster_size[centroid] << ")" << endl;
//		cout << endl << endl;

		i++;
	} while (i < 3);

//	cout << "Centroids" << endl;
//	for (auto centroid : centroids)
//		cout << centroid.x << " " << centroid.y << " (" << cluster_size[centroid] << ")" << endl;
//	cout << endl;

	Centroid best_cluster;
	double max_particles = -1;
	for (Centroid centroid : centroids) {
		if (cluster_size[centroid] > max_particles) {
			best_cluster = centroid;
			max_particles = cluster_size[centroid];
		}
	}

//	cout << "Best cluster: " << best_cluster.x << " " << best_cluster.y << " (" << cluster_size[best_cluster] << ")" << endl;
//
//	cout << "========> END K-MEANS <========" << endl << endl;

    // Compute the mean pose estimate
    mean_ = Pose2D();
    using T = decltype(mean_.translation);
    for(const auto& p : particles()) {
      mean_.translation += T(p.x,p.y);
      mean_.rotation += p.t;
    }
    if(particles().size() > 0)
      mean_ /= particles().size();

    // k-means update
    mean_.translation = best_cluster;

    dirty_ = false;
  }
  return mean_;
}
Esempio n. 11
0
void SpecialActions::update(SpecialActionsOutput& specialActionsOutput)
{
  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 < JointData::numOfJoints; ++i)
          lastRequest.angles[i] = theFilteredJointData.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 hardness
      if(wasEndOfSpecialAction)
      {
        specialActionsOutput.jointHardness.resetToDefault();
        if(!mirror)
          lastHardnessRequest = currentHardnessRequest;
        else
          lastHardnessRequest.mirror(currentHardnessRequest);
        currentHardnessRequest.resetToDefault();
      }
      wasEndOfSpecialAction = false;
      // search next data, leave on transition to external motion
      if(!getNextData(theMotionSelection.specialActionRequest, specialActionsOutput))
      {
        wasActive = true;
        wasEndOfSpecialAction = true;
        specialActionsOutput.odometryOffset = Pose2D();
        return;
      }
    }
    else
    {
      dataRepetitionCounter -= int(theFrameInfo.cycleTime * 1000 * speedFactor);
      hardnessInterpolationCounter -= 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 = Pose2D(-currentInfo.odometryOffset.rotation, currentInfo.odometryOffset.translation.x, -currentInfo.odometryOffset.translation.y);
      else
        specialActionsOutput.odometryOffset = currentInfo.odometryOffset;
    else
      specialActionsOutput.odometryOffset = Pose2D();
    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 = JointData::LShoulderPitch; i <= JointData::RElbowRoll; ++i)
        if(randomFloat() < 0.25)
          specialActionsOutput.angles[i] = JointData::off;
  }
  wasActive = theMotionSelection.specialActionMode == MotionSelection::active;
}
void CameraMatrixProvider::drawFieldLines(const CameraMatrix& cameraMatrix, const RobotPose& theRobotPose, const FieldDimensions& theFieldDimensions, const CameraInfo& theCameraInfo) const
{
  Vector3<> start0C, start1C, end0C, end1C;
  Vector2<> start0I, start1I, end0I, end1I;

  const Pose2D& robotPoseInv(theRobotPose.invert());
  const Pose3D& cameraMatrixInv(cameraMatrix.invert());
  int halfFieldLinesWidth = theFieldDimensions.fieldLinesWidth / 2;

  for(unsigned int i = 0; i < theFieldDimensions.fieldLines.lines.size(); ++i)
  {
    Pose2D relativeLine(robotPoseInv);
    relativeLine.conc(theFieldDimensions.fieldLines.lines[i].corner);
    const Vector2<> start0(Pose2D(relativeLine).translate(0, (float) - halfFieldLinesWidth).translation);
    const Vector2<> end1(Pose2D(relativeLine).translate(theFieldDimensions.fieldLines.lines[i].length, (float) halfFieldLinesWidth).translation);

    start0C = cameraMatrixInv * Vector3<>(start0.x, start0.y, 0.); // field2camera
    end1C = cameraMatrixInv * Vector3<>(end1.x, end1.y, 0.); // field2camera

    if(start0C.x <= 200 && end1C.x <= 200)
      continue;

    const Vector2<>& start1(Pose2D(relativeLine).translate(0, (float) halfFieldLinesWidth).translation);
    const Vector2<>& end0(Pose2D(relativeLine).translate(theFieldDimensions.fieldLines.lines[i].length, (float) - halfFieldLinesWidth).translation);

    start1C = cameraMatrixInv * Vector3<>(start1.x, start1.y, 0.); // field2camera
    end0C = cameraMatrixInv * Vector3<>(end0.x, end0.y, 0.); // field2camera

    if(start0C.x <= 200)
      intersectLineWithCullPlane(start0C, end0C - start0C, start0C);
    else if(end0C.x <= 200)
      intersectLineWithCullPlane(start0C, end0C - start0C, end0C);
    if(start1C.x <= 200)
      intersectLineWithCullPlane(start1C, end1C - start1C, start1C);
    else if(end1C.x <= 200)
      intersectLineWithCullPlane(start1C, end1C - start1C, end1C);

    camera2image(start0C, start0I, theCameraInfo);
    camera2image(end0C, end0I, theCameraInfo);
    camera2image(start1C, start1I, theCameraInfo);
    camera2image(end1C, end1I, theCameraInfo);

    //LINE("module:CameraMatrixProvider:calibrationHelper", start0I.x, start0I.y, end0I.x, end0I.y, 0, Drawings::ps_solid, ColorRGBA(0, 0, 0));
    //LINE("module:CameraMatrixProvider:calibrationHelper", start1I.x, start1I.y, end1I.x, end1I.y, 0, Drawings::ps_solid, ColorRGBA(0, 0, 0));
  }

  start0C = cameraMatrixInv * Vector3<>(100, -11, 0.); // field2camera
  end0C = cameraMatrixInv * Vector3<>(0, -11, 0.); // field2camera
  camera2image(start0C, start0I, theCameraInfo);
  camera2image(end0C, end0I, theCameraInfo);

  //LINE("module:CameraMatrixProvider:calibrationHelper", start0I.x, start0I.y, end0I.x, end0I.y, 0, Drawings::ps_solid, ColorClasses::blue);

  start0C = cameraMatrixInv * Vector3<>(100, 11, 0.); // field2camera
  end0C = cameraMatrixInv * Vector3<>(0, 11, 0.); // field2camera
  camera2image(start0C, start0I, theCameraInfo);
  camera2image(end0C, end0I, theCameraInfo);

  //LINE("module:CameraMatrixProvider:calibrationHelper", start0I.x, start0I.y, end0I.x, end0I.y, 0, Drawings::ps_solid, ColorClasses::blue);

  start0C = cameraMatrixInv * Vector3<>(110, 1000, 0.); // field2camera
  end0C = cameraMatrixInv * Vector3<>(110, -1000, 0.); // field2camera
  camera2image(start0C, start0I, theCameraInfo);
  camera2image(end0C, end0I, theCameraInfo);

  //LINE("module:CameraMatrixProvider:calibrationHelper", start0I.x, start0I.y, end0I.x, end0I.y, 0, Drawings::ps_solid, ColorClasses::blue);
}
Esempio n. 13
0
Pose2D OccupancyMapParams::getPoseFromPixel(const Pose2Di& pixel) const {
  return Pose2D(pixel.x * metersPerPixel + originOffset.x,
                      -pixel.y * metersPerPixel + originOffset.y, pixel.theta);
}
bool TeamDataProvider::handleMessage(InMessage& message)
{
  /*
  The robotNumber and the three flags hasGroundContact, isUpright and isPenalized should always be updated.
  */
  switch(message.getMessageID())
  {
  case idNTPHeader:
    VERIFY(ntp.handleMessage(message));
    timeStamp = ntp.receiveTimeStamp;
    return false;
  case idNTPIdentifier:
  case idNTPRequest:
  case idNTPResponse:
    return ntp.handleMessage(message);

  case idRobot:
    message.bin >> robotNumber;
    if(robotNumber != theRobotInfo.number)
      if(robotNumber >= TeamMateData::firstPlayer && robotNumber < TeamMateData::numOfPlayers)
        theTeamMateData.timeStamps[robotNumber] = timeStamp;
    return true;

  case idReleaseOptions:
    message.bin >> Global::getReleaseOptions();
    return true;

  case idSSLVisionData:
  {
    message.bin >> theSSLVisionData;
    unsigned remoteTimestamp = theSSLVisionData.recentData.top().receiveTimestamp;
    REMOTE_TO_LOCAL_TIME(theSSLVisionData.recentData.top().receiveTimestamp);
    unsigned localTimestamp = theSSLVisionData.recentData.top().receiveTimestamp;
    int offset = (int) localTimestamp - (int) remoteTimestamp;
    PLOT("module:TeamDataProvider:sslVisionOffset", offset);
  }
  return true;

  case idGroundTruthBallModel:
  {
    Vector2<> position;
    message.bin >> theGroundTruthBallModel.timeWhenLastSeen >> position;
    REMOTE_TO_LOCAL_TIME(theGroundTruthBallModel.timeWhenLastSeen);
    if(theOwnTeamInfo.teamColor == TEAM_BLUE)
      position *= -1;
    theGroundTruthBallModel.lastPerception.setPositionAndVelocityInFieldCoordinates(
      position, Vector2<>(), theGroundTruthRobotPose);
    theGroundTruthBallModel.estimate = theGroundTruthBallModel.lastPerception;
  }
  return true;

  case idGroundTruthRobotPose:
  {
    char teamColor,
         id;
    unsigned timeStamp;
    Pose2D robotPose;
    message.bin >> teamColor >> id >> timeStamp >> robotPose;
    if(teamColor == (int)theOwnTeamInfo.teamColor && id == theRobotInfo.number)
    {
      if(theOwnTeamInfo.teamColor == TEAM_BLUE)
        robotPose = Pose2D(pi) + robotPose;
      (Pose2D&) theGroundTruthRobotPose = robotPose;
    }
  }
  return true;

  case idTeamMateIsPenalized:
    if(robotNumber != theRobotInfo.number)
      if(robotNumber >= TeamMateData::firstPlayer && robotNumber < TeamMateData::numOfPlayers)
        message.bin >> theTeamMateData.isPenalized[robotNumber];
    return true;

  case idTeamMateHasGroundContact:
    if(robotNumber != theRobotInfo.number)
      if(robotNumber >= TeamMateData::firstPlayer && robotNumber < TeamMateData::numOfPlayers)
        message.bin >> theTeamMateData.hasGroundContact[robotNumber];
    return true;

  case idTeamMateIsUpright:
    if(robotNumber != theRobotInfo.number)
      if(robotNumber >= TeamMateData::firstPlayer && robotNumber < TeamMateData::numOfPlayers)
        message.bin >> theTeamMateData.isUpright[robotNumber];
    return true;

  case idTeamMateTimeSinceLastGroundContact:
    if(robotNumber != theRobotInfo.number)
      if(robotNumber >= TeamMateData::firstPlayer && robotNumber < TeamMateData::numOfPlayers)
      {
        message.bin >> theTeamMateData.timeSinceLastGroundContact[robotNumber];
        REMOTE_TO_LOCAL_TIME(theTeamMateData.timeSinceLastGroundContact[robotNumber]);
      }
    return true;

  default:
    break;
  }
Esempio n. 15
0
void PreviewWalk::goNextFrame(WalkingEngineOutput& lastWalkOoutput, WalkingEngineOutput& walkingEngineOutput, const NaoStructure& naoStructure)
{
	lastWalkStatus = walkStatus;
	// Copy from global naoStructure, as we will temporary modify this buffer for some calculation
	naoStructTmp = naoStructure;
	//first check for cmd change
	if(isCmdPending && isCmdChangePossible() && !(lastWalkStatus==WalkTypeBase::standing&&pendingCmd.speed==Pose2D(0,0,0)))
	{
		//std::cout<<"---isCmdPending shoule be true:  "<<pendingCmd.speed.translation.x<<"  "<<pendingCmd.speed.translation.y<<"  "<<pendingCmd.speed.rotation<<std::endl;
		executingCmd = pendingCmd;
		isCmdPending = false;
		// TODO: when we switch from other walk type , we need to reset the generator
		if(!preBufferGenrator.hasInitialized() 
			|| (executingCmd.walkType != lastwalktype/*lastWalkStatus*/ && lastWalkStatus == WalkTypeBase::standing))
		{
			//std::cout<<"------previewwalk reset---"<<std::endl;
			preBufferGenrator.reset(executingCmd,naoStructTmp);
			preBufferGenrator.changeSpeed(executingCmd, naoStructTmp);
			initialSlowCounter = walkParam.PG;
			// TODO: use measured COM Vector(p, vel, acc)
			double cposx = naoStructure.pCOM.x;
			double cposy = naoStructure.pCOM.y - (naoStructure.uLink[NaoStructure::lFootLink].p.y + naoStructure.uLink[NaoStructure::rFootLink].p.y)/2 ;
			previewController.resetController(Vector3<double>(cposx,0,0), Vector3<double>(cposy,0,0));
			pRefCoMLast = naoStructure.pCOM;
			
		}else
		{
			preBufferGenrator.changeSpeed(executingCmd, naoStructTmp);
			if (lastWalkStatus == WalkTypeBase::standing)
			{
				double cposx = naoStructure.pCOM.x;
				double cposy = naoStructure.pCOM.y - (naoStructure.uLink[NaoStructure::lFootLink].p.y + naoStructure.uLink[NaoStructure::rFootLink].p.y)/2 ;
				previewController.resetController(Vector3<double>(cposx,0,0), Vector3<double>(cposy,0,0));
				pRefCoMLast = naoStructure.pCOM;
			}
			//std::cout<<"------previewwalk changeSpeed---"<<std::endl;
		}
		lastwalktype = executingCmd.walkType;
	}
	

	if(!preBufferGenrator.hasInitialized())
		return;
	//=======
	PreviewState state;
	PreviewBuffer& previewBuffer = preBufferGenrator.getPreviewBuffer();
	if(!previewBuffer.empty())
		state= previewBuffer.front();
	if(state.walkStatus == WalkTypeBase::standing){
		walkStatus = WalkTypeBase::standing;
		//std::cout<<"------------standing standing standing ! ! !---------"<<std::endl;
		walkingEngineOutput.isLeavingPossible = true;
		return;
	}
	else{
		walkingEngineOutput.isLeavingPossible = false;
	}
	int lastSupMode = state.supmod;
	// lastWalkStatus = state.walkStatus
	// preBufferGenrator go Next and generate new knots and state
	preBufferGenrator.generateNext();
	if(!previewBuffer.empty())
		state = previewBuffer.front();
	sup_mod = state.supmod;
	walkStatus = state.walkStatus;
	naoStructTmp.supportingMode = sup_mod;
	//std::cout<<"------------WalkTypeBase: "<<walkStatus<<std::endl;  //start 1; ending 2; running 3; standing 4;  
	if (walkStatus!=WalkTypeBase::ending&&lastWalkStatus==WalkTypeBase::ending)
	{
		preBufferGenrator.finishEnding();
	}
	/*if(walkStatus == WalkTypeBase::standing){
		std::cout<<"------------standing standing standing ! ! !---------"<<std::endl;
		smoothJoints(walkingEngineOutput, lastWalkOoutput);
		lastWalkOoutput = walkingEngineOutput;
		walkingEngineOutput.isLeavingPossible = true;
		preBufferGenrator.generateNext();
		return;
	}*/
	// Foot positioning modification according to zmp error and last walk status
// 	if(state.walkStatus == WalkTypeBase::running && previewBuffer[1].supmod != sup_mod &&
// 		(sup_mod == NaoConfig::SUPPORT_MODE_DOUBLE_RIGHT || sup_mod == NaoConfig::SUPPORT_MODE_DOUBLE_LEFT) )
// 	{
// 		Vector3<double> zmpm = RotationMatrix(0, 0, lastState.rSupFootZMP.z) *pRobotState->mZMP + lastState.pSupFootZMP;
// 		Vector3<double> zmperror = state.pZMP - zmpm;
// 		preBufferGenrator.doLandingEvent(zmperror, Vector3<double>(0,0,0));
// 	}
	// TODO: If we use Sensor to detect supporting mode, the code bellow should be modified!!
	// When Supporting Leg Changed, modify pCOM to value relative to current supporting Foot
	if(lastSupMode != sup_mod &&
		((sup_mod == NaoConfig::SUPPORT_MODE_LEFT || sup_mod == NaoConfig::SUPPORT_MODE_RIGHT) ||
		(lastWalkStatus != walkStatus && lastWalkStatus == WalkTypeBase::standing)))
	{ 
		naoStructTmp.uLink[NaoStructure::bodyLink].p = Vector3<double>(0,0,0);
		naoStructTmp.uLink[NaoStructure::bodyLink].R = RotationMatrix();
		Kinematics::execForwardKinematics(naoStructTmp, NaoStructure::bodyLink);
		Kinematics::recalcBodyPos2SupFoot(naoStructTmp, Vector3<double>(0,0,0), naoStructTmp.supportingMode);
		Kinematics::execForwardKinematics(naoStructTmp, NaoStructure::bodyLink);
		naoStructTmp.pCOM = Kinematics::calcCOM(naoStructTmp);
		//In case we get NAN or IND num.... print some thing and halt execution when run on robot!!
		ASSERT(naoStructTmp.pCOM == naoStructTmp.pCOM);
	}
	//===== Check Landing Step Error=============================
	if(false && state.walkStatus == WalkTypeBase::running && lastSupMode != sup_mod &&
		(sup_mod == NaoConfig::SUPPORT_MODE_DOUBLE_RIGHT || sup_mod == NaoConfig::SUPPORT_MODE_DOUBLE_LEFT) )
	{
		Vector3<double> pRealLandFootW,rRealLandFootW;
		Vector3<double> pRealLandFoot2Sup;
		Vector3<double> pRefLandFootW, rRefLandFootW;
		const PreBufferGenerator::Knot* pKnot = 0;
		int landFoot = 0;
		if(sup_mod == NaoConfig::SUPPORT_MODE_DOUBLE_RIGHT)
			landFoot = NaoStructure::lFootLink;
		else if(sup_mod == NaoConfig::SUPPORT_MODE_DOUBLE_LEFT)
			landFoot = NaoStructure::rFootLink;

		pRealLandFoot2Sup = naoStructTmp.getPosition(landFoot, NaoStructure::Space_Supprot_Leg);
		pRealLandFoot2Sup.z = 0;
		pRealLandFootW = state.pSupFootZMP + RotationMatrix::getRotationZ(state.rSupFootZMP.z) * pRealLandFoot2Sup;
		rRealLandFootW = state.rSupFootZMP;
		rRealLandFootW.z += naoStructTmp.getRotAngles(landFoot, NaoStructure::Space_Supprot_Leg).z;

		pKnot = preBufferGenrator.findNextKnot();	
		ASSERT(pKnot);
		pRefLandFootW = pKnot->pSupFootZMP;
		rRefLandFootW = pKnot->rSupFootZMP;
		Vector3<double> pError = (pRefLandFootW - pRealLandFootW), rError(rRefLandFootW - rRealLandFootW);
		preBufferGenrator.doLandingEvent(pError, rError);
		// TODO: check here?
		preBufferGenrator.generateNext();
		if(!previewBuffer.empty())
			state = previewBuffer.front();
		sup_mod = state.supmod;
		walkStatus = state.walkStatus;
		naoStructTmp.supportingMode = sup_mod;
	}
	// ==== Get Swing Foot Infomation
	int iswgleg = NaoConfig::LegIDLeft;
	if(sup_mod == NaoConfig::SUPPORT_MODE_LEFT || sup_mod == NaoConfig::SUPPORT_MODE_DOUBLE_LEFT)
		iswgleg= NaoConfig::LegIDRight;
	Vector3<double> pSwgFootW, rSwgFootW;
	preBufferGenrator.getCurrentSwgF(pSwgFootW, rSwgFootW, iswgleg);
	pSwgFootW += Vector3<double>(0,0, NaoConfig::getInstance()->FootHeight);// TODO: muliply foot rotation
	Vector3<double> pSwgFoot2Sup, rSwgFoot2Sup;
	pSwgFoot2Sup = RotationMatrix::getRotationZ(-state.rSupFootZMP.z) * (pSwgFootW - state.pSupFootZMP);
	rSwgFoot2Sup = rSwgFootW - state.rSupFootZMP;
	// ====== CoM Control=====================
	double bRoll = pSensorData->data[SensorData::angleX];
	double bTilt = pSensorData->data[SensorData::angleY];
	RotationMatrix Rbw = RotationMatrix().rotateX(bRoll).rotateY(bTilt);
	RotationMatrix Rfw;//rotation of supporting foot in world cooridnate
	if(naoStructTmp.supportingMode == NaoConfig::SUPPORT_MODE_LEFT || naoStructTmp.supportingMode == NaoConfig::SUPPORT_MODE_DOUBLE_LEFT)
	{
		Rfw = naoStructTmp.uLink[NaoStructure::lFootLink].R * naoStructTmp.uLink[NaoStructure::bodyLink].R.invert();
	}else
	{
		Rfw =  naoStructTmp.uLink[NaoStructure::rFootLink].R * naoStructTmp.uLink[NaoStructure::bodyLink].R.invert();
	}
	Rfw = RotationMatrix::getRotationZ(state.rSupFootZMP.z) * Rfw * Rbw;
		// check world com state
	Vector3<double> comW = Rfw * naoStructure.getCoM(NaoStructure::Space_Supprot_Leg)+ lastState.pSupFootZMP;
	Vector3<double> comWv =  (comW - lastCoMW) / walkParam.dt;
	Vector3<double> comWa = Rbw * Vector3<double>(pSensorData->data[SensorData::accX], pSensorData->data[SensorData::accY], pSensorData->data[SensorData::accZ]);
	PrviewControllerState inputState;
	inputState.p = comW; inputState.v = comWv; inputState.a = comWa;
	Vector3<double> zmpW = RotationMatrix(0, 0, lastState.rSupFootZMP.z) *pRobotState->mZMP + lastState.pSupFootZMP;
	//=======Compute step modification according to  ZMP error and CoM information=========
	Vector3<double> ezmp =pRobotState->mZMP - RotationMatrix(0, 0, -state.rSupFootZMP.z)* (state.pZMP - state.pSupFootZMP);// state.pZMP - zmpW;
	if(state.supmod == NaoConfig::SUPPORT_MODE_RIGHT || state.supmod == NaoConfig::SUPPORT_MODE_DOUBLE_RIGHT)
			ezmp.y = - ezmp.y;
	//======Learning Step Modification Process=====
	if(Open_Step_Learning)
	{
		if(state.walkStatus == WalkTypeBase::running){
			sumZMPErrorTotal += Vector3<double>(fabs(ezmp.x), fabs(ezmp.y), fabs(ezmp.z));
			numZMPErrorAdded ++;
			updateCounter ++;
		}
		if((lastUpdateModelFlag != pRobotState->fallState.updateModel && pRobotState->fallState.updateModel == true) 
			|| (state.walkStatus == WalkTypeBase::running && updateCounter%600 == 0))
		{
			double critia1 = (sumZMPErrorTotal.x * 0.3+ sumZMPErrorTotal.y * 0.7)/ numZMPErrorAdded;//if we fall, the zmp error will also be significant
			double performance = critia1;
			double critia2 =  (pi - atan(static_cast<double>(numZMPErrorAdded) * 2 / walkParam.PG -3)) /2;
			performance = performance + performance * critia2;//walk longer, we walk better
			double critia3 = 0;
			if(numStepModify > 0)
				critia3 = (sumStepModify.x / numStepModify * 0.5 + sumStepModify.y / numStepModify) * 0.5;
			performance += critia3;
			learnerAgent.updatePerform(performance);
			learnerAgent.getPendingParam(spController);
			//std::cout<<"===>LearnCritia: ("<<numZMPErrorAdded<<", "<<sumZMPErrorTotal.x<<", "<<sumZMPErrorTotal.y<<"), "<<critia1<<", "<<critia2<<", "<<critia3<<std::endl;
			sumZMPErrorTotal = Vector3<double>(0,0,0);
			numZMPErrorAdded  = 0;
			updateCounter = 1;
			sumStepModify = Vector3<double>(0,0,0);
			numStepModify = 0;
		}
		lastUpdateModelFlag = pRobotState->fallState.updateModel;
	}
	//============
	if(Open_Step_Modify || Open_Step_Learning)
	{
		if(lastSupMode != sup_mod && sup_mod == NaoConfig::SUPPORT_MODE_LEFT)
		{
			errorZMP.x  = 0; errorZMP.y = 0;nErrors = 0;onSeeSupMode = sup_mod;
			spController.resetZMPError();
		}else if(lastSupMode != sup_mod && sup_mod == NaoConfig::SUPPORT_MODE_RIGHT)
		{
			errorZMP.x  = 0; errorZMP.y = 0;nErrors = 0;onSeeSupMode = sup_mod;
			spController.resetZMPError();
		}
		if(state.walkStatus == WalkTypeBase::running && sup_mod == onSeeSupMode && nErrors < 10)
		{
			errorZMP += ezmp;
			nErrors++;
			spController.addZMPError(ezmp);
		}
		if(sup_mod == onSeeSupMode && nErrors == 10)
		{
			nErrors++;
			//============switch to local system========
			RotationMatrix R = RotationMatrix::getRotationZ(-state.rSupFootZMP.z) * Rfw;
			Vector3<double> p = R * naoStructure.getCoM(NaoStructure::Space_Supprot_Leg);
			Vector3<double> v = RotationMatrix::getRotationZ(-state.rSupFootZMP.z)  * inputState.v;
			Vector3<double> a = comWa;
			if(state.supmod == NaoConfig::SUPPORT_MODE_RIGHT || state.supmod == NaoConfig::SUPPORT_MODE_DOUBLE_RIGHT)
			{
				p.y = - p.y; v.y = -v.y; a.y = -a.y;
			}
			Vector3<double> xState(p.x, v.x, a.x), yState(p.y, v.y, a.y);
			Vector3<double> dP = spController.getOutput(xState, yState);
			// Become effect in next frame....
			preBufferGenrator.modifyStepPosition(Vector3<double>(dP.x, dP.y, 0), Vector3<double>(0,0,0), 16);
			sumStepModify.x += dP.x * dP.x;
			sumStepModify.y += dP.y * dP.y;
			numStepModify ++;
			//MATLABHELP_PLOT(dPy, "dPy");
			//MATLABHELP_PLOT(spController.getSumZMPError(), "mErrrory");
		}
	}

	//=== Get Preview Controller Output============
	PrviewControllerOutput outputPC ;
// 	if(walkStatus != WalkTypeBase::starting && (sup_mod == 1 || sup_mod == 3))
// 		outputPC = previewController.getRefCOM(previewBuffer, walkParam, inputState);
// 	else
		outputPC = previewController.getRefCOM(previewBuffer, walkParam);
	Vector3<double> pCOMRefW(outputPC.p); 
	// CoM Ref world system to body system
	Vector3<double> pCOMRef =RotationMatrix::getRotationZ(-state.rSupFootZMP.z) * (pCOMRefW - state.pSupFootZMP);
	//Vector3<double> pCOMRef =Rfw.invert() * (pCOMRefW - state.pSupFootZMP);
	Vector3<double> realCOM = naoStructTmp.pCOM;
	Vector3<double> dCOM =  (pCOMRef - realCOM);
// 	MATLABHELP_PLOT(dCOM.y, "dCOMy");
// 	MATLABHELP_PLOT(pCOMRef.y, "pCOMRefy");
	//====Add ZMP mesaured feedback
// 	Vector3<double> zmpError = (lastState.pSupFootZMP - pRobotState->mZMP);
// 	dCOM -= Vector3<double>(zmpError.x * 0.01, zmpError.y * 0.1, 0);

	Vector3<double> refRBody(0,walkParam.torsoAngleY,0);
/*	refRBody +=  Vector3<double>(zmpError.y, zmpError.x * 0.1, 0);*/
	double gain = 1;//1.2, 1.8
	if(sup_mod == NaoConfig::SUPPORT_MODE_DOUBLE_LEFT || sup_mod == NaoConfig::SUPPORT_MODE_DOUBLE_RIGHT)
		gain = 1;
	Vector3<double> pBodyNext = dCOM *gain+ naoStructTmp.getPosition(NaoStructure::bodyLink, NaoStructure::Space_Supprot_Leg);

	double fRr, fRl;//z rotation of right and left foot
	if(sup_mod == NaoConfig::SUPPORT_MODE_LEFT || sup_mod == NaoConfig::SUPPORT_MODE_DOUBLE_LEFT){
		fRr = rSwgFoot2Sup.z;
		fRl = 0;
	}else{
		fRr = 0;
		fRl = rSwgFoot2Sup.z;
	}
	Vector3<double> equalHipAngles;
	double rHipYawPitchAngle;
	//search for best rHipYawPitchAngle, Feed angle relative to body...
	binarySearchforYawRollPitch(fRr, fRl, equalHipAngles, rHipYawPitchAngle);
	RotationMatrix brz  = RotationMatrix::getRotationY(walkParam.torsoAngleY);
	double zmpErrorY = pRobotState->mZMP.y;
	//brz.rotateX(-0.05*mRBody.x).rotateY(-0.05*mRBody.y);
	if(state.supmod == NaoConfig::SUPPORT_MODE_DOUBLE_LEFT || state.supmod == NaoConfig::SUPPORT_MODE_LEFT)
	{
		brz.rotateZ(equalHipAngles.z);
		Kinematics::calculateSafeLegJoints(walkingEngineOutput, NaoConfig::LegIDLeft, Vector3<double>(0,0,NaoConfig::getInstance()->FootHeight), RotationMatrix(), pBodyNext, brz,
			rHipYawPitchAngle, equalHipAngles.x, equalHipAngles.y);
	}else// if(state.supmod == NaoConfig::SUPPORT_MODE_DOUBLE_RIGHT)
	{
		brz.rotateZ(-equalHipAngles.z);
		Kinematics::calculateSafeLegJoints(walkingEngineOutput, NaoConfig::LegIDRight, Vector3<double>(0,0,NaoConfig::getInstance()->FootHeight), RotationMatrix(), pBodyNext, brz,
			rHipYawPitchAngle, equalHipAngles.x, equalHipAngles.y);
	}
	//======为消除身体的运动给游脚带来的影响, 先重新计算下Nao Structure
	naoStructTmp.setLinksJoints(walkingEngineOutput);
	naoStructTmp.uLink[NaoStructure::bodyLink].p = Vector3<double>(0,0,0);
	naoStructTmp.uLink[NaoStructure::bodyLink].R = RotationMatrix();
	Kinematics::execForwardKinematics(naoStructTmp, NaoStructure::bodyLink);
	Kinematics::recalcBodyPos2SupFoot(naoStructTmp, Vector3<double>(0,0,0), naoStructTmp.supportingMode);
	Kinematics::execForwardKinematics(naoStructTmp, NaoStructure::bodyLink);
	naoStructTmp.pCOM = Kinematics::calcCOM(naoStructTmp);
	//In case we get NAN or IND num.... print some thing and halt execution when run on robot!!
	ASSERT(naoStructTmp.pCOM == naoStructTmp.pCOM);
	//====== Swing Foot Joints================

	double supRotNowZ = 0;//TODO: error
	Vector3<double> psfoot = pSwgFoot2Sup;
	Vector3<double> psupfoot = state.pSupFootZMP;
	RotationMatrix frz = RotationMatrix::getRotationZ(rSwgFoot2Sup.z - supRotNowZ);
	Vector3<double> bodyAnglesNow = naoStructTmp.getRotAngles(NaoStructure::bodyLink, NaoStructure::Space_Supprot_Leg);
	if(state.supmod == NaoConfig::SUPPORT_MODE_LEFT || state.supmod == NaoConfig::SUPPORT_MODE_DOUBLE_LEFT)
	{
		Kinematics::calculateSafeLegJoints(walkingEngineOutput, NaoConfig::LegIDRight, psfoot, frz, naoStructTmp.uLink[NaoStructure::bodyLink].p, naoStructTmp.uLink[NaoStructure::bodyLink].R,
			rHipYawPitchAngle, equalHipAngles.x, equalHipAngles.y);
	}else{
		Kinematics::calculateSafeLegJoints(walkingEngineOutput, NaoConfig::LegIDLeft, psfoot, frz, naoStructTmp.uLink[NaoStructure::bodyLink].p, naoStructTmp.uLink[NaoStructure::bodyLink].R,
			rHipYawPitchAngle, equalHipAngles.x, equalHipAngles.y);
	}
	//===========
//	plotJointAngles(walkingEngineOutput, "O1_");
// 	if(state.supmod == NaoConfig::SUPPORT_MODE_LEFT && abs(zmpErrorY) > 0.01 && abs(zmpErrorY) < 0.025)
// 		walkingEngineOutput.angles[JointData::LAnkleRoll] += zmpErrorY * deg2rad(200);
// 	else if(state.supmod == NaoConfig::SUPPORT_MODE_RIGHT && abs(zmpErrorY) > 0.01 && abs(zmpErrorY) < 0.025)
// 		walkingEngineOutput.angles[JointData::RAnkleRoll] -= zmpErrorY * deg2rad(200);
//	plotJointAngles(walkingEngineOutput, "O2_");
	//=========LPF smoother=================
	if(Use_Smooth_Filter)
		smoothJoints(walkingEngineOutput, lastWalkOoutput);
	lastWalkOoutput = walkingEngineOutput;
	//===Compensate HipRoll When Single Supproting====//
	if(walkParam.useHipRollCompensation && (executingCmd.speed.translation.x != 0.0) && (walkStatus == WalkTypeBase::running ))
	{		
		compensateHipRoll(istep, sup_mod, walkParam,walkingEngineOutput);
	}
	if((walkParam.useHipRollCompensationRight&&(executingCmd.speed.translation.y < 0.0)||walkParam.useHipRollCompensationLeft&&(executingCmd.speed.translation.y > 0.0)) && (walkStatus == WalkTypeBase::running ))
	{	
		compensateHipRollindependent(istep, sup_mod, walkParam,walkingEngineOutput,executingCmd);
	}
	finishFrame();     
	//======Print something=========
	Vector3<double> pBodyRefW = RotationMatrix(state.rSupFootZMP.x, state.rSupFootZMP.y, state.rSupFootZMP.z) *pBodyNext + state.pSupFootZMP;

	// TODO: Check direction of com and acc
	//Vector3<double> comW = Rfw * naoStructure.getCoM(NaoStructure::Space_Supprot_Leg)+ lastState.pSupFootZMP;
	Vector3<double> comWSup = naoStructure.getCoM(NaoStructure::Space_Supprot_Leg) + lastState.pSupFootZMP;
	/*MATLABHELP_PLOT(pCOMRefW.x, "pCOMRefWx");
	MATLABHELP_PLOT(pCOMRefW.y, "pCOMRefWy");
	MATLABHELP_PLOT(pCOMRefW.z, "pCOMRefWz");*/
	//MATLABHELP_PLOT(outputPC.v.x, "CoMRefWvx");
	//MATLABHELP_PLOT(outputPC.v.y, "CoMRefWvy");
	//MATLABHELP_PLOT(outputPC.v.z, "CoMRefWvz");
	//MATLABHELP_PLOT(outputPC.a.x, "CoMRefWax");
	//MATLABHELP_PLOT(outputPC.a.y, "CoMRefWay");
	//MATLABHELP_PLOT(outputPC.a.z, "CoMRefWaz");

	//MATLABHELP_PLOT(pBodyRefW.x, "pBodyWx");
	//MATLABHELP_PLOT(pBodyRefW.y, "pBodyWy");
	//MATLABHELP_PLOT(pBodyRefW.z, "pBodyWz");
	/*MATLABHELP_PLOT(comW.x, "comWx");
	MATLABHELP_PLOT(comW.y, "comWy");
	MATLABHELP_PLOT(comW.z, "comWz");*/
	//MATLABHELP_PLOT(comWSup.x, "comWSupx");
	//MATLABHELP_PLOT(comWSup.y, "comWSupy");


	//MATLABHELP_PLOT(rSwgFoot2Sup.z, "swg2Foot");

	//MATLABHELP_PLOT(pSwgFootW.x, "pSwgFootx");
	//MATLABHELP_PLOT(pSwgFootW.y, "pSwgFooty");
	//MATLABHELP_PLOT(pSwgFootW.z, "pSwgFootz");
	//MATLABHELP_PLOT(rSwgFootW.x, "rSwgFootx");
	//MATLABHELP_PLOT(rSwgFootW.y, "rSwgFooty");
	//MATLABHELP_PLOT(rSwgFootW.z, "rSwgFootz");

	//Vector3<double> lfoot2B = naoStructTmp.getPosition(NaoStructure::lFootLink, NaoStructure::Space_Body);
	////Vector3<double> rfoot2B = naoStructTmp.getPosition(NaoStructure::rFootLink, NaoStructure::Space_Body);
	//MATLABHELP_PLOT(lfoot2B.x, "lfoot2Bx");
	//MATLABHELP_PLOT(lfoot2B.y, "lfoot2By");
	//MATLABHELP_PLOT(lfoot2B.z, "lfoot2Bz");

	//ZMP measured from LIPM
	/*MATLABHELP_PLOT(zmpW.x, "zmpWx");
	MATLABHELP_PLOT(zmpW.y, "zmpWy");
	MATLABHELP_PLOT(zmpW.z, "zmpWz");*/

	//// zmp Ideal
	//Vector3<double> zmpWIdeal = outputPC.p -  outputPC.a * pCOMRefW.z / 9.81;
	//MATLABHELP_PLOT(zmpWIdeal.x, "zmpWIdealx");
	//MATLABHELP_PLOT(zmpWIdeal.y, "zmpWIdealy");
	//cop
	MDEBUG_SAVE(MDebug::idPreviewState,state)
	MDEBUG_SAVE(MDebug::idRefCOM, pCOMRefW)
    MDEBUG_SAVE(MDebug::idRealCOM, comW)
    MDEBUG_SAVE(MDebug::idBodyPos, pBodyRefW)
    //MDEBUG_SAVE(MDebug::idBodyAngles, )

	Vector3<double> copW;
	const CoP& LCoP = pRobotState->mCoPL;
	const CoP& RCoP = pRobotState->mCoPR;

	if(naoStructure.supportingMode == NaoConfig::SUPPORT_MODE_LEFT || naoStructure.supportingMode == NaoConfig::SUPPORT_MODE_DOUBLE_LEFT){
		copW =  LCoP.p* LCoP.pressure + (naoStructure.getRotationMatrix(NaoStructure::rFootLink) * RCoP.p 
			+naoStructTmp.getPosition(NaoStructure::rFootLink, NaoStructure::Space_Supprot_Leg)) * RCoP.pressure;
		copW /= (LCoP.pressure + RCoP.pressure);
	}else{
		copW =  RCoP.p* RCoP.pressure + (naoStructure.getRotationMatrix(NaoStructure::lFootLink) * LCoP.p 
			+naoStructTmp.getPosition(NaoStructure::lFootLink, NaoStructure::Space_Supprot_Leg)) * LCoP.pressure;
		copW /= (LCoP.pressure + RCoP.pressure);
	}
	copW = RotationMatrix(0, 0, lastState.rSupFootZMP.z) *copW + lastState.pSupFootZMP;
	/*MATLABHELP_PLOT(copW.x, "copWx");
	MATLABHELP_PLOT(copW.y, "copWy");
	MATLABHELP_PLOT(copW.z, "copWz");

	MATLABHELP_PLOT(pRobotState->groundContactLeft.contact?0.75:0.25, "isContactLeft");
	MATLABHELP_PLOT(pRobotState->groundContactRight.contact?0.75:0.25, "isContactRight");*/
	lastState = state;
	lastCoMW = comW;
}
Esempio n. 16
0
bool TeamDataProvider::handleMessage(InMessage& message)
{
  /*
  The robotNumber and the three flags hasGroundContact, isUpright and isPenalized should always be updated.
   */
  switch(message.getMessageID())
  {
    case idNTPHeader:
      VERIFY(ntp.handleMessage(message));
      timeStamp = ntp.receiveTimeStamp;
      return false;
    case idNTPIdentifier:
    case idNTPRequest:
    case idNTPResponse:
      return ntp.handleMessage(message);

    case idRobot:
      message.bin >> robotNumber;
      if(robotNumber != theRobotInfo.number)
        if(robotNumber >= TeamMateData::firstPlayer && robotNumber < TeamMateData::numOfPlayers)
          theTeamMateData.timeStamps[robotNumber] = timeStamp;
      return true;

    case idGroundTruthBallModel:
    {
      Vector2<> position;
      message.bin >> theGroundTruthBallModel.timeWhenLastSeen >> position;
      REMOTE_TO_LOCAL_TIME(theGroundTruthBallModel.timeWhenLastSeen);
      if(theOwnTeamInfo.teamColor == TEAM_BLUE)
        position *= -1;
      theGroundTruthBallModel.lastPerception = theGroundTruthRobotPose.invert() * position;
      theGroundTruthBallModel.estimate.position = theGroundTruthBallModel.lastPerception;
    }
      return true;

    case idGroundTruthRobotPose:
    {
      char teamColor,
          id;
      unsigned timeStamp;
      Pose2D robotPose;
      message.bin >> teamColor >> id >> timeStamp >> robotPose;
      if(teamColor == (int) theOwnTeamInfo.teamColor && id == theRobotInfo.number)
      {
        if(theOwnTeamInfo.teamColor == TEAM_BLUE)
          robotPose = Pose2D(pi) + robotPose;
        (Pose2D&) theGroundTruthRobotPose = robotPose;
      }
    }
      return true;

    case idTeamMateIsPenalized:
      if(robotNumber != theRobotInfo.number)
        if(robotNumber >= TeamMateData::firstPlayer && robotNumber < TeamMateData::numOfPlayers)
          message.bin >> theTeamMateData.isPenalized[robotNumber];
      return true;

    case idTeamMateHasGroundContact:
      if(robotNumber != theRobotInfo.number)
        if(robotNumber >= TeamMateData::firstPlayer && robotNumber < TeamMateData::numOfPlayers)
        {
          message.bin >> theTeamMateData.hasGroundContact[robotNumber];
          // This is a potentially evil quick workaround that should be replaced by a better handling of ground contacts of team mates
          // at many different places in our code! For a detailed problem description, ask Tim.
          if(!theTeamMateData.hasGroundContact[robotNumber])
            theTeamMateData.hasGroundContact[robotNumber] = theFrameInfo.getTimeSince(theTeamMateData.timeLastGroundContact[robotNumber]) < 2000;
        }
      return true;

    case idTeamMateIsUpright:
      if(robotNumber != theRobotInfo.number)
        if(robotNumber >= TeamMateData::firstPlayer && robotNumber < TeamMateData::numOfPlayers)
          message.bin >> theTeamMateData.isUpright[robotNumber];
      return true;

    case idTeamMateTimeSinceLastGroundContact:
      if(robotNumber != theRobotInfo.number)
        if(robotNumber >= TeamMateData::firstPlayer && robotNumber < TeamMateData::numOfPlayers)
        {
          message.bin >> theTeamMateData.timeLastGroundContact[robotNumber];
          REMOTE_TO_LOCAL_TIME(theTeamMateData.timeLastGroundContact[robotNumber]);
        }