Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix/botdribbledballtoofar #19

Merged
merged 6 commits into from
Jun 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading