package org.jactr.modules.pm.visual.memory.impl; /* * default logging */ import java.util.HashSet; import java.util.Set; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.commonreality.identifier.IIdentifier; import org.jactr.core.chunk.IChunk; import org.jactr.core.logging.Logger; import org.jactr.core.model.IModel; import org.jactr.core.queue.timedevents.RunnableTimedEvent; import org.jactr.core.runtime.ACTRRuntime; import org.jactr.modules.pm.common.memory.IActivePerceptListener; import org.jactr.modules.pm.visual.IVisualModule; import org.jactr.modules.pm.visual.buffer.IVisualLocationBuffer; import org.jactr.modules.pm.visual.event.VisualModuleEvent; public class DefaultPerceptListener implements IActivePerceptListener { /** * Logger definition */ static private final transient Log LOGGER = LogFactory .getLog(DefaultPerceptListener.class); private IVisualModule _module; private Set<IIdentifier> _trackedObjects; public DefaultPerceptListener(IVisualModule module) { _module = module; _trackedObjects = new HashSet<IIdentifier>(); } public void addTrackedIdentifier(IIdentifier identifier) { _trackedObjects.add(identifier); } public void removeTrackedIdentifier(IIdentifier identifier) { _trackedObjects.remove(identifier); } public void clearTrackedIdentifiers() { _trackedObjects.clear(); } public void reencoded(final IIdentifier identifier, final IChunk oldChunk, IChunk newChunk) { /* * its normal to get the reencoded event after removing the chunk from the * buffer */ if (oldChunk.isEncoded()) return; IModel model = _module.getModel(); if (model.getDeclarativeModule().willEncode(oldChunk)) return; if (Logger.hasLoggers(model) || LOGGER.isDebugEnabled()) { StringBuilder sb = new StringBuilder("Percept underlying "); sb.append(oldChunk).append(" has changed too much. (").append(identifier) .append(")"); String msg = sb.toString(); if (Logger.hasLoggers(model)) Logger.log(model, Logger.Stream.VISUAL, msg); else LOGGER.debug(msg); } IChunk error = _module.getModel().getDeclarativeModule().getErrorChunk(); _module.getVisualActivationBuffer().setStateChunk(error); _module.getVisualActivationBuffer().setExecutionChunk(error); } public void removed(final IIdentifier identifier, final IChunk chunk) { /* * and set error. we do this on the model thread just in case there are * buffer changes currently going on.. */ removeTrackedIdentifier(identifier); if (chunk.isEncoded()) return; /* * log */ IModel model = _module.getModel(); if (model.getDeclarativeModule().willEncode(chunk)) return; if (Logger.hasLoggers(model) || LOGGER.isDebugEnabled()) { StringBuilder sb = new StringBuilder("Percept underlying "); sb.append(chunk).append(" is no longer visible. (").append(identifier) .append(")"); String msg = sb.toString(); if (Logger.hasLoggers(model)) Logger.log(model, Logger.Stream.VISUAL, msg); else LOGGER.debug(msg); } IChunk error = _module.getModel().getDeclarativeModule().getErrorChunk(); _module.getVisualActivationBuffer().setStateChunk(error); _module.getVisualActivationBuffer().setExecutionChunk(error); } public void updated(IIdentifier identifier, IChunk chunk) { /* * first log that the chunk has changed. */ IModel model = _module.getModel(); if (Logger.hasLoggers(model) || LOGGER.isDebugEnabled()) { StringBuilder sb = new StringBuilder("Percept underlying "); sb.append(chunk).append(" has changed. (").append(identifier).append(")"); String msg = sb.toString(); if (Logger.hasLoggers(model)) Logger.log(model, Logger.Stream.VISUAL, msg); if (LOGGER.isDebugEnabled()) LOGGER.debug(msg); } double start = ACTRRuntime.getRuntime().getClock(model).getTime(); /* * if the chunk is tracked, we need to update the visuallocation buffer */ if (_trackedObjects.contains(identifier)) { final IChunk visualLocation = (IChunk) chunk.getSymbolicChunk().getSlot( IVisualModule.SCREEN_POSITION_SLOT); IVisualLocationBuffer buffer = _module.getVisualLocationBuffer(); if (visualLocation != null && visualLocation.equals(buffer.getCurrentVisualLocation())) { /* * fire off the event on this thread (CR) */ if (_module.hasListeners()) _module.dispatch(new VisualModuleEvent(_module, VisualModuleEvent.Type.TRACKING_MOVED, chunk)); if (LOGGER.isDebugEnabled()) LOGGER.debug("shifting visual location from " + buffer.getCurrentVisualLocation() + " to " + visualLocation); /* * do the assignment on the model thread, not here */ buffer.addSourceChunk(visualLocation); model.getTimedEventQueue().enqueue( new RunnableTimedEvent(start, new Runnable() { public void run() { _module.getVisualLocationBuffer() .addSourceChunk(visualLocation); } })); } } /* * now we need to set the buffer as busy for 50ms */ double end = start + 0.05; model.getTimedEventQueue().enqueue( new RunnableTimedEvent(start, new Runnable() { public void run() { _module.getVisualActivationBuffer().setExecutionChunk( _module.getModel().getDeclarativeModule().getBusyChunk()); } })); model.getTimedEventQueue().enqueue( new RunnableTimedEvent(end, new Runnable() { public void run() { _module.getVisualActivationBuffer().setExecutionChunk( _module.getModel().getDeclarativeModule().getFreeChunk()); } })); } public void newPercept(IIdentifier identifier, IChunk chunk) { /* * flag the percept as new.. */ // removed into anonymous inner in default visual module // so that it can be accessed immediately after the chunk is available // IFINSTFeatureMap finstMap = // _module.getVisualMemory().getFINSTFeatureMap(); // if (finstMap != null && !finstMap.isAttended(identifier)) // finstMap.flagAsNew(identifier, chunk, _module.getVisualMemory() // .getOnsetDuration()); } }