From: <pat...@us...> - 2017-07-08 15:42:41
|
Revision: 415 http://sourceforge.net/p/simspark/svn/415 Author: patmac369 Date: 2017-07-08 15:42:38 +0000 (Sat, 08 Jul 2017) Log Message: ----------- Adding changes for the RoboCup 2017 competition. Additions are the following: - Fixed bug where double touches on kicks (kickoffs, free kicks, kick-ins, corner kicks) were not always being detected correctly - Fixed bug where if a player is touching the ball right when the wait time at the beginning of a kick play mode ends the play mode could end up recording the touch and inadvertently end the kick. - Fixed bug where if two players enter their own penalty area at the same time, and in doing so cause the maximum allowed number of players in the penalty area to be exceeded, both players will be called for illegal defense even if the team is only one player over the allowed number of players in the penalty area. - The automated referee will no longer move/reposition agents on top of each other or into their own penalty area if it will trigger an illegal defense penalty. This is accomplished by doing a breadth first search around the position that an agent is to be repositioned to until a safe position is found. The number of positions that will be considered by the breadth first search is bounded by the MaxNumSafeRepositionAttempts value (default 100) in naosocersim.rb. Setting this value to 0 turns this feature off. If ever the server isn't able to safely reposition a player it will print an error message. - The order in which players are evaluated for fouls and are penalized is now randomized so as to not have any bias associated with players' teams and uniform numbers. - Fixed issue where free kicks and kicks-in printed an error message and didn't behave correctly if the ball has yet to be touched by an agent. - Averaging the velocity of an agent over the last 3 time steps instead of 5 when determining charging fouls. This allows agents to reduce their effective velocities faster so as to have a better chance of avoiding charging fouls when colliding with an opponent. - Removing code that takes into account the opponent's velocity moving away from a colliding agent when determining fouls. This code was decreasing the likelihood of an agent being called for a foul when running down an opponent from behind. - Turning off crowding rules in naosoccersim.rb - Adding StartAnyFieldPosition flag (default false) to naosoccersim.rb. Turning this flag on allows agents to be at, beam, or be moved to any position on the field at the start of kickoffs including the opponent's side of the field. Modified Paths: -------------- trunk/rcssserver3d/plugin/soccer/beameffector/beameffector.cpp trunk/rcssserver3d/plugin/soccer/beameffector/beameffector.h trunk/rcssserver3d/plugin/soccer/soccerruleaspect/soccerruleaspect.cpp trunk/rcssserver3d/plugin/soccer/soccerruleaspect/soccerruleaspect.h trunk/rcssserver3d/rcssserver3d/naosoccersim.rb Modified: trunk/rcssserver3d/plugin/soccer/beameffector/beameffector.cpp =================================================================== --- trunk/rcssserver3d/plugin/soccer/beameffector/beameffector.cpp 2017-03-24 21:15:15 UTC (rev 414) +++ trunk/rcssserver3d/plugin/soccer/beameffector/beameffector.cpp 2017-07-08 15:42:38 UTC (rev 415) @@ -94,16 +94,19 @@ return; } - // an agent can only beam within it's own field half - float minX = -mFieldLength/2; - pos[0] = std::max<float>(pos[0],minX); - pos[0] = std::min<float>(pos[0],0.0f); + if (!mStartAnyFieldPosition) + { + // an agent can only beam within it's own field half + float minX = -mFieldLength/2; + pos[0] = std::max<float>(pos[0],minX); + pos[0] = std::min<float>(pos[0],0.0f); + + float minY = -mFieldWidth/2; + float maxY = mFieldWidth/2; + pos[1] = std::max<float>(minY,pos[1]); + pos[1] = std::min<float>(maxY,pos[1]); + } - float minY = -mFieldWidth/2; - float maxY = mFieldWidth/2; - pos[1] = std::max<float>(minY,pos[1]); - pos[1] = std::min<float>(maxY,pos[1]); - // fix z coordinate pos[2] = mAgentRadius; @@ -190,6 +193,9 @@ mBeamNoiseAngle = 10.0f; SoccerBase::GetSoccerVar(*this, "BeamNoiseAngle",mBeamNoiseAngle); + mStartAnyFieldPosition = false; + SoccerBase::GetSoccerVar(*this,"StartAnyFieldPosition",mStartAnyFieldPosition); + UniformRngPtr rng1(new salt::UniformRNG<>(-1,1)); mNoiseRng = rng1; } Modified: trunk/rcssserver3d/plugin/soccer/beameffector/beameffector.h =================================================================== --- trunk/rcssserver3d/plugin/soccer/beameffector/beameffector.h 2017-03-24 21:15:15 UTC (rev 414) +++ trunk/rcssserver3d/plugin/soccer/beameffector/beameffector.h 2017-07-08 15:42:38 UTC (rev 415) @@ -80,6 +80,10 @@ /** amount of noise added to beam angle value */ float mBeamNoiseAngle; + + /** Allow starting at any field position including on opponent's + side of the field */ + bool mStartAnyFieldPosition; }; DECLARE_CLASS(BeamEffector); Modified: trunk/rcssserver3d/plugin/soccer/soccerruleaspect/soccerruleaspect.cpp =================================================================== --- trunk/rcssserver3d/plugin/soccer/soccerruleaspect/soccerruleaspect.cpp 2017-03-24 21:15:15 UTC (rev 414) +++ trunk/rcssserver3d/plugin/soccer/soccerruleaspect/soccerruleaspect.cpp 2017-07-08 15:42:38 UTC (rev 415) @@ -98,7 +98,9 @@ mKeepawayLength(20.0), mKeepawayWidth(20.0), mKeepawayLengthReductionRate(4.0), - mKeepawayWidthReductionRate(4.0) + mKeepawayWidthReductionRate(4.0), + mMaxNumSafeRepositionAttempts(100), + mStartAnyFieldPosition(false) { mFreeKickPos = Vector3f(0.0,0.0,mBallRadius); ResetFoulCounter(TI_LEFT); @@ -188,7 +190,7 @@ mGameState->SetPlayMode(PM_GameOver); } } - } + } if (mPenaltyShootout && mGameState->GetPlayMode() == PM_Goal_Left) { // Cancel penalty shootout mode now that a goal has been scored @@ -213,8 +215,13 @@ AnalyseTouchGroups(TI_LEFT); // Analyzes whether too many players are touching for the left team AnalyseTouchGroups(TI_RIGHT); // Analyzes whether too many players are touching for the right team - ClearPlayersAutomatic(TI_LEFT); // enforce standing and not overcrowding rules for left team - ClearPlayersAutomatic(TI_RIGHT); // enforce standing and not overcrowding rules for right team + if (rand()%2 == 0) { + ClearPlayersAutomatic(TI_LEFT); // enforce standing and not overcrowding rules for left team + ClearPlayersAutomatic(TI_RIGHT); // enforce standing and not overcrowding rules for right team + } else { + ClearPlayersAutomatic(TI_RIGHT); // enforce standing and not overcrowding rules for right team + ClearPlayersAutomatic(TI_LEFT); // enforce standing and not overcrowding rules for left team + } // Reset touch groups ResetTouchGroups(TI_LEFT); @@ -384,6 +391,7 @@ SoccerBase::TAgentStateList::const_iterator i; numPlInsideOwnArea[idx] = 0; + numPlReposInsideOwnArea[idx] = 0; closestPlayer[idx] = 1; closestPlayerDist[idx] = 1000.0; for(int t = 1; t <= 11; t++) @@ -605,17 +613,11 @@ for (int i = 0; i <= 1; i++) { - // Take into account the opponent's velocity vector when determining - // collision speed and subtract half the opponent's speed moving - // away from the the collision point as that speed reduces the - // collision force. - agentCollisionSpeed[i] = (agentAvgVel[i].x()*agentToCollisionVec[i].x() + agentAvgVel[i].y()*agentToCollisionVec[i].y()) + - 0.5*min(0.0f, agentAvgVel[1-i].x()*agentToCollisionVec[1-i].x() + agentAvgVel[1-i].y()*agentToCollisionVec[1-i].y()); - + // Get collision speed + agentCollisionSpeed[i] = agentAvgVel[i].x()*agentToCollisionVec[i].x() + agentAvgVel[i].y()*agentToCollisionVec[i].y(); isCharging[i] = (isCharging[i] && s[i] >= mChargingMinSpeed - && agentCollisionSpeed[i] >= mMinCollisionSpeed); - + && agentCollisionSpeed[i] >= mMinCollisionSpeed); } #ifdef RVDRAW @@ -814,9 +816,16 @@ void SoccerRuleAspect::AnalyseFouls(TTeamIndex idx) { TTeamIndex idx2 = SoccerBase::OpponentTeam(idx); // //Other team + + // Randomize order of agents evaluated + std::vector<unsigned int> unums(11); + for (unsigned int i = 0; i < unums.size(); i++) {unums[i] = i+1;} + std::random_shuffle(unums.begin(), unums.end()); - for(unsigned int unum=1; unum<=11; unum++) + for(std::vector<unsigned int>::const_iterator it = unums.begin(); it != unums.end(); ++it) { + unsigned int unum = *it; + if (HaveEnforceableFoul(unum,idx)) { // Once a player has been called for a foul don't check for @@ -853,6 +862,7 @@ { playerFoulTime[unum][idx]++; playerLastFoul[unum][idx] = FT_IllegalDefence; + numPlInsideOwnArea[idx]--; } // I am a field player and on the ground for too much time else if (unum != 1 && playerGround[unum][idx] > mGroundMaxTime / 0.02) @@ -901,6 +911,327 @@ } +bool SoccerRuleAspect::GetSafeRepositionHelper_AdjustPositionForPenaltyArea(const salt::Vector2f agent_pos, int unum, TTeamIndex idx, salt::Vector2f ¤t_pos) +{ + // Check that we're not being moved into our penalty area when there + // are already the maximum number of teammates allowed in the penalty + // area + if (playerInsideOwnArea[unum][idx] == 0 && numPlInsideOwnArea[idx]+numPlReposInsideOwnArea[idx] >= mMaxPlayersInsideOwnArea) { + if ((idx == TI_LEFT + && current_pos.x() > mLeftPenaltyArea.minVec[0]-mAgentRadius + && current_pos.x() < mLeftPenaltyArea.maxVec[0]+mAgentRadius + && current_pos.y() > mLeftPenaltyArea.minVec[1]-mAgentRadius + && current_pos.y() < mLeftPenaltyArea.maxVec[1]+mAgentRadius) + || (idx == TI_RIGHT + && current_pos.x() > mRightPenaltyArea.minVec[0]-mAgentRadius + && current_pos.x() < mRightPenaltyArea.maxVec[0]+mAgentRadius + && current_pos.y() > mRightPenaltyArea.minVec[1]-mAgentRadius + && current_pos.y() < mRightPenaltyArea.maxVec[1]+mAgentRadius)) { + /* +#ifdef RVDRAW + if (mRVSender) { + //mRVSender->clearStaticDrawings(); + mRVSender->drawPoint(current_pos.x(), current_pos.y(), 10, RVSender::YELLOW); + } +#endif + */ + if (idx == TI_LEFT) { + if (current_pos.x() > agent_pos.x()) { + // Move beyond the top of the penalty area + current_pos[0] = mLeftPenaltyArea.maxVec[0]+mAgentRadius; + } else { + // Move to a side of the penalty area + if (current_pos.y() > agent_pos.y() || (current_pos.y() == agent_pos.y() && current_pos.y() < 0)) { + current_pos[1] = mLeftPenaltyArea.maxVec[1]+mAgentRadius; + } else { + current_pos[1] = mLeftPenaltyArea.minVec[1]-mAgentRadius; + } + } + } else { + if (current_pos.x() < agent_pos.x()) { + // Move beyond the top of the penalty area + current_pos[0] = mRightPenaltyArea.minVec[0]-mAgentRadius; + } else { + // Move to a side of the penalty area + if (current_pos.y() > agent_pos.y() || (current_pos.y() == agent_pos.y() && current_pos.y() < 0)) { + current_pos[1] = mRightPenaltyArea.maxVec[1]+mAgentRadius; + } else { + current_pos[1] = mRightPenaltyArea.minVec[1]-mAgentRadius; + } + } + } + return true; + } + } + return false; +} + +void SoccerRuleAspect::GetSafeRepositionHelper_SamplePositions(const salt::Vector2f agent_pos, int unum, TTeamIndex idx, salt::Vector2f current_pos, std::list<salt::Vector2f> &candidatePosList) +{ + std::list<salt::Vector2f> newPosList; + salt::Vector2f agent_pos_xmove = current_pos; + if (idx == TI_LEFT) { + agent_pos_xmove[0] = current_pos.x() + mAgentRadius * (agent_pos.x() < current_pos.x() ? 1 : -1); + } else { + agent_pos_xmove[0] = current_pos.x() + mAgentRadius * (agent_pos.x() > current_pos.x() ? -1 : 1); + } + if (abs(agent_pos_xmove.x()) <= mFieldLength/2.0) { + GetSafeRepositionHelper_AdjustPositionForPenaltyArea(agent_pos, unum, idx, agent_pos_xmove); + newPosList.push_back(agent_pos_xmove); + } + + if (current_pos.x() == agent_pos.x()) { + // Also add x position moving in other direction + salt::Vector2f agent_pos_xmove2 = current_pos; + if (idx == TI_LEFT) { + agent_pos_xmove2[0] = current_pos.x() + mAgentRadius; + } else { + agent_pos_xmove2[0] = current_pos.x() - mAgentRadius; + } + if (abs(agent_pos_xmove2.x()) <= mFieldLength/2.0) { + GetSafeRepositionHelper_AdjustPositionForPenaltyArea(agent_pos, unum, idx, agent_pos_xmove2); + newPosList.push_back(agent_pos_xmove2); + } + } + + salt::Vector2f agent_pos_ymove = current_pos; + if (current_pos.y() == agent_pos.y()) { + // Move towards the center of the field + agent_pos_ymove[1] = current_pos.y() + mAgentRadius * (agent_pos.y() < 0 ? 1 : -1); + GetSafeRepositionHelper_AdjustPositionForPenaltyArea(agent_pos, unum, idx, agent_pos_ymove); + newPosList.push_back(agent_pos_ymove); + + // Move away from the center of the field + salt::Vector2f agent_pos_ymove2 = current_pos; + agent_pos_ymove2[1] = current_pos.y() + mAgentRadius * (agent_pos.y() < 0 ? -1 : 1); + GetSafeRepositionHelper_AdjustPositionForPenaltyArea(agent_pos, unum, idx, agent_pos_ymove2); + newPosList.push_back(agent_pos_ymove2); + } else { + agent_pos_ymove[1] = current_pos.y() + mAgentRadius * (agent_pos.y() < current_pos.y() ? 1 : -1); + GetSafeRepositionHelper_AdjustPositionForPenaltyArea(agent_pos, unum, idx, agent_pos_ymove); + newPosList.push_back(agent_pos_ymove); + } + + std::list<salt::Vector2f>::const_iterator i; + for (i = newPosList.begin(); i != newPosList.end(); ++i) { + salt::Vector2f newPos = *i; + float newPosDistToAgent = sqrt((newPos.x()-agent_pos.x())*(newPos.x()-agent_pos.x()) + + (newPos.y()-agent_pos.y())*(newPos.y()-agent_pos.y())); + bool fAddPos = true; + std::list<salt::Vector2f>::reverse_iterator c; + for (c = candidatePosList.rbegin(); c != candidatePosList.rend(); ++c) { + salt::Vector2f candidatePos = *c; + float candidatePosDistToNewPos = sqrt((candidatePos.x()-newPos.x())*(candidatePos.x()-newPos.x()) + + (candidatePos.y()-newPos.y())*(candidatePos.y()-newPos.y())); + if (candidatePosDistToNewPos < mAgentRadius/2.0) { + fAddPos = false; + break; + } + + float candidatePosDistToAgent = sqrt((candidatePos.x()-agent_pos.x())*(candidatePos.x()-agent_pos.x()) + + (candidatePos.y()-agent_pos.y())*(candidatePos.y()-agent_pos.y())); + if (newPosDistToAgent >= candidatePosDistToAgent) { + break; + } + } + if (fAddPos) { + /* +#ifdef RVDRAW + if (mRVSender) { + //mRVSender->clearStaticDrawings(); + mRVSender->drawPoint(newPos.x(), newPos.y(), 10, RVSender::LIGHTBLUE); + } +#endif + */ + candidatePosList.insert(c.base(), newPos); + } + + /* + std::list<salt::Vector2f>::const_iterator d; + std::cout << "-----------------\n"; + for (d = candidatePosList.begin(); d != candidatePosList.end(); ++d) { + salt::Vector2f candidatePos = *d; + float candidatePosDistToAgent = sqrt((candidatePos.x()-agent_pos.x())*(candidatePos.x()-agent_pos.x()) + + (candidatePos.y()-agent_pos.y())*(candidatePos.y()-agent_pos.y())); + std::cout << candidatePosDistToAgent << "\n"; + } + std::cout << "-----------------\n"; + */ + } +} + +salt::Vector3f SoccerRuleAspect::GetSafeReposition(salt::Vector3f posIni, int unum, TTeamIndex idx) +{ + salt::Vector3f pos = posIni; + if (mMaxNumSafeRepositionAttempts == 0 || idx == TI_NONE || mBallState.get() == 0 || mAgentRadius <= 0) + return pos; + + bool fFoundAgentPos = false; + salt::Vector3f agentPos = Vector3f(0,0,0); + SoccerBase::TAgentStateList agent_states; + if (SoccerBase::GetAgentStates(*mBallState.get(), agent_states, idx)) { + boost::shared_ptr<oxygen::Transform> agent_aspect; + SoccerBase::TAgentStateList::const_iterator i; + for (i = agent_states.begin(); i != agent_states.end(); ++i) + { + int unumAgent = (*i)->GetUniformNumber(); + if (unum == unumAgent) { + SoccerBase::GetTransformParent(**i, agent_aspect); + agentPos = agent_aspect->GetWorldTransform().Pos(); + fFoundAgentPos = true; + break; + } + } + } else { + return pos; + } + + if (!fFoundAgentPos) { + return pos; + } + + std::list<salt::Vector2f> candidatePosList; + + Vector2f agent_pos = Vector2f(agentPos.x(),agentPos.y()); + Vector2f initial_pos = Vector2f(posIni.x(),posIni.y()); + bool fUnsafePosition = GetSafeRepositionHelper_AdjustPositionForPenaltyArea(agent_pos, unum, idx, initial_pos); + if (fUnsafePosition) { + Vector2f current_pos = Vector2f(posIni.x(),posIni.y()); + GetSafeRepositionHelper_SamplePositions(agent_pos, unum, idx, current_pos, candidatePosList); + if (candidatePosList.empty()) { + GetLog()->Error() << "ERROR: (SoccerRuleAspect) Failed to safely reposition player " << unum << " " << (idx == TI_LEFT ? "(left)" : "(right)") << "\n"; + return posIni; + } + Vector2f candidatePos = candidatePosList.front(); + candidatePosList.pop_front(); + pos[0] = candidatePos.x(); + pos[1] = candidatePos.y(); + } + + // Count the number of times we've repositioned an agent from colliding, + // and bound this so as to avoid the possibility of an infinite loop + int repositionAttempts = 0; + while (repositionAttempts < mMaxNumSafeRepositionAttempts) { + fUnsafePosition = false; + SoccerBase::TAgentStateList agent_states; + salt::BoundingSphere sphere(pos, mAgentRadius); + + // Check for collisions with teammates + if (SoccerBase::GetAgentStates(*mBallState.get(), agent_states, idx)) { + SoccerBase::TAgentStateList::const_iterator i; + + for (i = agent_states.begin(); i != agent_states.end(); ++i) + { + int unumAgent = (*i)->GetUniformNumber(); + if (unum == unumAgent) { + continue; + } + + boost::shared_ptr<oxygen::Transform> agent_aspect; + SoccerBase::GetTransformParent(**i, agent_aspect); + AABB3 agentAABB = SoccerBase::GetAgentBoundingBox(*agent_aspect); + if (sphere.Intersects(agentAABB)) { + /* +#ifdef RVDRAW + if (mRVSender) { + //mRVSender->clearStaticDrawings(); + mRVSender->drawPoint(pos.x(), pos.y(), 10, RVSender::RED); + } +#endif + */ + Vector2f current_pos = Vector2f(pos.x(),pos.y()); + GetSafeRepositionHelper_SamplePositions(agent_pos, unum, idx, current_pos, candidatePosList); + fUnsafePosition = true; + break; + } + } + } + + // Check for collision with opponents + agent_states.clear(); + if (!fUnsafePosition && SoccerBase::GetAgentStates(*mBallState.get(), agent_states, SoccerBase::OpponentTeam(idx))) { + SoccerBase::TAgentStateList::const_iterator i; + + for (i = agent_states.begin(); i != agent_states.end(); ++i) + { + boost::shared_ptr<oxygen::Transform> agent_aspect; + SoccerBase::GetTransformParent(**i, agent_aspect); + AABB3 agentAABB = SoccerBase::GetAgentBoundingBox(*agent_aspect); + if (sphere.Intersects(agentAABB)) { +#ifdef RVDRAW + if (mRVSender) { + //mRVSender->clearStaticDrawings(); + mRVSender->drawPoint(pos.x(), pos.y(), 10, RVSender::RED); + } +#endif + Vector2f current_pos = Vector2f(pos.x(),pos.y()); + GetSafeRepositionHelper_SamplePositions(agent_pos, unum, idx, current_pos, candidatePosList); + fUnsafePosition = true; + break; + } + } + } + + if (!fUnsafePosition) { + // Check for collisions with other repositioned agents + list<Vector2f>::const_iterator i; + for (i = reposLocs.begin(); i != reposLocs.end(); ++i) + { + Vector2f repos_agent_pos = *i; + float dist = sqrt((repos_agent_pos.x()-pos.x())*(repos_agent_pos.x()-pos.x()) + + (repos_agent_pos.y()-pos.y())*(repos_agent_pos.y()-pos.y())); + if (dist < mAgentRadius*2) { + /* +#ifdef RVDRAW + if (mRVSender) { + //mRVSender->clearStaticDrawings(); + mRVSender->drawPoint(pos.x(), pos.y(), 10, RVSender::ORANGE); + } +#endif + */ + Vector2f current_pos = Vector2f(pos.x(),pos.y()); + GetSafeRepositionHelper_SamplePositions(agent_pos, unum, idx, current_pos, candidatePosList); + fUnsafePosition = true; + break; + } + } + } + + if (!fUnsafePosition || candidatePosList.empty()) { + break; + } + + Vector2f candidatePos = candidatePosList.front(); + candidatePosList.pop_front(); + pos[0] = candidatePos.x(); + pos[1] = candidatePos.y(); + repositionAttempts++; + } + + //std::cout << repositionAttempts << "\n"; + + if (fUnsafePosition) { + GetLog()->Error() << "ERROR: (SoccerRuleAspect) Failed to safely reposition player " << unum << " " << (idx == TI_LEFT ? "(left)" : "(right)") << "\n"; + pos = posIni; + } + + if (playerInsideOwnArea[unum][idx] == 0 && ((idx == TI_LEFT && mLeftPenaltyArea.Contains(Vector2f(pos.x(), pos.y()))) || + (idx == TI_RIGHT && mRightPenaltyArea.Contains(Vector2f(pos.x(), pos.y()))))) + { + numPlReposInsideOwnArea[idx]++; + } + else if (playerInsideOwnArea[unum][idx] == 1 && ((idx == TI_LEFT && !mLeftPenaltyArea.Contains(Vector2f(pos.x(), pos.y()))) || + (idx == TI_RIGHT && !mRightPenaltyArea.Contains(Vector2f(pos.x(), pos.y()))))) + { + numPlReposInsideOwnArea[idx]--; + } + + reposLocs.push_back(Vector2f(pos.x(), pos.y())); + + return pos; +} + + // Clear Players that are violating the rules void SoccerRuleAspect::ClearPlayersAutomatic(TTeamIndex idx) @@ -912,6 +1243,8 @@ if (! SoccerBase::GetAgentStates(*mBallState.get(), agent_states, idx)) return; + random_shuffle(agent_states.begin(), agent_states.end()); + salt::Vector3f ballPos = mBallBody->GetPosition(); boost::shared_ptr<oxygen::Transform> agent_aspect; @@ -931,7 +1264,7 @@ if (playerFoulTime[unum][idx] <= mFoulHoldTime/0.02) { playerFoulTime[unum][idx]++; agentPos[2] = 1.0 + playerFoulTime[unum][idx]*0.01; - MoveAgent(agent_aspect, agentPos); + MoveAgent(agent_aspect, agentPos, false /*fSafe*/); } else { // I am not a very good soccer player... I am violating the rules... salt::Vector3f new_pos = RepositionOutsidePos(ballPos, unum, idx); @@ -959,6 +1292,8 @@ if (! SoccerBase::GetAgentStates(*mBallState.get(), agent_states, idx)) return; + random_shuffle(agent_states.begin(), agent_states.end()); + salt::BoundingSphere sphere(pos, radius); boost::shared_ptr<oxygen::Transform> agent_aspect; SoccerBase::TAgentStateList::const_iterator i; @@ -1004,6 +1339,8 @@ if (! SoccerBase::GetAgentStates(*mBallState.get(), agent_states, idx)) return; + random_shuffle(agent_states.begin(), agent_states.end()); + boost::shared_ptr<oxygen::Transform> agent_aspect; SoccerBase::TAgentStateList::const_iterator i; for (i = agent_states.begin(); i != agent_states.end(); ++i) @@ -1031,7 +1368,7 @@ void SoccerRuleAspect::ClearPlayersBeforeKickOff(TTeamIndex idx) { - if (idx == TI_NONE || mBallState.get() == 0) return; + if (mStartAnyFieldPosition || idx == TI_NONE || mBallState.get() == 0) return; // move the non-kick off team to own half field except the center // circle @@ -1049,6 +1386,8 @@ if (! SoccerBase::GetAgentStates(*mBallState.get(), agent_states, idx)) return; + random_shuffle(agent_states.begin(), agent_states.end()); + salt::AABB2 box; if ( TI_RIGHT == idx ){ box = mLeftHalf; @@ -1098,6 +1437,8 @@ if (! SoccerBase::GetAgentStates(*mBallState.get(), agent_states, idx)) return; + random_shuffle(agent_states.begin(), agent_states.end()); + boost::shared_ptr<oxygen::Transform> agent_aspect; SoccerBase::TAgentStateList::const_iterator i; for (i = agent_states.begin(); i != agent_states.end(); ++i) @@ -1116,6 +1457,7 @@ Vector2f updated_pos = avoid_pos+pos2Agent.Normalize()*radius; new_pos[0] = updated_pos[0]; new_pos[1] = updated_pos[1]; + new_pos = GetSafeReposition(new_pos, (*i)->GetUniformNumber(), idx); SoccerBase::MoveAgent(agent_aspect, new_pos); } } @@ -1297,9 +1639,29 @@ TTime kickTime; // notice that a kick is not necessarily an immediate action, it can // take some time... - return mBallState->GetLastCollidingAgent(lastKicker, kickTime) - && kickTime - mLastFreeKickKickTime < 0.1 // kick duration = 0.1 - && lastKicker == mLastFreeKickTaker; + if (!mLastFreeKickTaker || !mBallState->GetLastCollidingAgent(lastKicker, kickTime)) { + return false; + } + + boost::shared_ptr<AgentState> agentStateLastKicker; + if (!SoccerBase::GetAgentState(lastKicker, agentStateLastKicker)) + { + GetLog()->Error() << "ERROR: (SoccerRuleAspect) Cannot get " + "AgentState from an AgentAspect\n"; + return false; + } + + boost::shared_ptr<AgentState> agentStateLastFreeKickTaker; + if (!SoccerBase::GetAgentState(mLastFreeKickTaker, agentStateLastFreeKickTaker)) + { + GetLog()->Error() << "ERROR: (SoccerRuleAspect) Cannot get " + "AgentState from an AgentAspect\n"; + return false; + } + + return kickTime - mLastFreeKickKickTime < 0.1 // kick duration = 0.1 + && agentStateLastKicker->GetUniformNumber() == agentStateLastFreeKickTaker->GetUniformNumber() + && agentStateLastKicker->GetTeamIndex() == agentStateLastFreeKickTaker->GetTeamIndex(); } void @@ -1310,6 +1672,8 @@ if (! SoccerBase::GetAgentStates(*mBallState.get(), agent_states, TI_NONE)) return; + random_shuffle(agent_states.begin(), agent_states.end()); + boost::shared_ptr<oxygen::Transform> agent_aspect; SoccerBase::TAgentStateList::const_iterator i; for (i = agent_states.begin(); i != agent_states.end(); ++i) @@ -1395,9 +1759,17 @@ MoveBall(pos); - ClearPlayers(pos, mFreeKickDist, mFreeKickMoveDist, TI_LEFT); - ClearPlayers(pos, mFreeKickDist, mFreeKickMoveDist, TI_RIGHT); - + if (rand()%2 == 0) + { + ClearPlayers(pos, mFreeKickDist, mFreeKickMoveDist, TI_LEFT); + ClearPlayers(pos, mFreeKickDist, mFreeKickMoveDist, TI_RIGHT); + } + else + { + ClearPlayers(pos, mFreeKickDist, mFreeKickMoveDist, TI_RIGHT); + ClearPlayers(pos, mFreeKickDist, mFreeKickMoveDist, TI_LEFT); + } + // After a drop ball allow anyone to touch it ResetKickChecks(); @@ -1425,8 +1797,20 @@ MoveBall(pos); mGameState->SetPaused(true); - ClearPlayers(mRightHalf, mFreeKickMoveDist, TI_LEFT); - ClearPlayers(mLeftHalf, mFreeKickMoveDist, TI_RIGHT); + + if (!mStartAnyFieldPosition) + { + if (rand()%2 == 0) + { + ClearPlayers(mRightHalf, mFreeKickMoveDist, TI_LEFT); + ClearPlayers(mLeftHalf, mFreeKickMoveDist, TI_RIGHT); + } + else + { + ClearPlayers(mLeftHalf, mFreeKickMoveDist, TI_RIGHT); + ClearPlayers(mRightHalf, mFreeKickMoveDist, TI_LEFT); + } + } #if 0 // @@ -1493,6 +1877,9 @@ void SoccerRuleAspect::UpdateKickIn(TTeamIndex idx) { + // [patmac] This method is almost identical to UpdateFreeKick + // and could probably just call UpdateFreeKick(idx, true /*indirect*/) + mGameState->SetPaused(false); // do nothing for the duration of mKickInPauseTime @@ -1523,14 +1910,10 @@ // change to the KickIn mode *plus* pause time boost::shared_ptr<AgentAspect> agent; TTime time; - if (! mBallState->GetLastCollidingAgent(agent,time)) - { - GetLog()->Error() << "ERROR: (SoccerRuleAspect) " << "no agent collided yet\n"; - return; - } + bool fHaveAgentCollidedWithBall = mBallState->GetLastCollidingAgent(agent,time); TTime lastChange = mGameState->GetLastModeChange(); - if (time > lastChange + mKickInPauseTime && !mRepelPlayersForKick) + if (fHaveAgentCollidedWithBall && time > lastChange + mKickInPauseTime + 0.03 && !mRepelPlayersForKick) { SetKickTakenValues(time, agent, true); mGameState->SetPlayMode(PM_PlayOn); @@ -1600,14 +1983,10 @@ // change to the KickIn mode boost::shared_ptr<AgentAspect> agent; TTime time; - if (! mBallState->GetLastCollidingAgent(agent,time)) - { - GetLog()->Error() << "ERROR: (SoccerRuleAspect) " << "no agent collided yet\n"; - return; - } + bool fHaveAgentCollidedWithBall = mBallState->GetLastCollidingAgent(agent,time); TTime lastChange = mGameState->GetLastModeChange(); - if (time > lastChange + mKickInPauseTime && !mRepelPlayersForKick) + if (fHaveAgentCollidedWithBall && time > lastChange + mKickInPauseTime + 0.03 && !mRepelPlayersForKick) { SetKickTakenValues(time, agent, indirect); mGameState->SetPlayMode(PM_PlayOn); @@ -1666,7 +2045,7 @@ TTime lastChange = mGameState->GetLastModeChange(); // if the team with the goal kick touched the ball and the ball is // outside the penalty area, we switch to play on. - if (time > lastChange + mKickInPauseTime && !mRepelPlayersForKick) + if (time > lastChange + mKickInPauseTime + 0.03 && !mRepelPlayersForKick) { Vector2f pos(mBallBody->GetPosition().x(), mBallBody->GetPosition().y()); @@ -1737,7 +2116,7 @@ } TTime lastChange = mGameState->GetLastModeChange(); - if (time > lastChange + mKickInPauseTime && !mRepelPlayersForKick) + if (time > lastChange + mKickInPauseTime + 0.03 && !mRepelPlayersForKick) { SetKickTakenValues(time, agent, false); mGameState->SetPlayMode(PM_PlayOn); @@ -1956,7 +2335,7 @@ bool SoccerRuleAspect::CheckFreeKickTakerFoul() { - if (!mCheckFreeKickKickerFoul) + if (!mCheckFreeKickKickerFoul || !mLastFreeKickTaker) return false; boost::shared_ptr<AgentAspect> agent; @@ -1964,8 +2343,26 @@ { mCheckFreeKickKickerFoul = false; mIndirectKick = false; - if (agent == mLastFreeKickTaker) + + boost::shared_ptr<AgentState> agentStateLastKicker; + if (!SoccerBase::GetAgentState(agent, agentStateLastKicker)) { + GetLog()->Error() << "ERROR: (SoccerRuleAspect) Cannot get " + "AgentState from an AgentAspect\n"; + return false; + } + + boost::shared_ptr<AgentState> agentStateLastFreeKickTaker; + if (!SoccerBase::GetAgentState(mLastFreeKickTaker, agentStateLastFreeKickTaker)) + { + GetLog()->Error() << "ERROR: (SoccerRuleAspect) Cannot get " + "AgentState from an AgentAspect\n"; + return false; + } + + if (agentStateLastKicker->GetUniformNumber() == agentStateLastFreeKickTaker->GetUniformNumber() + && agentStateLastKicker->GetTeamIndex() == agentStateLastFreeKickTaker->GetTeamIndex()) + { PunishFreeKickFoul(mLastFreeKickTaker); return true; } @@ -2167,6 +2564,8 @@ return; } + reposLocs.clear(); + CheckTime(); TPlayMode playMode = mGameState->GetPlayMode(); @@ -2420,7 +2819,10 @@ SoccerBase::GetSoccerVar(*this,"ChargingMinCollisionSpeed",mMinCollisionSpeed); SoccerBase::GetSoccerVar(*this,"FoulHoldTime",mFoulHoldTime); + SoccerBase::GetSoccerVar(*this,"MaxNumSafeRepositionAttempts",mMaxNumSafeRepositionAttempts); + SoccerBase::GetSoccerVar(*this,"StartAnyFieldPosition",mStartAnyFieldPosition); + // cout << "MaxInside " << mMaxPlayersInsideOwnArea << endl << endl; // set up bounding boxes for halfs and goal areas @@ -2806,7 +3208,7 @@ TTeamIndex collidingAgentIdx = agentState->GetTeamIndex(); TTime lastChange = mGameState->GetLastModeChange(); - if (time > lastChange && collidingAgentIdx==idx && !mRepelPlayersForKick) + if (time > lastChange + 0.03 && collidingAgentIdx==idx && !mRepelPlayersForKick) { mGameState->SetPlayMode(PM_PlayOn); } @@ -2830,6 +3232,8 @@ if (! SoccerBase::GetAgentStates(*mBallState.get(), agent_states, idx)) return; + random_shuffle(agent_states.begin(), agent_states.end()); + salt::BoundingSphere sphere(pos, radius); boost::shared_ptr<oxygen::Transform> agent_aspect; SoccerBase::TAgentStateList::const_iterator i; @@ -2919,8 +3323,10 @@ bool -SoccerRuleAspect::MoveAgent(boost::shared_ptr<Transform> agent_aspect, const Vector3f& pos) +SoccerRuleAspect::MoveAgent(boost::shared_ptr<Transform> agent_aspect, const Vector3f& pos, bool fSafe) { + Vector3f move_pos = pos; + boost::shared_ptr<AgentState> agentState; if (!SoccerBase::GetAgentState(agent_aspect, agentState)) { @@ -2930,11 +3336,15 @@ else { int unum = agentState->GetUniformNumber(); - int idx = agentState->GetTeamIndex(); + TTeamIndex idx = agentState->GetTeamIndex(); playerTimeSinceLastWasMoved[unum][idx] = 0; + + if (fSafe) { + move_pos = GetSafeReposition(pos, unum, idx); + } } - return SoccerBase::MoveAgent(agent_aspect, pos); + return SoccerBase::MoveAgent(agent_aspect, move_pos); } bool Modified: trunk/rcssserver3d/plugin/soccer/soccerruleaspect/soccerruleaspect.h =================================================================== --- trunk/rcssserver3d/plugin/soccer/soccerruleaspect/soccerruleaspect.h 2017-03-24 21:15:15 UTC (rev 414) +++ trunk/rcssserver3d/plugin/soccer/soccerruleaspect/soccerruleaspect.h 2017-07-08 15:42:38 UTC (rev 415) @@ -102,6 +102,23 @@ */ salt::Vector3f RepositionOutsidePos(salt::Vector3f initPos, int unum, TTeamIndex idx); + /** Helper for GetSafeReposition that adjusts positions if they are in + a team's penalty area and would cause an illegal defense foul if an + agent was moved there + */ + bool GetSafeRepositionHelper_AdjustPositionForPenaltyArea(const salt::Vector2f agent_pos, int unum, TTeamIndex idx, salt::Vector2f ¤t_pos); + + /** Helper for GetSafeReposition that samples new positions to try and + move an agent to for repositioning + */ + void GetSafeRepositionHelper_SamplePositions(const salt::Vector2f agent_pos, int unum, TTeamIndex idx, salt::Vector2f current_pos, std::list<salt::Vector2f> &candidatePosList); + + /** Checks the current position for an agent to be repositioned to for + potential collisions with other agents, and adjusts the position if need + be to avoid collisions + */ + salt::Vector3f GetSafeReposition(salt::Vector3f posIni, int unum, TTeamIndex idx); + /** Calculates the inside field reposition pos for a given agent with unum and team idx Agents are repositioned at distance from the ball, that is, at: plpos + (plpos-ballpos).normalize()*dist */ @@ -367,13 +384,13 @@ bool WasLastKickFromFreeKick( boost::shared_ptr<oxygen::AgentAspect> &lastKicker); - bool MoveAgent(boost::shared_ptr<oxygen::Transform> agent_aspect, const salt::Vector3f& pos); + bool MoveAgent(boost::shared_ptr<oxygen::Transform> agent_aspect, const salt::Vector3f& pos, bool fSafe=true); /** if a player has committed a foul that should be enforced */ bool HaveEnforceableFoul(int unum, TTeamIndex ti); protected: - static const int AVERAGE_VELOCITY_MEASUREMENTS = 5; + static const int AVERAGE_VELOCITY_MEASUREMENTS = 3; /** reference to the body node of the Ball */ boost::shared_ptr<oxygen::RigidBody> mBallBody; @@ -485,6 +502,8 @@ int playerFoulTime[12][3]; //Time player is commiting a positional foul EFoulType playerLastFoul[12][3]; //Type of last foul committed by player int numPlInsideOwnArea[3]; //Number of players inside own area + int numPlReposInsideOwnArea[3]; //Number of players repositioned inside own area + std::list<salt::Vector2f> reposLocs; // List of locations players have been repositioned to int closestPlayer[3]; //Closest Player from each team float closestPlayerDist[3]; //Closest Player distance to ball from each team salt::Vector3f playerVelocities[12][3][AVERAGE_VELOCITY_MEASUREMENTS]; // Player velocities over last AVERAGE_VELOCITY_MEASUREMENTS cycles @@ -594,6 +613,13 @@ /** reduction rate of width of keepaway box per minute */ float mKeepawayWidthReductionRate; + /** Maximum number of attempts made to safely reposition an agent */ + int mMaxNumSafeRepositionAttempts; + + /** Allow starting at any field position including on opponent's + side of the field */ + bool mStartAnyFieldPosition; + #ifdef RVDRAW boost::shared_ptr<RVSender> mRVSender; #endif // RVDRAW Modified: trunk/rcssserver3d/rcssserver3d/naosoccersim.rb =================================================================== --- trunk/rcssserver3d/rcssserver3d/naosoccersim.rb 2017-03-24 21:15:15 UTC (rev 414) +++ trunk/rcssserver3d/rcssserver3d/naosoccersim.rb 2017-07-08 15:42:38 UTC (rev 415) @@ -56,6 +56,7 @@ addSoccerVar('WaitBeforeKickOff', 30.0) addSoccerVar('CoinTossForKickOff', false) addSoccerVar('PenaltyShootout', false) +addSoccerVar('StartAnyFieldPosition', false) addSoccerVar('AutomaticQuit', false) addSoccerVar('ChangeSidesInSecondHalf', false) @@ -106,9 +107,13 @@ addSoccerVar('GroundMaxTime',15) addSoccerVar('GoalieGroundMaxTime', 30) addSoccerVar('MaxPlayersInsideOwnArea',3) -addSoccerVar('MinOppDistance',0.8) -addSoccerVar('Min2PlDistance',0.4) -addSoccerVar('Min3PlDistance',1.0) +#addSoccerVar('MinOppDistance',0.8) +#addSoccerVar('Min2PlDistance',0.4) +#addSoccerVar('Min3PlDistance',1.0) +# Turning off crowding for 2017 competition +addSoccerVar('MinOppDistance',0.0) +addSoccerVar('Min2PlDistance',0.0) +addSoccerVar('Min3PlDistance',0.0) addSoccerVar('FoulHoldTime', 0.5) @@ -128,8 +133,10 @@ #addSoccerVar('MaxPlayersInsideOwnArea',2) #addSoccerVar('MinOppDistance',1.0) #addSoccerVar('Min2PlDistance',0.6) -#addSoccerVar('Min3PlDistance',1.5) +#addSoccerVar('Min3PlDistance',1.5) +addSoccerVar('MaxNumSafeRepositionAttempts', 100) + # recorders addSoccerVar('BallRecorder',"Ball/geometry/recorder") addSoccerVar('LeftGoalRecorder',"leftgoal/GoalBox/BoxCollider/recorder") This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |