Skip to content

Commit

Permalink
Merge pull request #19 from RoboTeamTwente/fix/botdribbledballtoofar
Browse files Browse the repository at this point in the history
Fix/botdribbledballtoofar
  • Loading branch information
JWillegers authored Jun 26, 2024
2 parents b8d5e4d + 06f2fac commit 4152b08
Show file tree
Hide file tree
Showing 12 changed files with 155 additions and 60 deletions.
86 changes: 56 additions & 30 deletions src/main/java/nl/roboteamtwente/autoref/SSLAutoRef.java
Original file line number Diff line number Diff line change
Expand Up @@ -208,7 +208,6 @@ private void deriveRobot(Game game, TeamColor teamColor, WorldRobotOuterClass.Wo
robot.getVelocity().setY(worldRobot.getVel().getY());
if (teamColor == TeamColor.BLUE) {
robot.setRadius(statePacket.getBlueRobotParameters().getParameters().getRadius());
System.out.println(robot.getRadius());
} else {
robot.setRadius(statePacket.getYellowRobotParameters().getParameters().getRadius());
}
Expand Down Expand Up @@ -266,14 +265,38 @@ private void deriveField(Game game, StateOuterClass.State statePacket) {
private void deriveTouch(Game game) {
// copy variables from previous game
game.getBall().setLastTouchStarted(game.getPrevious().getBall().getLastTouchStarted());

// restore all finished touches, in-progress touches will be evaluated next
game.getTouches().addAll(game.getPrevious().getFinishedTouches());
game.setKickType(game.getPrevious().getKickType());
game.setKickIntoPlay(game.getPrevious().getKickIntoPlay());
for (Touch touch : game.getPrevious().getTouches()) {
if (!touch.isFinished()) {
game.getTouches().add(touch);
}
}
if (game.getPrevious().getLastFinishedTouch() != null) {
game.getTouches().add(game.getPrevious().getLastFinishedTouch());
}

Ball ball = game.getBall();
Vector3 ballPosition = ball.getPosition();
int robotsCloseToBall = 0;

//check if ball has randomly teleported
if (game.getBall().getLastTouchStarted() != null && !game.getBall().getLastTouchStarted().isFinished()) { // a robot is still touching the ball
Ball ball_ = game.getBall();
Touch touch_ = ball_.getLastTouchStarted();
Robot robot_ = game.getRobot(touch_.getBy());
//if distance between robot and ball is greater than 15m/s * 60Hz + robot radius there is a false positive
if (ball_.getPosition().xy().distance(robot_.getPosition().xy()) > (15 * 1/60 + robot_.getRadius())) {
return;
}
}

//find out how many robots are within 0.25m (needs testing to find out what range is effective)
for (Robot robot : game.getRobots()) {
if(robot.getPosition().xy().distance(ballPosition.xy()) < 0.25) {
robotsCloseToBall++;
}
}

for (Robot robot : game.getRobots()) {
Robot oldRobot = game.getPrevious().getRobot(robot.getIdentifier());
Expand All @@ -285,40 +308,43 @@ private void deriveTouch(Game game) {
}

Touch touch = robot.getTouch();

float distance = robot.getPosition().xy().distance(ballPosition.xy());

// detect if there's a touch
if (distance <= robot.getTeam().getRobotRadius() + BALL_TOUCHING_DISTANCE && ball.getPosition().getZ() <= robot.getTeam().getRobotHeight() + BALL_TOUCHING_DISTANCE) {
ball.getRobotsTouching().add(robot);

// it just started touching ball, either when its the first frame or when
// in the previous frame the robot was not touching the ball.
robot.setJustTouchedBall(oldRobot == null || !oldRobot.isTouchingBall());
} else {
// robot is not touching ball
robot.setJustTouchedBall(false);
robot.setTouch(null);

if (touch != null) {
// we update the touch to include the end position
touch = new Touch(touch.id(), touch.startLocation(), ballPosition, touch.startTime(), game.getTime(), touch.startVelocity(), ball.getVelocity(), robot.getIdentifier());


// if this touch is the kick into play, we update that too
if (Objects.equals(touch, game.getKickIntoPlay())) {
game.setKickIntoPlay(touch);
if (ball.isVisible()) {
// detect if there's a touch
if (distance <= robot.getTeam().getRobotRadius() + BALL_TOUCHING_DISTANCE && ball.getPosition().getZ()
<= robot.getTeam().getRobotHeight() + BALL_TOUCHING_DISTANCE) {
ball.getRobotsTouching().add(robot);

// it just started touching ball, either when its the first frame or when
// in the previous frame the robot was not touching the ball.
robot.setJustTouchedBall(oldRobot == null || !oldRobot.isTouchingBall());
} else {
// robot is not touching ball
robot.setJustTouchedBall(false);
robot.setTouch(null);

if (touch != null) {
// we update the touch to include the end position
touch.setEndLocation(ballPosition);
touch.setEndTime(game.getTime());
touch.setEndVelocity(ball.getVelocity());

// if this touch is the kick into play, we update that too
if (Objects.equals(touch, game.getKickIntoPlay())) {
game.setKickIntoPlay(touch);
}
}
}
}

if (robot.hasJustTouchedBall()) {
// we create a new partial touch
touch = new Touch(nextTouchId++, ballPosition, null, game.getTime(), null, ball.getVelocity(), null, robot.getIdentifier());
touch = new Touch(nextTouchId++, ballPosition, game.getTime(), ball.getVelocity(), robotsCloseToBall, robot.getIdentifier());
ball.setLastTouchStarted(touch);
robot.setTouch(touch);

System.out.print("touch #" + touch.id() + " by " + robot.getIdentifier());
System.out.print("touch #" + touch.getId() + " by " + robot.getIdentifier());

// if this happened during kickoff or a free kick, this is the kick into play
if (game.getState() == GameState.KICKOFF || game.getState() == GameState.FREE_KICK) {
Expand All @@ -330,12 +356,12 @@ private void deriveTouch(Game game) {

System.out.print(" (kick into play)");
}

System.out.println();
} else if (touch != null) {
touch.updatePercentages(ball.isVisible(), robotsCloseToBall);
}

// to conclude, we add the touch to the game
if (touch != null) {
if (touch != null && !game.getTouches().contains(touch)) {
game.getTouches().add(touch);
}
}
Expand Down
69 changes: 68 additions & 1 deletion src/main/java/nl/roboteamtwente/autoref/model/Touch.java
Original file line number Diff line number Diff line change
@@ -1,10 +1,45 @@
package nl.roboteamtwente.autoref.model;

public record Touch(int id, Vector3 startLocation, Vector3 endLocation, double startTime, Double endTime, Vector3 startVelocity, Vector3 endVelocity, RobotIdentifier by) {
public class Touch {
int id;
private Vector3 startLocation;
private Vector3 endLocation;
private double startTime;
private Double endTime;
private Vector3 startVelocity;
private Vector3 endVelocity;
private float percentageBallSeen;
private float averageNumberOfRobotsCloseBy;
private int nOfDataPoints;
private RobotIdentifier by;

public Touch(int id, Vector3 startLocation, double startTime,
Vector3 startVelocity, int numberOfRobotsCloseBy, RobotIdentifier by) {
this.id = id;
this.startLocation = startLocation;
this.endLocation = null;
this.startTime = startTime;
this.endTime = null;
this.startVelocity = startVelocity;
this.endVelocity = null;
this.percentageBallSeen = 1.0f;
this.averageNumberOfRobotsCloseBy = numberOfRobotsCloseBy;
this.nOfDataPoints = 1;
this.by = by;
}

public boolean isFinished() {
return this.endLocation != null;
}

public void updatePercentages(boolean ballVisible, int numberOfRobotsCloseBy) {
int value = ballVisible ? 1 : 0;
this.percentageBallSeen = (this.percentageBallSeen * this.nOfDataPoints + value) / (nOfDataPoints + 1);
this.averageNumberOfRobotsCloseBy = (this.averageNumberOfRobotsCloseBy * this.nOfDataPoints
+ numberOfRobotsCloseBy) / (nOfDataPoints + 1);
this.nOfDataPoints++;
}

public float deflectionAngle() {
float angle = startVelocity.xy().angle(endVelocity.xy());
return Math.min(angle, 360 - angle);
Expand All @@ -18,4 +53,36 @@ public boolean equals(Object o) {
return false;
}
}

public Vector3 getStartLocation() {
return startLocation;
}

public void setEndLocation(Vector3 endLocation) {
this.endLocation = endLocation;
}

public Vector3 getEndLocation() {
return endLocation;
}

public void setEndTime(Double endTime) {
this.endTime = endTime;
}

public Double getEndTime() {
return endTime;
}

public void setEndVelocity(Vector3 endVelocity) {
this.endVelocity = endVelocity;
}

public int getId() {
return id;
}

public RobotIdentifier getBy() {
return by;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -30,24 +30,24 @@ public RuleViolation validate(Game game) {
}

//Get the last robot who made the last touch
Robot byBot = game.getRobot(touch.by());
Robot byBot = game.getRobot(touch.getBy());

//Check if the bot retrieved was in their own half before the ball went out.
if (game.getField().isInOwnHalf(byBot.getTeam().getSide(), touch.endLocation().xy())
if (game.getField().isInOwnHalf(byBot.getTeam().getSide(), touch.getEndLocation().xy())
&& game.getTime() - lastViolation > GRACE_PERIOD) {

//If the ball left the right goal line and the side of the bot was left then an aimless kick happened.
if (game.getBall().getPosition().getX() > rightGoalLine.p1().getX()
&& byBot.getTeam().getSide() == Side.LEFT) {
lastViolation = game.getTime();
return new Violation(byBot.getTeam().getColor(), byBot.getId(), game.getBall().getPosition().xy(), touch.endLocation().xy());
return new Violation(byBot.getTeam().getColor(), byBot.getId(), game.getBall().getPosition().xy(), touch.getEndLocation().xy());
}

//If the ball left the left goal line and the side of the bot was right then an aimless kick happened.
if (game.getBall().getPosition().getX() < leftGoalLine.p1().getX()
&& byBot.getTeam().getSide() == Side.RIGHT) {
lastViolation = game.getTime();
return new Violation(byBot.getTeam().getColor(), byBot.getId(), game.getBall().getPosition().xy(), touch.endLocation().xy());
return new Violation(byBot.getTeam().getColor(), byBot.getId(), game.getBall().getPosition().xy(), touch.getEndLocation().xy());
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,15 +24,15 @@ public RuleViolation validate(Game game) {
return null;
}

Robot robot = game.getRobot(kickIntoPlay.by());
Robot robot = game.getRobot(kickIntoPlay.getBy());
Touch currentTouch = robot.getTouch();

// Ball should move 0.05 meters before "in play", then another 0.05 meters before it's a violation.
float distance = kickIntoPlay.isFinished() ? 0.05f : 0.10f;

if (!triggered && currentTouch != null && game.getBall().getPosition().distance(kickIntoPlay.startLocation()) >= distance) {
if (!triggered && currentTouch != null && game.getBall().getPosition().distance(kickIntoPlay.getStartLocation()) >= distance) {
triggered = true;
return new Violation(robot.getTeam().getColor(),robot.getIdentifier(), game.getKickIntoPlay().startLocation().xy());
return new Violation(robot.getTeam().getColor(),robot.getIdentifier(), game.getKickIntoPlay().getStartLocation().xy());
}

return null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ public RuleViolation validate(Game game) {
return null;
}

RobotIdentifier byBot = game.getLastStartedTouch().by();
RobotIdentifier byBot = game.getLastStartedTouch().getBy();
if (game.getTime() - lastViolations > GRACE_PERIOD) {
lastViolations = game.getTime();
return new Violation(byBot.teamColor(), byBot.id(), ball.xy());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ public RuleViolation validate(Game game) {
return null;
}

RobotIdentifier byBot = game.getLastStartedTouch().by();
RobotIdentifier byBot = game.getLastStartedTouch().getBy();
if (game.getTime() - lastViolations > GRACE_PERIOD) {
lastViolations = game.getTime();
return new Violation(byBot.teamColor(), byBot.id(), ball.xy());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,9 @@ public RuleViolation validate(Game game) {
}

for (Touch touch : game.getFinishedTouches()) {
Vector2 startLocation = touch.startLocation().xy();
Vector2 endLocation = touch.endLocation().xy();
Robot robot = game.getRobot(touch.by());
Vector2 startLocation = touch.getStartLocation().xy();
Vector2 endLocation = touch.getEndLocation().xy();
Robot robot = game.getRobot(touch.getBy());
float dist = startLocation.distance(endLocation);

if (dist <= 1) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ public RuleViolation validate(Game game) {

// If speed in one frame is higher than 6.5 m/s, ball was kicked too fast by the bot.
if (speed > 6.5) {
RobotIdentifier robotID = game.getLastStartedTouch().by();
RobotIdentifier robotID = game.getLastStartedTouch().getBy();
TeamColor team = robotID.teamColor();
Vector2 location = ball.getPosition().xy();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ public RuleViolation validate(Game game) {

triggered = true;
if (touch != null) {
Robot byBot = game.getRobot(touch.by());
Robot byBot = game.getRobot(touch.getBy());
return new Violation(byBot.getTeam().getColor(), location);
} else {
return new Violation(null, location);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,9 @@ public RuleViolation validate(Game game) {
FieldLine penaltyStretch = game.getField().getLineByName(sideString + "PenaltyStretch");
FieldLine rightPenaltyStretch = game.getField().getLineByName(sideString + "FieldRightPenaltyStretch");
FieldLine leftPenaltyStretch = game.getField().getLineByName(sideString + "FieldLeftPenaltyStretch");
float dist = Math.min(Math.abs(game.getLastStartedTouch().startLocation().getX() - penaltyStretch.p1().getX()), Math.min(Math.abs( game.getLastStartedTouch().startLocation().getY() - rightPenaltyStretch.p1().getY()), Math.abs(game.getLastStartedTouch().startLocation().getY() - leftPenaltyStretch.p1().getY())));
float dist = Math.min(Math.abs(game.getLastStartedTouch().getStartLocation().getX() - penaltyStretch.p1().getX()),
Math.min(Math.abs( game.getLastStartedTouch().getStartLocation().getY() - rightPenaltyStretch.p1().getY()),
Math.abs(game.getLastStartedTouch().getStartLocation().getY() - leftPenaltyStretch.p1().getY())));
if (!botStillOnCoolDown(robot.getIdentifier(), game.getTime())) {
lastViolations.put(robot.getIdentifier(), game.getTime());
return new Violation(robot.getTeam().getColor(), robot.getId(), robot.getPosition().xy(), dist);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,12 @@ public RuleViolation validate(Game game) {

// if last finished touch was by goalkeeper
Touch touch = game.getLastFinishedTouch();
if (touch.by().teamColor() != game.getStateForTeam() && game.getTeam(game.getStateForTeam().getOpponentColor()).getGoalkeeperId() == touch.by().id()) {
if (touch.deflectionAngle() >= 90.0f) {
valid = false;
return new Violation(touch.by().teamColor(), game.getBall().getPosition().xy(),
"defending goalkeeper changed angle of velocity of ball by " + touch.deflectionAngle() + " degrees");
}
if (touch.getBy().teamColor() != game.getStateForTeam() && touch.deflectionAngle() >= 90.0f &&
game.getTeam(game.getStateForTeam().getOpponentColor()).getGoalkeeperId() == touch.getBy().id()) {
valid = false;
return new Violation(touch.getBy().teamColor(), game.getBall().getPosition().xy(),
"defending goalkeeper changed angle of velocity of ball by " + touch.deflectionAngle() + " degrees");

}

return null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,18 +33,18 @@ boolean checkBallInsideGoal(Game game, Side side, Vector2 ballPos) {
FieldLine fieldLine = game.getField().getLineByName(fieldLineName);
if (fieldLine != null) {
// LeftToRightCoefficient if leftPenaltyStretch is positive otherwise negative
float LeftToRightCoefficient = 1;
float leftToRightCoefficient = 1;
if (fieldLine.p1().getY() >= 0) {
LeftToRightCoefficient = 1;
leftToRightCoefficient = 1;
} else {
LeftToRightCoefficient = -1;
leftToRightCoefficient = -1;
}
float leftPostP1x = fieldLine.p1().getX();
float leftPostP1y = (goalWidthLength/2) * LeftToRightCoefficient;
float leftPostP1y = (goalWidthLength/2) * leftToRightCoefficient;

float leftPostP2x = leftPostP1x + side.getCardinality()*goalDepthLength;

float rightPostP1y = (goalWidthLength/2) * LeftToRightCoefficient * -1;
float rightPostP1y = (goalWidthLength/2) * leftToRightCoefficient * -1;

// Check if ball inside right goal
if ((ballPos.getY() >= Math.min(rightPostP1y, leftPostP1y)) && (ballPos.getY() <= Math.max(rightPostP1y, leftPostP1y))
Expand All @@ -69,10 +69,10 @@ public RuleViolation validate(Game game) {
}
Side ballSide = ballPos.getX() < 0 ? Side.LEFT : Side.RIGHT;
if (checkBallInsideGoal(game, ballSide, ballPos)) {
Vector2 kickLocation = touch.endLocation().xy();
RobotIdentifier kickBot = touch.by();
Vector2 kickLocation = touch.getEndLocation().xy();
RobotIdentifier kickBot = touch.getBy();
TeamColor kickingTeam = kickBot.teamColor();
double lastTouchTimeStampByTeam = touch.endTime();
double lastTouchTimeStampByTeam = touch.getEndTime();
TeamColor byTeam;

// Scoring team is the opposite team of the team owns the side
Expand Down

0 comments on commit 4152b08

Please sign in to comment.