Commit 326d832c authored by MarkG's avatar MarkG Committed by TIGERs GitLab
Browse files

Resolve "Fix dribbling detection starting point"

Closes #1715

See merge request main/Sumatra!1481

sumatra-commit: f03a7672cc84516e4731311b7a8c7e91a008dd50
parent 6c204620
Pipeline #17311 failed with stage
in 11 minutes and 34 seconds
/*
* Copyright (c) 2009 - 2021, DHBW Mannheim - TIGERs Mannheim
* Copyright (c) 2009 - 2022, DHBW Mannheim - TIGERs Mannheim
*/
package edu.tigers.autoreferee;
......@@ -18,11 +18,12 @@ public enum EAutoRefShapesLayer implements IShapeLayer
LAST_BALL_CONTACT_EXT("Ball Contact ext", "AutoReferee", false),
BALL_LEFT_FIELD("Ball Left Field", "AutoReferee", true),
ALLOWED_DISTANCES("Allowed Distances", "AutoReferee", true),
ALLOWED_DRIBBLING_DISTANCE("Allowed Dribbling Distances", "AutoReferee", true),
VIOLATED_DISTANCES("Violated Distances", "AutoReferee", true),
MODE("AutoRef Mode", "AutoReferee", true),
PUSHING("Pushing Detector", "AutoReferee", true),
PASS_DETECTION("Pass Detection", "AutoReferee", true),
;
private final String id;
......@@ -38,33 +39,33 @@ public enum EAutoRefShapesLayer implements IShapeLayer
this.visible = visible;
id = EAutoRefShapesLayer.class.getCanonicalName() + name();
}
@Override
public String getCategory()
{
return category;
}
@Override
public String getLayerName()
{
return name;
}
@Override
public String getId()
{
return id;
}
@Override
public boolean isVisibleByDefault()
{
return visible;
}
}
/*
* Copyright (c) 2009 - 2018, DHBW Mannheim - TIGERs Mannheim
* Copyright (c) 2009 - 2022, DHBW Mannheim - TIGERs Mannheim
*/
package edu.tigers.autoreferee.engine.detector;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import com.github.g3force.configurable.Configurable;
import edu.tigers.autoreferee.EAutoRefShapesLayer;
import edu.tigers.autoreferee.generic.BotPosition;
import edu.tigers.sumatra.drawable.DrawableCircle;
import edu.tigers.sumatra.geometry.Geometry;
import edu.tigers.sumatra.ids.BotID;
import edu.tigers.sumatra.math.vector.IVector2;
import edu.tigers.sumatra.referee.data.EGameState;
import edu.tigers.sumatra.referee.gameevent.BotDribbledBallTooFar;
import edu.tigers.sumatra.referee.gameevent.IGameEvent;
import java.awt.Color;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;
/**
* Detect if bots dribble the ball over a large distance.
......@@ -25,57 +29,63 @@ public class DribblingDetector extends AGameEventDetector
{
@Configurable(comment = "[mm] Any dribbling distance above this value is considered a violation", defValue = "1000.0")
private static double maxDribblingLength = 1000.0;
private final Map<BotID, BotPosition> currentContacts = new HashMap<>();
private final Map<BotID, IVector2> currentContacts = new HashMap<>();
public DribblingDetector()
{
super(EGameEventDetectorType.DRIBBLING, EGameState.RUNNING);
}
@Override
public Optional<IGameEvent> doUpdate()
{
IVector2 ballPos = getBall().getPos();
List<BotPosition> botsTouchingBall = frame.getBotsTouchingBall();
// add new touching bots
botsTouchingBall.forEach(b -> currentContacts.putIfAbsent(b.getBotID(), b));
botsTouchingBall.stream()
// bots are considered touching ball quite early, so only accept them here if ball is close
// This is fine here, because we do not need to consider ball reflection
.filter(bp -> bp.getPos().distanceTo(ballPos) < Geometry.getBotRadius() + Geometry.getBallRadius() + 10)
.forEach(bp -> currentContacts.putIfAbsent(bp.getBotID(), ballPos));
// remove vanished touching bots
currentContacts.keySet().removeIf(k -> botsTouchingBall.stream().noneMatch(b -> b.getBotID().equals(k)));
Optional<IGameEvent> gameEvent = botsTouchingBall.stream()
.filter(b -> dribbleDistance(b) > maxDribblingLength)
.findFirst()
.map(this::createViolation);
gameEvent.ifPresent(g -> doReset());
return gameEvent;
}
private IVector2 dribbleStartPosition(final BotID botID)
{
return currentContacts.get(botID).getPos();
currentContacts.values().forEach(this::drawCircle);
Map<BotID, Double> dribbleDistances = currentContacts.entrySet().stream()
.collect(Collectors.toMap(Map.Entry::getKey, e -> dribbleDistance(e.getValue())));
Optional<BotID> violatingBot = dribbleDistances.entrySet().stream()
.filter(e -> e.getValue() > maxDribblingLength)
.min(Map.Entry.comparingByValue())
.map(Map.Entry::getKey);
violatingBot.ifPresent(currentContacts::remove);
return violatingBot.map(botId -> new BotDribbledBallTooFar(botId, currentContacts.get(botId), ballPos));
}
private double dribbleDistance(final BotPosition b)
private void drawCircle(IVector2 pos)
{
return b.getPos().distanceTo(dribbleStartPosition(b.getBotID()));
frame.getShapes().get(EAutoRefShapesLayer.ALLOWED_DRIBBLING_DISTANCE).add(
new DrawableCircle(pos, maxDribblingLength).setColor(Color.red)
);
frame.getShapes().get(EAutoRefShapesLayer.ALLOWED_DRIBBLING_DISTANCE).add(
new DrawableCircle(pos, 10).setColor(Color.red)
);
}
private BotDribbledBallTooFar createViolation(final BotPosition finalBotPosition)
private double dribbleDistance(IVector2 startPos)
{
final BotID violatorId = finalBotPosition.getBotID();
final IVector2 kickPos = dribbleStartPosition(finalBotPosition.getBotID());
return new BotDribbledBallTooFar(violatorId, kickPos, finalBotPosition.getPos());
return startPos.distanceTo(getBall().getPos());
}
@Override
protected void doReset()
{
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment