[Orxonox-commit 215] r2885 - in trunk/src/orxonox/objects: controllers gametypes worldentities

landauf at orxonox.net landauf at orxonox.net
Wed Apr 1 00:37:16 CEST 2009


Author: landauf
Date: 2009-04-01 00:37:16 +0200 (Wed, 01 Apr 2009)
New Revision: 2885

Modified:
   trunk/src/orxonox/objects/controllers/PongAI.cc
   trunk/src/orxonox/objects/controllers/PongAI.h
   trunk/src/orxonox/objects/gametypes/Pong.cc
   trunk/src/orxonox/objects/worldentities/PongBall.cc
   trunk/src/orxonox/objects/worldentities/PongBall.h
Log:
Extended PongAI:
 - Random prediction errors depend on the vertical ball-speed
 - Fixed a bug: Position correction was also affected by the reaction delay. Now it works instantly.
 - Added oscillation avoidance system (the already implemented hysteresis avoidance system failed at low framerates)

Additionally fixed auto-respawn in Pong Gametype.

Modified: trunk/src/orxonox/objects/controllers/PongAI.cc
===================================================================
--- trunk/src/orxonox/objects/controllers/PongAI.cc	2009-03-31 22:25:12 UTC (rev 2884)
+++ trunk/src/orxonox/objects/controllers/PongAI.cc	2009-03-31 22:37:16 UTC (rev 2885)
@@ -52,6 +52,8 @@
         this->relHysteresisOffset_ = 0.02;
         this->strength_ = 0.5;
         this->movement_ = 0;
+        this->oldMove_ = 0;
+        this->bOscillationAvoidanceActive_ = false;
 
         this->setConfigValues();
     }
@@ -78,6 +80,7 @@
         float hysteresisOffset = this->relHysteresisOffset_ * this->ball_->getFieldDimension().y;
 
         char move = 0;
+        bool delay = false;
 
         // Check in which direction the ball is flying
         if ((mypos.x > 0 && ballvel.x < 0) || (mypos.x < 0 && ballvel.x > 0))
@@ -85,6 +88,7 @@
             // The ball is flying away
             this->ballDirection_.x = -1;
             this->ballDirection_.y = 0;
+            this->bOscillationAvoidanceActive_ = false;
 
             // Move to the middle
             if (mypos.z > hysteresisOffset)
@@ -97,6 +101,7 @@
             // The ball is standing still
             this->ballDirection_.x = 0;
             this->ballDirection_.y = 0;
+            this->bOscillationAvoidanceActive_ = false;
         }
         else
         {
@@ -111,6 +116,8 @@
 
                 this->calculateRandomOffset();
                 this->calculateBallEndPosition();
+                delay = true;
+                this->bOscillationAvoidanceActive_ = false;
             }
 
             if (this->ballDirection_.y != sgn(ballvel.z))
@@ -119,18 +126,36 @@
                 this->ballDirection_.y = sgn(ballvel.z);
 
                 this->calculateBallEndPosition();
+                delay = true;
+                this->bOscillationAvoidanceActive_ = false;
             }
 
             // Move to the predicted end position with an additional offset (to hit the ball with the side of the bat)
-            float desiredZValue = this->ballEndPosition_ + this->randomOffset_;
+            if (!this->bOscillationAvoidanceActive_)
+            {
+                float desiredZValue = this->ballEndPosition_ + this->randomOffset_;
 
-            if (mypos.z > desiredZValue + hysteresisOffset * (this->randomOffset_ < 0))
-                move = 1;
-            else if (mypos.z < desiredZValue - hysteresisOffset * (this->randomOffset_ > 0))
-                move = -1;
+                if (mypos.z > desiredZValue + hysteresisOffset * (this->randomOffset_ < 0))
+                    move = 1;
+                else if (mypos.z < desiredZValue - hysteresisOffset * (this->randomOffset_ > 0))
+                    move = -1;
+            }
+
+            if (move != 0 && this->oldMove_ != 0 && move != this->oldMove_ && !delay)
+            {
+                // We had to correct our position because we moved too far
+                // (and delay ist false, so we're not in the wrong place because of a new end-position prediction)
+                if (fabs(mypos.z - this->ballEndPosition_) < 0.5 * this->ball_->getBatLength() * this->ball_->getFieldDimension().y)
+                {
+                    // We're not at the right position, but we still hit the ball, so just stay there to avoid oscillation
+                    move = 0;
+                    this->bOscillationAvoidanceActive_ = true;
+                }
+            }
         }
 
-        this->move(move);
+        this->oldMove_ = move;
+        this->move(move, delay);
         this->getControllableEntity()->moveFrontBack(this->movement_);
     }
 
@@ -167,18 +192,21 @@
         // Calculate bounces
         for (float limit = 0.35; limit < this->strength_ || this->strength_ > 0.99; limit += 0.4)
         {
-            // Bounce from the upper bound
+            // Calculate a random prediction error, based on the vertical speed of the ball and the strength of the AI
+            float randomError = rnd(-1, 1) * dimension.y * (velocity.z / velocity.x / PongBall::MAX_REL_Z_VELOCITY) * (1 - this->strength_);
+
+            // Bounce from the lower bound
             if (this->ballEndPosition_ > dimension.y / 2)
             {
                 // Mirror the predicted position at the upper bound and add some random error
-                this->ballEndPosition_ = dimension.y - this->ballEndPosition_ + (rnd(-1, 1) * dimension.y * (1 - this->strength_));
+                this->ballEndPosition_ = dimension.y - this->ballEndPosition_ + randomError;
                 continue;
             }
             // Bounce from the upper bound
             if (this->ballEndPosition_ < -dimension.y / 2)
             {
                 // Mirror the predicted position at the lower bound and add some random error
-                this->ballEndPosition_ = -dimension.y - this->ballEndPosition_ + (rnd(-1, 1) * dimension.y * (1 - this->strength_));
+                this->ballEndPosition_ = -dimension.y - this->ballEndPosition_ + randomError;
                 continue;
             }
             // No bounce - break
@@ -186,7 +214,7 @@
         }
     }
 
-    void PongAI::move(char direction)
+    void PongAI::move(char direction, bool bUseDelay)
     {
         // The current direction is either what we're doing right now (movement_) or what is last in the queue
         char currentDirection = this->movement_;
@@ -197,9 +225,9 @@
         if (direction == currentDirection)
             return;
 
-        // Calculate delay, but only to change direction or start moving (stop works without delay)
-        if (direction != 0)
+        if (bUseDelay)
         {
+            // Calculate delay
             float delay = MAX_REACTION_TIME * (1 - this->strength_);
 
             // Add a new Timer
@@ -208,7 +236,7 @@
         }
         else
         {
-            this->movement_ = 0;
+            this->movement_ = direction;
         }
     }
 

Modified: trunk/src/orxonox/objects/controllers/PongAI.h
===================================================================
--- trunk/src/orxonox/objects/controllers/PongAI.h	2009-03-31 22:25:12 UTC (rev 2884)
+++ trunk/src/orxonox/objects/controllers/PongAI.h	2009-03-31 22:37:16 UTC (rev 2885)
@@ -55,7 +55,7 @@
         protected:
             void calculateRandomOffset();
             void calculateBallEndPosition();
-            void move(char direction);
+            void move(char direction, bool bUseDelay);
             void delayedMove();
 
             PongBall* ball_;
@@ -67,6 +67,8 @@
 
             std::list<std::pair<Timer<PongAI>*, char> > reactionTimers_;
             char movement_;
+            char oldMove_;
+            bool bOscillationAvoidanceActive_;
     };
 }
 

Modified: trunk/src/orxonox/objects/gametypes/Pong.cc
===================================================================
--- trunk/src/orxonox/objects/gametypes/Pong.cc	2009-03-31 22:25:12 UTC (rev 2884)
+++ trunk/src/orxonox/objects/gametypes/Pong.cc	2009-03-31 22:37:16 UTC (rev 2885)
@@ -53,8 +53,6 @@
         this->bat_[0] = 0;
         this->bat_[1] = 0;
 
-        this->bForceSpawn_ = true;
-
         this->starttimer_.setTimer(1.0, false, this, createExecutor(createFunctor(&Pong::startBall)));
         this->starttimer_.stopTimer();
 
@@ -110,7 +108,13 @@
 
         this->starttimer_.startTimer();
 
+
+        bool temp = this->bForceSpawn_;
+        this->bForceSpawn_ = true;
+
         Deathmatch::start();
+
+        this->bForceSpawn_ = temp;
     }
 
     void Pong::end()

Modified: trunk/src/orxonox/objects/worldentities/PongBall.cc
===================================================================
--- trunk/src/orxonox/objects/worldentities/PongBall.cc	2009-03-31 22:25:12 UTC (rev 2884)
+++ trunk/src/orxonox/objects/worldentities/PongBall.cc	2009-03-31 22:37:16 UTC (rev 2885)
@@ -37,6 +37,8 @@
 {
     CreateFactory(PongBall);
 
+    const float PongBall::MAX_REL_Z_VELOCITY = 1.5;
+
     PongBall::PongBall(BaseObject* creator) : MovableEntity(creator)
     {
         RegisterObject(PongBall);
@@ -78,7 +80,7 @@
                         {
                             position.x = this->fieldWidth_ / 2;
                             velocity.x = -velocity.x;
-                            velocity.z = distance * distance * sgn(distance) * 1.5 * this->speed_;
+                            velocity.z = distance * distance * sgn(distance) * PongBall::MAX_REL_Z_VELOCITY * this->speed_;
                         }
                         else if (position.x > this->fieldWidth_ / 2 * (1 + this->relMercyOffset_))
                         {
@@ -96,7 +98,7 @@
                         {
                             position.x = -this->fieldWidth_ / 2;
                             velocity.x = -velocity.x;
-                            velocity.z = distance * distance * sgn(distance) * 1.5 * this->speed_;
+                            velocity.z = distance * distance * sgn(distance) * PongBall::MAX_REL_Z_VELOCITY * this->speed_;
                         }
                         else if (position.x < -this->fieldWidth_ / 2 * (1 + this->relMercyOffset_))
                         {

Modified: trunk/src/orxonox/objects/worldentities/PongBall.h
===================================================================
--- trunk/src/orxonox/objects/worldentities/PongBall.h	2009-03-31 22:25:12 UTC (rev 2884)
+++ trunk/src/orxonox/objects/worldentities/PongBall.h	2009-03-31 22:37:16 UTC (rev 2885)
@@ -62,6 +62,8 @@
             void setBats(PongBat** bats)
                 { this->bat_ = bats; }
 
+            static const float MAX_REL_Z_VELOCITY;
+
         private:
             float fieldWidth_;
             float fieldHeight_;




More information about the Orxonox-commit mailing list