/** * */ package iamrescue.belief.inference; import iamrescue.agent.ISimulationTimer; import iamrescue.belief.IAMWorldModel; import iamrescue.belief.entities.RoutingInfoBlockade; import iamrescue.belief.provenance.IPropertyMerger; import iamrescue.belief.provenance.InferredOrigin; import iamrescue.belief.provenance.ProvenanceLogEntry; import iamrescue.belief.spatial.ISpatialIndex; import java.util.Collection; import java.util.List; import java.util.Set; import javolution.util.FastList; import javolution.util.FastSet; import org.apache.log4j.Logger; import rescuecore2.config.Config; import rescuecore2.misc.Pair; import rescuecore2.misc.geometry.GeometryTools2D; import rescuecore2.misc.geometry.Line2D; import rescuecore2.misc.geometry.Point2D; import rescuecore2.standard.entities.Blockade; import rescuecore2.standard.entities.Building; import rescuecore2.standard.entities.Human; import rescuecore2.standard.entities.StandardEntity; import rescuecore2.standard.entities.StandardPropertyURN; import rescuecore2.worldmodel.ChangeSet; import rescuecore2.worldmodel.EntityID; import rescuecore2.worldmodel.Property; /** * @author Sebastian * */ public class NegativeSenseUpdater implements INegativeSenseUpdater { private static final int DEFAULT_VIEW_DISTANCE = 30000; public static final String VIEW_DISTANCE_KEY = "perception.los.max-distance"; private static final List<String> HUMAN_PROPERTIES = new FastList<String>(); private static final List<String> BLOCKADE_PROPERTIES = new FastList<String>(); private int viewDistance; private EntityID myself; private IAMWorldModel worldModel; private ISimulationTimer timer; private IPropertyMerger propertyMerger; private static final Logger LOGGER = Logger .getLogger(NegativeSenseUpdater.class); public NegativeSenseUpdater(Config config, IAMWorldModel worldModel, EntityID myself, ISimulationTimer timer, IPropertyMerger propertyMerger) { viewDistance = config.getIntValue(VIEW_DISTANCE_KEY, DEFAULT_VIEW_DISTANCE); this.worldModel = worldModel; this.myself = myself; // this.spatialIndex = spatialIndex; this.timer = timer; this.propertyMerger = propertyMerger; } public ChangeSet removeUnseenEntities(ChangeSet seen) { ChangeSet changes = new ChangeSet(); Set<EntityID> seenIDs = seen.getChangedEntities(); StandardEntity me = worldModel.getEntity(myself); Pair<Integer, Integer> location = me.getLocation(worldModel); // SpatialQuery humanQuery = SpatialQueryFactory.queryWithinDistance( // new PositionXY(location), viewDistance, Human.class); // Now check blockades // SpatialQuery blockadeQuery = SpatialQueryFactory.queryWithinDistance( // new PositionXY(location), viewDistance, Blockade.class); Collection<StandardEntity> potentialInRange = worldModel .getObjectsInRange(myself, viewDistance); Set<StandardEntity> inRange = new FastSet<StandardEntity>(); // inRange.addAll(spatialIndex.query(humanQuery)); // inRange.addAll(spatialIndex.query(blockadeQuery)); for (StandardEntity standardEntity : potentialInRange) { if ((standardEntity instanceof Human || standardEntity instanceof Blockade) && standardEntity.getLocation(worldModel) != null) { inRange.add(standardEntity); } } Collection<Line2D> blockingLines = getBlockingLines(potentialInRange); // Check if I should be able to see these. Set<StandardEntity> expectedButNotSeen = new FastSet<StandardEntity>(); for (StandardEntity standardEntity : inRange) { if (seenIDs.contains(standardEntity.getID())) { continue; } Pair<Integer, Integer> otherLocation = standardEntity .getLocation(worldModel); if (LOGGER.isTraceEnabled()) { LOGGER.trace("Checking " + standardEntity.getFullDescription()); } Line2D lineToHuman = new Line2D(new Point2D(location.first(), location.second()), new Point2D(otherLocation.first(), otherLocation.second())); boolean blocked = false; for (Line2D line : blockingLines) { double d1 = line.getIntersection(lineToHuman); double d2 = lineToHuman.getIntersection(line); if (d2 >= 0 && d2 <= 1 && d1 >= 0 && d1 <= 1) { // blocked! blocked = true; break; } } if (!blocked) { expectedButNotSeen.add(standardEntity); } } for (StandardEntity unknown : expectedButNotSeen) { if (unknown instanceof Human) { processUnknownHuman(unknown, changes); } else { processUnknownBlockade(unknown, changes); } } return changes; } private void processUnknown(StandardEntity entity, List<String> propertyURNs, ChangeSet changed) { for (String propertyURN : propertyURNs) { Property property = entity.getProperty(propertyURN); if (property != null) { Property newProperty = property.copy(); newProperty.undefine(); if (LOGGER.isTraceEnabled()) { LOGGER.trace("Undefined " + newProperty + " of " + entity.getFullDescription()); } ProvenanceLogEntry entry = new ProvenanceLogEntry(timer .getTime(), InferredOrigin.INSTANCE, newProperty); worldModel.storeProvenance(entity.getID(), entry); Property decidedValue = propertyMerger.decideValue(worldModel .getProvenance(entity.getID(), propertyURN)); if (!decidedValue.isDefined()) { if (property.isDefined()) { changed.addChange(entity.getID(), propertyURN, decidedValue); } } if (decidedValue.isDefined()) { property.takeValue(decidedValue); } else { property.undefine(); } } } } private void processUnknownHuman(StandardEntity unknown, ChangeSet changed) { processUnknown(unknown, HUMAN_PROPERTIES, changed); } private void processUnknownBlockade(StandardEntity unknown, ChangeSet changed) { processUnknown(unknown, BLOCKADE_PROPERTIES, changed); } /** * @param potentialInRange * @param location * @return */ private Collection<Line2D> getBlockingLines( Collection<StandardEntity> potentialInRange) { // SpatialQuery query = SpatialQueryFactory.queryWithinDistance( // new PositionXY(location), viewDistance, Building.class); // Collection<StandardEntity> inRange = spatialIndex.query(query); Collection<Line2D> result = new FastSet<Line2D>(); for (StandardEntity se : potentialInRange) { if (se instanceof Building) { int[] apexes = ((Building) se).getApexList(); List<Point2D> points = GeometryTools2D .vertexArrayToPoints(apexes); List<Line2D> lines = GeometryTools2D .pointsToLines(points, true); result.addAll(lines); } } return result; } static { HUMAN_PROPERTIES.add(StandardPropertyURN.POSITION.toString()); HUMAN_PROPERTIES.add(StandardPropertyURN.X.toString()); HUMAN_PROPERTIES.add(StandardPropertyURN.Y.toString()); BLOCKADE_PROPERTIES.add(StandardPropertyURN.APEXES.toString()); BLOCKADE_PROPERTIES.add(RoutingInfoBlockade.BLOCK_INFO_URN); BLOCKADE_PROPERTIES.add(StandardPropertyURN.EDGES.toString()); } }