00001
00002
00003
00004
00005
00006
00007
00008 #include "GT2004BallLocator.h"
00009 #include "Tools/Debugging/Debugging.h"
00010 #include "Tools/Actorics/RobotDimensions.h"
00011 #include "Tools/FieldDimensions.h"
00012 #include "Platform/SystemCall.h"
00013 #include "Tools/Debugging/DebugDrawings.h"
00014 #include "Tools/Debugging/GT2004BallLocatorDebugData.h"
00015 #include "GT2004ProcessModels/FixedPositionModel.h"
00016 #include "GT2004ProcessModels/ConstantSpeedModel.h"
00017
00018 double GT2004BallLocator::dFieldDiagonalLength =
00019 1.2*sqrt((2.0*xPosOpponentGoal)*(2.0*xPosOpponentGoal) +
00020 (2.0*yPosLeftFlags)*(2.0*yPosLeftFlags));
00021
00022 GT2004BallLocator::GT2004BallLocator(BallLocatorInterfaces& interfaces)
00023 : BallLocator(interfaces)
00024
00025 {
00026
00027 bSendProcessModelStates = false;
00028 ballWasSeen = false;
00029 ballWasSeenInLastImage = false;
00030 x_abs = 0.0;
00031 y_abs = 0.0;
00032 x_rel = 0.0;
00033 y_rel = 0.0;
00034 vx_abs = 0.0;
00035 vy_abs = 0.0;
00036 vx_rel = 0.0;
00037 vy_rel = 0.0;
00038
00039
00040
00041
00042
00043
00044
00045 addModel(new KalmanConstantSpeedModel);
00046
00047
00048
00049 freshDefend = true;
00050 ballSensedPos.x = 0;
00051 ballSensedPos.y = 0;
00052 ballSensedTime = 0;
00053 ballSensedRelPos.x = 0;
00054 ballSensedRelPos.y = 0;
00055 last_seen_x_rel = 0;
00056 last_seen_y_rel = 0;
00057 }
00058
00059 GT2004BallLocator::~GT2004BallLocator()
00060 {
00061
00062 destroyModels();
00063 }
00064
00065 void GT2004BallLocator::execute()
00066 {
00067 Player::teamColor ownColor = getPlayer().getTeamColor();
00068 colorClass opponentGoalColor = ownColor == Player::red ? skyblue : yellow;
00069 ballModel.seen.ballInFrontOfOpponentGoal = false;
00070 if(landmarksPercept.numberOfGoals > 0)
00071 {
00072 double angleToBall = ballPercept.getAngleSizeBased();
00073 double ballDistance = ballPercept.getDistanceSizeBased();
00074 if(
00075 landmarksPercept.goals[0].color == opponentGoalColor &&
00076 ballPercept.ballWasSeen &&
00077 landmarksPercept.goals[0].x.min < angleToBall &&
00078 angleToBall < landmarksPercept.goals[0].x.max &&
00079 ballDistance < 1100
00080 )
00081 {
00082 ballModel.seen.ballInFrontOfOpponentGoal = true;
00083 }
00084 }
00085
00086 static bool prevCameraMatrixUninitialized = true;
00087 if (prevCameraMatrixUninitialized && cameraMatrix.frameNumber != 0)
00088 {
00089 prevCameraMatrix = cameraMatrix;
00090 prevCameraMatrixUninitialized = false;
00091 }
00092
00093 determineNumberOfImagesWith_WithoutBall();
00094
00095
00096 double ballMeasurementError = 159.1 * tan(openingAngleHeight_ERS210/2)/176*3;
00097 ballModel.seen.distanceError =
00098 ballMeasurementError *
00099 ballPercept.getDistance() * ballPercept.getDistance() /
00100 (ballRadius * 159.1 );
00101 ballModel.seen.angleError = 0.05;
00102
00103 compensateOdometry();
00104
00105
00106 if (ballPercept.ballWasSeen)
00107 {
00108 handleSeenBall();
00109 ballWasSeen = true;
00110 }
00111 else
00112 {
00113 handleUnseenBall();
00114 ballWasSeen = false;
00115 }
00116
00117
00118 ballModel.frameNumber = cameraMatrix.frameNumber;
00119
00120
00121 setBallState();
00122
00123
00124
00125 if (bSendProcessModelStates)
00126 sendProcessModelStates();
00127
00128
00129 drawBallPosition();
00130
00131 prevCameraMatrix = cameraMatrix;
00132
00133
00134 if(ballPercept.ballWasSeen)
00135 {
00136 Vector2<double> ballOffset;
00137 ballPercept.getOffset(ballOffset);
00138
00139 lastBallSeen = ballOffset;
00140 }
00141 else
00142 {
00143 lastBallSeen = (lastRobotOdometry + Pose2D(lastBallSeen) - odometryData).translation;
00144 }
00145
00146 ballModel.seen =
00147 Geometry::relative2FieldCoord(robotPose, lastBallSeen.x, lastBallSeen.y);
00148
00149 lastRobotOdometry = odometryData;
00150 }
00151
00152 void GT2004BallLocator::handleSeenBall()
00153 {
00154 int i;
00155
00156
00157 if (!ballWasSeen)
00158 ballModel.seen.timeWhenFirstSeenConsecutively
00159 = SystemCall::getCurrentSystemTime();
00160
00161
00162 double time = (double)SystemCall::getCurrentSystemTime() / 1000.0;
00163
00164
00165 Vector2<double> ballOffset;
00166
00167 ballPercept.getOffset(ballOffset);
00168
00169
00170 if (isNonSensePos(ballOffset.x, ballOffset.y))
00171 {
00172 handleUnseenBall();
00173 return;
00174 }
00175
00176
00177 x_rel = ballOffset.x / 1000.0;
00178 y_rel = ballOffset.y / 1000.0;
00179
00180 Vector3<double> vectorInDirectionOfViewCamera(1,0,0);
00181 Vector3<double> vectorInDirectionOfViewWorld, vectorInDirectionOfViewWorldOld;
00182 vectorInDirectionOfViewWorld = cameraMatrix.rotation * vectorInDirectionOfViewCamera;
00183 vectorInDirectionOfViewWorldOld = prevCameraMatrix.rotation * vectorInDirectionOfViewCamera;
00184 long frameNumber = cameraMatrix.frameNumber,
00185 prevFrameNumber = prevCameraMatrix.frameNumber;
00186 const RobotDimensions& r = getRobotConfiguration().getRobotDimensions();
00187 double timeDiff = (frameNumber - prevFrameNumber) * r.motionCycleTime;
00188 Vector2<double> currentOnGround(vectorInDirectionOfViewWorld.x, vectorInDirectionOfViewWorld.y),
00189 oldOnGround(vectorInDirectionOfViewWorldOld.x, vectorInDirectionOfViewWorldOld.y);
00190 currentOnGround.normalize();
00191 oldOnGround.normalize();
00192 double panningVelocity = 0;
00193 if (timeDiff > 0)
00194 {
00195 double cosAng = currentOnGround*oldOnGround;
00196 if (cosAng > 1.0)
00197 cosAng = 1.0;
00198 else
00199 if (cosAng < -1.0)
00200 cosAng = -1.0;
00201 panningVelocity = fabs(normalize(acos(cosAng))/timeDiff);
00202 }
00203
00204 double liklihoodSum = 0.0;
00205 try
00206 {
00207 for (i = 0; i < (int)kalmanModels.size(); ++i)
00208 {
00209
00210 if (!kalmanModels[i]->useModel())
00211 continue;
00212
00213
00214 kalmanModels[i]->adapt(lastOdometry, odometryData);
00215
00216
00217 kalmanUpdateResults[i] = kalmanModels[i]->update(time, x_rel, y_rel, robotPose, panningVelocity);
00218 liklihoodSum += kalmanUpdateResults[i].liklihood;
00219
00220
00221 if (kalmanModels[i]->isNonSensePos(kalmanUpdateResults[i].state.x,
00222 kalmanUpdateResults[i].state.y))
00223 kalmanModels[i]->reset();
00224 }
00225 }
00226 catch (...)
00227 {
00228
00229 OUTPUT(idText, text,
00230 "Unknown Exception in GT2004BallLocator::handleSeenBall");
00231 setUnknownResult();
00232 return;
00233 }
00234 lastOdometry = odometryData;
00235
00236
00237 if (liklihoodSum != 0.0)
00238 {
00239 x_rel = 0.0;
00240 y_rel = 0.0;
00241 vx_rel = 0.0;
00242 vy_rel = 0.0;
00243 double probability;
00244
00245
00246
00247
00248
00249
00250
00251 for (i = 0; i < (int)kalmanModels.size(); ++i)
00252 {
00253 if (!kalmanModels[i]->useModel())
00254 continue;
00255
00256 std::vector<KalmanUpdateResult>::iterator pos =
00257 kalmanUpdateResults.begin() + i;
00258 if (pos->liklihood != 0.0)
00259 probability = pos->liklihood = pos->liklihood / liklihoodSum;
00260 else
00261 probability = 0.0;
00262 x_rel += pos->state.x * probability;
00263 y_rel += pos->state.y * probability;
00264 vx_rel += pos->state.vx * probability;
00265 vy_rel += pos->state.vy * probability;
00266 }
00267
00268
00269 x_rel *= 1000.0;
00270 y_rel *= 1000.0;
00271 vx_rel *= 1000.0;
00272 vy_rel *= 1000.0;
00273
00274
00275 last_seen_x_rel = x_rel;
00276 last_seen_y_rel = y_rel;
00277
00278
00279 ballOffset = Geometry::relative2FieldCoord(robotPose, x_rel, y_rel);
00280 x_abs = ballOffset.x;
00281 y_abs = ballOffset.y;
00282 vx_abs = vx_rel*cos(robotPose.rotation) + vy_rel*sin(robotPose.rotation);
00283 vy_abs = -vx_rel*sin(robotPose.rotation) + vy_rel*cos(robotPose.rotation);
00284
00285
00286 ballModel.seen = ballOffset;
00287
00288
00289 ballModel.seen.speed.x = vx_rel;
00290 ballModel.seen.speed.y = vy_rel;
00291
00292
00293 ballModel.propagated.timeOfObservation = SystemCall::getCurrentSystemTime();
00294 ballModel.propagated.x = ballOffset.x;
00295 ballModel.propagated.y = ballOffset.y;
00296 ballModel.propagated.positionWhenLastObserved = ballOffset;
00297
00298
00299 ballModel.propagated.observedSpeed.x = vx_rel;
00300 ballModel.propagated.observedSpeed.y = vy_rel;
00301 }
00302 else
00303 {
00304
00305
00306
00307 x_rel *= 1000.0;
00308 y_rel *= 1000.0;
00309
00310
00311 ballOffset = Geometry::relative2FieldCoord(robotPose, x_rel, y_rel);
00312 x_abs = ballOffset.x;
00313 y_abs = ballOffset.y;
00314 vx_rel = 0.0;
00315 vy_rel = 0.0;
00316 vx_abs = 0.0;
00317 vy_abs = 0.0;
00318
00319
00320 ballModel.seen = ballOffset;
00321 ballModel.seen.speed.x = 0.0;
00322 ballModel.seen.speed.y = 0.0;
00323 }
00324
00325
00326 ballModel.seen.timeWhenLastSeen = SystemCall::getCurrentSystemTime();
00327 ballModel.seen.timeUntilSeenConsecutively = SystemCall::getCurrentSystemTime();
00328 }
00329
00330 void GT2004BallLocator::handleUnseenBall()
00331 {
00332
00333
00334
00335
00336 double time = (double)SystemCall::getCurrentSystemTime() / 1000.0;
00337
00338 int i;
00339 double liklihoodSum = 0.0;
00340 try
00341 {
00342 for (i = 0; i < (int)kalmanModels.size(); ++i)
00343 {
00344
00345 if (!kalmanModels[i]->useModel())
00346 continue;
00347
00348
00349 kalmanModels[i]->adapt(lastOdometry, odometryData);
00350
00351
00352 kalmanPredictResults[i] = kalmanModels[i]->predict(time);
00353 liklihoodSum += kalmanPredictResults[i].liklihood;
00354
00355
00356 if (kalmanModels[i]->isNonSensePos(kalmanPredictResults[i].state.x,
00357 kalmanPredictResults[i].state.y))
00358 kalmanModels[i]->reset();
00359 }
00360 }
00361 catch (...)
00362 {
00363
00364 OUTPUT(idText, text,
00365 "Unknown Exception in GT2004BallLocator::handleUnseenBall");
00366 setUnknownResult();
00367 return;
00368 }
00369 lastOdometry = odometryData;
00370
00371
00372 if (liklihoodSum != 0.0)
00373 {
00374 x_rel = 0.0;
00375 y_rel = 0.0;
00376 vx_rel = 0.0;
00377 vy_rel = 0.0;
00378 double probability;
00379
00380
00381
00382
00383
00384
00385
00386 for (i = 0; i < (int)kalmanModels.size(); ++i)
00387 {
00388 if (!kalmanModels[i]->useModel())
00389 continue;
00390
00391 std::vector<KalmanPredictResult>::iterator pos =
00392 kalmanPredictResults.begin() + i;
00393
00394 if (pos->liklihood != 0.0)
00395 probability = pos->liklihood = pos->liklihood / liklihoodSum;
00396 else
00397 probability = 0.0;
00398 x_rel += pos->state.x * probability;
00399 y_rel += pos->state.y * probability;
00400 vx_rel += pos->state.vx * probability;
00401 vy_rel += pos->state.vy * probability;
00402 }
00403
00404
00405 x_rel *= 1000.0;
00406 y_rel *= 1000.0;
00407 vx_rel *= 1000.0;
00408 vy_rel *= 1000.0;
00409
00410
00411 Vector2<double> ballOffset =
00412 Geometry::relative2FieldCoord(robotPose, x_rel, y_rel);
00413 x_abs = ballOffset.x;
00414 y_abs = ballOffset.y;
00415 vx_abs = vx_rel*cos(robotPose.rotation) + vy_rel*sin(robotPose.rotation);
00416 vy_abs = -vx_rel*sin(robotPose.rotation) + vy_rel*cos(robotPose.rotation);
00417
00418
00419 ballModel.propagated.x = ballOffset.x;
00420 ballModel.propagated.y = ballOffset.y;
00421 }
00422 else
00423 {
00424
00425
00426
00427 double dt = (SystemCall::getCurrentSystemTime() -
00428 ballModel.propagated.timeOfObservation) / 1000.0;
00429
00430
00431 ballModel.propagated.x =
00432 ballModel.propagated.positionWhenLastObserved.x +
00433 ballModel.propagated.observedSpeed.x*dt;
00434 ballModel.propagated.y =
00435 ballModel.propagated.positionWhenLastObserved.y +
00436 ballModel.propagated.observedSpeed.y*dt;
00437 }
00438
00439
00440 Vector2<double> ballOnField =
00441 Geometry::relative2FieldCoord(robotPose, last_seen_x_rel, last_seen_y_rel);
00442 ballModel.seen.x = ballOnField.x;
00443 ballModel.seen.y = ballOnField.y;
00444 }
00445
00446 void GT2004BallLocator::compensateOdometry()
00447 {
00448 Vector2<double> lastBallSeenRelative
00449 = (lastOdometry +
00450 Pose2D(last_seen_x_rel,last_seen_y_rel) -
00451 odometryData).translation;
00452 last_seen_x_rel = lastBallSeenRelative.x;
00453 last_seen_y_rel = lastBallSeenRelative.y;
00454
00455
00456 }
00457
00458 void GT2004BallLocator::setBallState()
00459 {
00460 ballModel.ballState.reset();
00461
00462
00463 if (vx_rel > -50.0)
00464 return;
00465
00466
00467
00468 ballModel.ballState.projectedDistanceOnYAxis = y_rel - (vy_rel/vx_rel)*x_rel;
00469
00470 ballModel.ballState.timeBallCrossesYAxis = (long)(ballModel.ballState.projectedDistanceOnYAxis / vx_rel) * 1000;
00471
00472
00473 double dist = sqrt(x_rel*x_rel + y_rel*y_rel);
00474 if (dist > 1000.0)
00475 return;
00476
00477 if ((ballModel.ballState.projectedDistanceOnYAxis < -100.0)
00478 && (ballModel.ballState.projectedDistanceOnYAxis > -500.0))
00479 {
00480 ballModel.ballState.ballRollsByRight = true;
00481 }
00482 else if ((ballModel.ballState.projectedDistanceOnYAxis > 100.0)
00483 && (ballModel.ballState.projectedDistanceOnYAxis < 500.0))
00484 {
00485 ballModel.ballState.ballRollsByLeft = true;
00486 }
00487 else if ((ballModel.ballState.projectedDistanceOnYAxis >= -100.0)
00488 && (ballModel.ballState.projectedDistanceOnYAxis <= 100.0))
00489 {
00490 ballModel.ballState.ballRollsTowardsRobot = true;
00491 }
00492 }
00493
00494 void GT2004BallLocator::setBallStateV2()
00495 {
00496
00497
00498 static int const defendZone1Border = 550;
00499 static int const defendZone2Border = 1000;
00500 static int const defendZone3Border = 1000;
00501
00502 static double const ballHasMovedThreshold = 20.0;
00503
00504
00505
00506
00507 static unsigned long const speedTrigger = 1000;
00508
00509
00510
00511
00512
00513
00514
00515
00516
00517
00518
00519
00520
00521
00522
00523
00524
00525
00526
00527
00528
00529
00530 ballModel.ballState.reset();
00531
00532
00533 double ballRelDist =
00534 Geometry::distanceTo(robotPose.getPose(),ballModel.seen);
00535
00536 Vector2<double> ballRelPos;
00537 ballRelPos.x = ballRelDist *
00538 cos(Geometry::angleTo(robotPose.getPose(),ballModel.seen));
00539 ballRelPos.y = ballRelDist *
00540 sin(Geometry::angleTo(robotPose.getPose(),ballModel.seen));
00541
00542 double ballRelAngle = toDegrees(Geometry::angleTo(robotPose.getPose(),
00543 ballModel.seen));
00544
00545 if ((ballRelDist > (defendZone1Border+100)) && (ballRelDist < defendZone2Border))
00546 {
00547 ballSensedPos = ballModel.seen;
00548
00549 ballSensedRelPos = ballRelPos;
00550 if ((ballRelAngle > -90) && (ballRelAngle <= 90))
00551 ballSensedTime = SystemCall::getCurrentSystemTime();
00552 }
00553
00554 if (ballRelDist > defendZone3Border) {
00555 freshDefend = true;
00556 }
00557
00558 double side;
00559 side = ballSensedRelPos.y + (ballSensedRelPos.x / (ballRelPos.x - ballSensedRelPos.x))*(ballRelPos.y - ballSensedRelPos.y);
00560 ballModel.ballState.projectedDistanceOnYAxis = side;
00561 ballModel.ballState.timeBallCrossesYAxis = (long)(ballModel.ballState.projectedDistanceOnYAxis / vx_rel) * 1000;
00562 if ( (ballRelAngle > -90)
00563 && (ballRelAngle < 90)
00564 && (ballRelDist < defendZone1Border)
00565 && (freshDefend == true))
00566 {
00567 freshDefend = false;
00568 unsigned long travelTime = SystemCall::getCurrentSystemTime() - ballSensedTime;
00569 double travelDist = (ballSensedPos - ballModel.seen).abs();
00570 if ( (travelTime < speedTrigger)
00571 && (ballSensedRelPos.x - ballRelPos.x >= 1)
00572 && (travelDist > ballHasMovedThreshold)
00573 )
00574 {
00575 if ((side > -150) && (side < 150))
00576 ballModel.ballState.ballRollsTowardsRobot = true;
00577 else if ((side > -500) && (side <= -150))
00578 ballModel.ballState.ballRollsByRight = true;
00579 else if ((side >= 150) && (side < 500))
00580 ballModel.ballState.ballRollsByLeft = true;
00581 }
00582 }
00583
00584
00585
00586 }
00587
00588 void GT2004BallLocator::setUnknownResult()
00589 {
00590
00591 ballModel.propagated.x = x_abs;
00592 ballModel.propagated.y = y_abs;
00593 }
00594
00595 bool GT2004BallLocator::isNonSensePos(double x, double y)
00596 {
00597 double dist = sqrt(x*x + y*y);
00598 if (dist > dFieldDiagonalLength)
00599 return true;
00600 else
00601 return false;
00602 }
00603
00604 void GT2004BallLocator::addModel(KalmanProcessModelBase* pModel)
00605 {
00606
00607 kalmanModels.push_back(pModel);
00608 kalmanUpdateResults.push_back(KalmanUpdateResult());
00609 kalmanPredictResults.push_back(KalmanPredictResult());
00610 }
00611
00612 void GT2004BallLocator::destroyModels()
00613 {
00614
00615 std::vector<KalmanProcessModelBase*>::iterator pos;
00616 for (pos = kalmanModels.begin(); pos != kalmanModels.end(); ++pos)
00617 delete *pos;
00618 }
00619
00620 bool GT2004BallLocator::handleMessage(InMessage& message)
00621 {
00622
00623 if (message.getMessageID() != idGT2004BallLocatorData)
00624 return false;
00625
00626
00627 char action;
00628 message.bin >> action;
00629
00630 switch (action)
00631 {
00632 case GT2004BallLocatorDebugData::idRequestParameters:
00633 {
00634
00635
00636
00637 getDebugOut().bin << (char)GT2004BallLocatorDebugData::idSendingParameters
00638 << kalmanModels.size();
00639
00640
00641 std::vector<KalmanProcessModelBase*>::iterator pos;
00642 for (pos = kalmanModels.begin(); pos != kalmanModels.end(); ++pos)
00643 (*pos)->toStream(getDebugOut().bin);
00644
00645
00646 getDebugOut().finishMessage(idGT2004BallLocatorData);
00647 }
00648 return true;
00649
00650 case GT2004BallLocatorDebugData::idSetParameters:
00651 {
00652
00653
00654
00655 int modelIndex;
00656 message.bin >> modelIndex;
00657
00658
00659 kalmanModels[modelIndex]->fromStream(message.bin);
00660 }
00661 return true;
00662 }
00663
00664
00665 message.resetReadPosition();
00666 return false;
00667 }
00668
00669 void GT2004BallLocator::sendProcessModelStates()
00670 {
00671
00672 OutMessage& stream = getDebugOut();
00673
00674
00675 stream.bin << (char)GT2004BallLocatorDebugData::idFilterState;
00676
00677
00678 stream.bin << SystemCall::getCurrentSystemTime();
00679
00680
00681 stream.bin << robotPose;
00682
00683
00684
00685 stream.bin << x_rel << y_rel;
00686 stream.bin << vx_rel << vy_rel;
00687
00688
00689 stream.bin << (char)ballWasSeen;
00690
00691
00692 stream.bin << kalmanUpdateResults.size();
00693
00694
00695 std::vector<KalmanUpdateResult>::const_iterator urpos;
00696 std::vector<KalmanPredictResult>::const_iterator prpos;
00697 std::vector<KalmanProcessModelBase*>::const_iterator mpos;
00698 for (mpos = kalmanModels.begin(),
00699 urpos = kalmanUpdateResults.begin(),
00700 prpos = kalmanPredictResults.begin();
00701 mpos != kalmanModels.end();
00702 ++mpos, ++urpos, ++prpos)
00703 {
00704
00705 if (ballWasSeen)
00706 {
00707
00708 stream.bin << urpos->state.x*1000.0 << urpos->state.y*1000.0;
00709
00710 stream.bin << urpos->state.vx*1000.0 << urpos->state.vy*1000.0;
00711
00712 stream.bin << urpos->liklihood;
00713 }
00714 else
00715 {
00716
00717 stream.bin << prpos->state.x*1000.0 << prpos->state.y*1000.0;
00718
00719 stream.bin << prpos->state.vx*1000.0 << prpos->state.vy*1000.0;
00720
00721 stream.bin << prpos->liklihood;
00722 }
00723
00724
00725 int n = (*mpos)->getStateDim();
00726 stream.bin << n;
00727
00728
00729 double* M = new double[n*n];
00730 (*mpos)->getP(M);
00731 int i;
00732 for (i = 0; i < n*n; ++i)
00733 stream.bin << M[i];
00734 delete [] M;
00735 }
00736
00737
00738 stream.finishMessage(idGT2004BallLocatorData);
00739 }
00740
00741 void GT2004BallLocator::drawBallPosition()
00742 {
00743
00744 if (ballWasSeen)
00745 {
00746 CIRCLE(ballLocatorField, x_abs, y_abs, 90, 3, 0, Drawings::orange);
00747 LINE(ballLocatorField, x_abs, y_abs,
00748 x_abs + vx_abs*3, y_abs + vy_abs*3,
00749 3, 0, Drawings::orange);
00750 }
00751 else
00752 {
00753 CIRCLE(ballLocatorField, x_abs, y_abs, 90, 3, 0, Drawings::blue);
00754 LINE(ballLocatorField, x_abs, y_abs,
00755 x_abs + vx_abs*3, y_abs + vy_abs*3,
00756 3, 0, Drawings::blue);
00757 }
00758
00759
00760 std::vector<KalmanUpdateResult>::const_iterator urpos;
00761 std::vector<KalmanPredictResult>::const_iterator prpos;
00762 std::vector<KalmanProcessModelBase*>::const_iterator mpos;
00763 for (mpos = kalmanModels.begin(),
00764 urpos = kalmanUpdateResults.begin(),
00765 prpos = kalmanPredictResults.begin();
00766 mpos != kalmanModels.end();
00767 ++mpos, ++urpos, ++prpos)
00768 {
00769
00770 if (ballWasSeen)
00771 {
00772
00773 Vector2<double> ballOffset =
00774 Geometry::relative2FieldCoord(robotPose, urpos->state.x*1000.0,
00775 urpos->state.y*1000.0);
00776 CIRCLE(ballLocatorField, ballOffset.x, ballOffset.y,
00777 60, 2, 0, Drawings::yellowOrange);
00778 }
00779 else
00780 {
00781
00782 Vector2<double> ballOffset =
00783 Geometry::relative2FieldCoord(robotPose, prpos->state.x*1000.0,
00784 prpos->state.y*1000.0);
00785 CIRCLE(ballLocatorField, ballOffset.x, ballOffset.y,
00786 60, 2, 0, Drawings::skyblue);
00787 }
00788 }
00789
00790 DEBUG_DRAWING_FINISHED(ballLocatorField);
00791 }
00792
00793 void GT2004BallLocator::determineNumberOfImagesWith_WithoutBall()
00794 {
00795 unsigned char diff = 1;
00796 switch (lastFrameNumber)
00797 {
00798 case 4: diff = 1; break;
00799 case 5: diff = 1; break;
00800 case 8: diff = 2; break;
00801 case 9: diff = 2; break;
00802 case 12: diff = 3; break;
00803 case 13: diff = 3; break;
00804 case 16: diff = 4; break;
00805 case 17: diff = 4; break;
00806 case 18: diff = 4; break;
00807 }
00808
00809
00810 if(ballWasSeenInLastImage)
00811 {
00812 if(!ballPercept.ballWasSeen)
00813 {
00814 ballModel.numberOfImagesWithoutBallPercept = 1;
00815 }
00816 else
00817 {
00818 ballModel.numberOfImagesWithBallPercept += diff;
00819 }
00820 }
00821 else
00822 {
00823 if(ballPercept.ballWasSeen)
00824 {
00825 ballModel.numberOfImagesWithBallPercept = 1;
00826 }
00827 else
00828 {
00829 ballModel.numberOfImagesWithoutBallPercept += diff;
00830 }
00831 }
00832 ballModel.ballWasSeen = ballPercept.ballWasSeen;
00833 ballWasSeenInLastImage = ballPercept.ballWasSeen;
00834 }
00835
00836
00837
00838
00839
00840
00841
00842
00843
00844
00845
00846
00847
00848
00849
00850
00851
00852
00853
00854
00855
00856
00857
00858
00859
00860
00861
00862
00863
00864
00865
00866
00867
00868
00869
00870
00871
00872
00873
00874
00875
00876
00877
00878
00879
00880
00881
00882
00883
00884
00885
00886
00887
00888
00889
00890
00891
00892
00893
00894
00895
00896
00897
00898
00899
00900
00901
00902
00903
00904
00905
00906
00907
00908
00909
00910
00911
00912
00913
00914
00915
00916
00917
00918
00919
00920
00921
00922
00923
00924
00925
00926
00927
00928
00929
00930
00931
00932
00933
00934
00935
00936
00937
00938
00939
00940
00941
00942