Skip to content

Commit

Permalink
clean(perception): Improve generics usage in perception module (#416)
Browse files Browse the repository at this point in the history
Signed-off-by: Moritz Schweppenhäuser <[email protected]>
  • Loading branch information
schwepmo authored Dec 9, 2024
1 parent 8c8817d commit 6650436
Show file tree
Hide file tree
Showing 21 changed files with 135 additions and 88 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -96,8 +96,8 @@ public List<TrafficLightObject> getPerceivedTrafficLights() {
abstract List<TrafficLightObject> getTrafficLightsInRange();

@Override
public List<SpatialObject> getPerceivedObjects() {
List<SpatialObject> objectsInRange = getObjectsInRange();
public List<SpatialObject<?>> getPerceivedObjects() {
List<SpatialObject<?>> objectsInRange = getObjectsInRange();
objectsInRange = applyPerceptionModifiers(objectsInRange);
return objectsInRange;
}
Expand All @@ -108,12 +108,13 @@ public List<SpatialObject> getPerceivedObjects() {
*
* @return the raw list of objects in range of the ego vehicle
*/
abstract List<SpatialObject> getObjectsInRange();
abstract List<SpatialObject<?>> getObjectsInRange();

private <T extends SpatialObject<T>> List<T> applyPerceptionModifiers(List<T> objectsInRange) {
private <T extends SpatialObject<?>> List<T> applyPerceptionModifiers(List<T> objectsInRange) {
List<T> filteredList = new ArrayList<>(objectsInRange);
// create a copy of all perceived objects to avoid interference with modifiers of other perception modules.
filteredList.replaceAll(T::copy);
//noinspection unchecked
filteredList.replaceAll(object -> (T) object.copy());
for (PerceptionModifier perceptionModifier : configuration.getPerceptionModifiers()) {
filteredList = perceptionModifier.apply(owner, filteredList); // apply filters in sequence
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ List<TrafficLightObject> getTrafficLightsInRange() {
}

@Override
List<SpatialObject> getObjectsInRange() {
List<SpatialObject<?>> getObjectsInRange() {
log.debug("No vehicle index configured, leading to disabled perception.");
return new ArrayList<>();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ public interface PerceptionModel {
/**
* Checks, if the other spatial object is within this perception range.
*/
boolean isInRange(SpatialObject other);
boolean isInRange(SpatialObject<?> other);

/**
* Returns the minimum bounding box around this perception area. This is used for range search queries in the perception index.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -86,14 +86,14 @@ public List<TrafficLightObject> getTrafficLightsInRange() {
}

@Override
public List<SpatialObject> getObjectsInRange() {
public List<SpatialObject<?>> getObjectsInRange() {
if (perceptionModel == null || owner.getVehicleData() == null) {
log.warn("No perception model initialized.");
return Lists.newArrayList();
}
perceptionModel.updateOrigin(owner.getVehicleData().getProjectedPosition(), owner.getVehicleData().getHeading());
SimulationKernel.SimulationKernel.getCentralPerceptionComponent().updateSpatialIndices();
List<SpatialObject> objectsInRange = new ArrayList<>();
List<SpatialObject<?>> objectsInRange = new ArrayList<>();
objectsInRange.addAll(SimulationKernel.SimulationKernel.getCentralPerceptionComponent()
.getTrafficObjectIndex()
.getVehiclesInRange(perceptionModel));
Expand All @@ -105,7 +105,8 @@ public List<SpatialObject> getObjectsInRange() {

@Override
public Collection<Edge<Vector3d>> getSurroundingWalls() {
return SimulationKernel.SimulationKernel.getCentralPerceptionComponent().getTrafficObjectIndex().getSurroundingWalls(perceptionModel);
return SimulationKernel.SimulationKernel.getCentralPerceptionComponent()
.getTrafficObjectIndex().getSurroundingWalls(perceptionModel);
}

/**
Expand Down Expand Up @@ -157,7 +158,7 @@ public BoundingBox getBoundingBox() {
}

@Override
public boolean isInRange(SpatialObject other) {
public boolean isInRange(SpatialObject<?> other) {
if (other.getId().equals(this.ownerId)) { // cannot see itself
return false;
}
Expand All @@ -167,10 +168,10 @@ public boolean isInRange(SpatialObject other) {
// we use tmpVector2 as origin from the viewpoint of this object
tmpVector2.set(0, 0, 0);

if (tmpVector1.magnitude() > configuration.getViewingRange()) { // other vehicle is NOT in range
if (tmpVector1.magnitude() > configuration.getViewingRange()) { // the other vehicle is NOT in range
return false;
}
if (MathUtils.isFuzzyEqual(configuration.getViewingAngle(), 360d)) { // for 360 degree viewing angle field-of-view check is obsolete
if (MathUtils.isFuzzyEqual(configuration.getViewingAngle(), 360d)) { // for 360° viewing angle FOV check is obsolete
return true;
} else if (configuration.getViewingAngle() < 180d) { // for < 180 degree viewing angle we use left and right vector
return isBetweenVectors(tmpVector1, tmpVector2, leftBoundVector, rightBoundVector)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ public List<TrafficLightObject> getTrafficLightsInRange() {
}

@Override
public List<SpatialObject> getObjectsInRange() {
public List<SpatialObject<?>> getObjectsInRange() {
this.log.debug("Traffic Light Perception not implemented for {} only vehicles will be retrieved.", this.getClass().getSimpleName());
return new ArrayList<>(getVehiclesInRange());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,19 @@
import java.util.ArrayList;
import java.util.List;

/**
* An occlusion modifier for other vehicles configuration is done using {@link #pointsPerSide} and {@link #detectionThreshold}.
* Example for {@code pointsPerSide = 3} (x's are the corners which will be evaluated anyway, o's are the added points):
* <pre>
* x-----o-----x
* | |
* | |
* o o
* | |
* | |
* x-----o-----x
* </pre>
*/
public class BoundingBoxOcclusion implements PerceptionModifier {

private final Vector3d intersectionResult = new Vector3d();
Expand Down Expand Up @@ -58,7 +71,6 @@ public BoundingBoxOcclusion() {
*
* @param pointsPerSide the number of points that will be evaluated per object side (corners count towards 2 edges)
* @param detectionThreshold how many points have to be visible in order for an object to be treated as detected
*
* @throws IllegalArgumentException if pointsPerSide or detectionThreshold is configured wrongly
*/
public BoundingBoxOcclusion(int pointsPerSide, int detectionThreshold) {
Expand All @@ -76,7 +88,7 @@ public BoundingBoxOcclusion(int pointsPerSide, int detectionThreshold) {
}

@Override
public <T extends SpatialObject> List<T> apply(PerceptionModuleOwner owner, List<T> spatialObjects) {
public <T extends SpatialObject<?>> List<T> apply(PerceptionModuleOwner owner, List<T> spatialObjects) {
List<T> newObjects = new ArrayList<>();
// the ego object cannot occlude vision
List<T> occludingObjects = spatialObjects.stream()
Expand Down Expand Up @@ -115,7 +127,8 @@ public <T extends SpatialObject> List<T> apply(PerceptionModuleOwner owner, List
* @param occludingObjects all objects that potentially occlude the vehicle
* @return {@code true} if the point is visible, else {@code false}
*/
private <T extends SpatialObject> boolean isVisible(Vector3d egoPosition, Vector3d pointToEvaluate, String objectId, List<T> occludingObjects) {
private <T extends SpatialObject<?>> boolean isVisible(Vector3d egoPosition, Vector3d pointToEvaluate,
String objectId, List<T> occludingObjects) {
for (T occludingObject : occludingObjects) {
if (occludingObject.getId().equals(objectId)) {
continue; // cannot be occluded by itself
Expand Down Expand Up @@ -146,12 +159,12 @@ private <T extends SpatialObject> boolean isVisible(Vector3d egoPosition, Vector
* o o
* | |
* | |
* x-----o-----y
* x-----o-----x
* </pre>
*
* @param spatialObject a {@link SpatialObject} for which the occlusion should be evaluated
*/
private <T extends SpatialObject> List<Vector3d> createPointsToEvaluate(T spatialObject) {
private <T extends SpatialObject<?>> List<Vector3d> createPointsToEvaluate(T spatialObject) {
List<Vector3d> pointsToEvaluate = new ArrayList<>();
SpatialObjectBoundingBox boundingBox = spatialObject.getBoundingBox();
// if object has edges and more than 2 points per side are to be evaluated, calculate points that have to be evaluated
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,13 +43,26 @@ public class DimensionsModifier implements PerceptionModifier {
private final RandomNumberGenerator rng;


public DimensionsModifier(RandomNumberGenerator rng, double lengthDeviation, double widthDeviation, double heightDeviation) {
/**
* Constructor for {@link DimensionsModifier} given the sigma values for the gaussian distribution applied to different dimensions.
*
* @param rng {@link RandomNumberGenerator} used to generate pseudo-random gaussian numbers
* @param lengthDeviation sigma value for the length
* @param widthDeviation sigma value for the width
* @param heightDeviation sigma value for the height
*/
public DimensionsModifier(RandomNumberGenerator rng, double lengthDeviation, double widthDeviation, double heightDeviation) {
this.rng = rng;
this.lengthDeviation = lengthDeviation;
this.widthDeviation = widthDeviation;
this.heightDeviation = heightDeviation;
}

/**
* Constructor for {@link DimensionsModifier} using default values of 0.2 for the sigma value of the dimensions
*
* @param rng @link RandomNumberGenerator} used to generate pseudo-random gaussian numbers
*/
public DimensionsModifier(RandomNumberGenerator rng) {
this.rng = rng;
this.lengthDeviation = SIGMA_LENGTH_OFFSET;
Expand All @@ -58,7 +71,7 @@ public DimensionsModifier(RandomNumberGenerator rng) {
}

@Override
public <T extends SpatialObject> List<T> apply(PerceptionModuleOwner owner, List<T> spatialObjects) {
public <T extends SpatialObject<?>> List<T> apply(PerceptionModuleOwner owner, List<T> spatialObjects) {
spatialObjects.stream()
.filter(o -> o instanceof VehicleObject)
.forEach(o -> adjustDimensionsOfVehicle((VehicleObject) o));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ public DistanceFilter(RandomNumberGenerator rng, double offset) {
}

@Override
public <T extends SpatialObject> List<T> apply(PerceptionModuleOwner owner, List<T> spatialObjects) {
public <T extends SpatialObject<?>> List<T> apply(PerceptionModuleOwner owner, List<T> spatialObjects) {
if (spatialObjects.isEmpty()) {
return spatialObjects;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,13 @@ public HeadingModifier(RandomNumberGenerator rng) {
this.chanceOfWrongDirection = DEFAULT_CHANCE_WRONG_DIR;
}

/**
* Constructor for the {@link HeadingModifier} using configured values.
*
* @param rng {@link RandomNumberGenerator} for evaluation of probabilities
* @param headingStandardDeviation the sigma value used for the applied heading offset [0, 360]
* @param chanceOfWrongDirection chance for a heading to be rotated by 180° [0, 1]
*/
public HeadingModifier(RandomNumberGenerator rng, double headingStandardDeviation, double chanceOfWrongDirection) {
Validate.inclusiveBetween(0, 360, headingStandardDeviation, "Heading deviation should lie between 0 and 360");
Validate.inclusiveBetween(0, 1, chanceOfWrongDirection, "Wrong direction probability should lie between 0 and 1");
Expand All @@ -69,18 +76,15 @@ public HeadingModifier(RandomNumberGenerator rng, double headingStandardDeviatio
}

@Override
public <T extends SpatialObject> List<T> apply(PerceptionModuleOwner owner, List<T> spatialObjects) {
final Vector3d ownerPosition = owner.getVehicleData().getProjectedPosition().toVector3d();

public <T extends SpatialObject<?>> List<T> apply(PerceptionModuleOwner owner, List<T> spatialObjects) {
spatialObjects.stream()
.filter(o -> o instanceof VehicleObject)
.forEach(o -> adjustHeadingOfVehicle(ownerPosition, (VehicleObject) o));
.forEach(o -> adjustHeadingOfVehicle((VehicleObject) o));

return spatialObjects;
}

private void adjustHeadingOfVehicle(Vector3d ownerPosition, VehicleObject vehicleObject) {

private void adjustHeadingOfVehicle(VehicleObject vehicleObject) {
double oldHeading = vehicleObject.getHeading();

if (rng.nextDouble() < chanceOfWrongDirection) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,5 +27,5 @@ public interface PerceptionModifier {
*
* @return the filtered/modified list
*/
<T extends SpatialObject> List<T> apply(PerceptionModuleOwner owner, List<T> spatialObjects);
<T extends SpatialObject<?>> List<T> apply(PerceptionModuleOwner owner, List<T> spatialObjects);
}
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ public PositionModifier(RandomNumberGenerator rng, double longitudinalStandardDe
}

@Override
public <T extends SpatialObject> List<T> apply(PerceptionModuleOwner owner, List<T> spatialObjects) {
public <T extends SpatialObject<?>> List<T> apply(PerceptionModuleOwner owner, List<T> spatialObjects) {
Vector3d ownerPosition = owner.getVehicleData().getProjectedPosition().toVector3d();
Vector3d ownerDirection = new Vector3d();
VectorUtils.getDirectionVectorFromHeading(owner.getVehicleData().getHeading(), ownerDirection);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,13 +62,13 @@ public SimpleOcclusion(double minDetectionAngle, double maxDetectionAngle) {
}

@Override
public <T extends SpatialObject> List<T> apply(PerceptionModuleOwner owner, List<T> spatialObjects) {
public <T extends SpatialObject<?>> List<T> apply(PerceptionModuleOwner owner, List<T> spatialObjects) {
if (spatialObjects.isEmpty()) {
return spatialObjects;
}
Vector3d ownerPosition = owner.getVehicleData().getProjectedPosition().toVector3d();
// sort by distances
List<SpatialObject> sortedByDistance = new ArrayList<>(spatialObjects);
List<T> sortedByDistance = new ArrayList<>(spatialObjects);
sortedByDistance.sort(Comparator.comparingDouble(vehicleObject -> vehicleObject.getPosition().distanceTo(ownerPosition)));
// fit linear function to (closest distance, min angle) and (furthest distance, max angle)
double closestPerceivedDistance = ownerPosition.distanceTo(sortedByDistance.get(0).getPosition());
Expand All @@ -81,7 +81,7 @@ public <T extends SpatialObject> List<T> apply(PerceptionModuleOwner owner, List
double m = (maxDetectionAngle - minDetectionAngle) / (furthestPerceivedDistance - closestPerceivedDistance);
double n = minDetectionAngle - (closestPerceivedDistance * m);

List<SpatialObject> notOccludedObjects = new ArrayList<>();
List<T> notOccludedObjects = new ArrayList<>();
List<Vector3d> nonOccludedVectors = new ArrayList<>();
notOccludedObjects.add(sortedByDistance.get(0)); // closest vehicle is always perceived
nonOccludedVectors.add(getVectorRelativeTo(ownerPosition, sortedByDistance.get(0).getPosition()));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@
public class WallOcclusion implements PerceptionModifier {

@Override
public <T extends SpatialObject> List<T> apply(PerceptionModuleOwner owner, List<T> spatialObjects) {
public <T extends SpatialObject<?>> List<T> apply(PerceptionModuleOwner owner, List<T> spatialObjects) {
if (spatialObjects.isEmpty()) {
return spatialObjects;
}
Expand Down
Loading

0 comments on commit 6650436

Please sign in to comment.