/** * @author Frank Zeyda, Kun Wei */ package scjlibs.examples.hijac.cdx; import javax.realtime.AperiodicParameters; import javax.realtime.PriorityParameters; import javax.realtime.PriorityScheduler; //import javax.realtime.ImmortalMemory; //import javax.safetycritical.AperiodicEvent; import javax.safetycritical.AperiodicEventHandler; //import javax.safetycritical.Mission; import javax.safetycritical.StorageParameters; import scjlibs.examples.hijac.cdx.Aircraft; import scjlibs.examples.hijac.cdx.CDxMission; import scjlibs.examples.hijac.cdx.CallSign; import scjlibs.examples.hijac.cdx.Constants; import scjlibs.examples.hijac.cdx.DetectorControl; import scjlibs.examples.hijac.cdx.Motion; import scjlibs.examples.hijac.cdx.PersistentData; import scjlibs.examples.hijac.cdx.RawFrame; import scjlibs.examples.hijac.cdx.Reducer; import scjlibs.examples.hijac.cdx.Vector3d; import scjlibs.util.ArrayList; import scjlibs.util.HashMap; import scjlibs.util.Iterator; import scjlibs.util.LinkedList; import scjlibs.util.List; /** * ReducerHandler performs two preparational tasks prior to the parallel * detection phase. First, it carries out voxel hashing which results in * aircrafts being assigned to voxels in a way that it is sufficient to check * for collisions within each voxel in order to obtain an upper bound on the * number of actual collisions. Secondly, it divides and distributes the * computational work between the parallel DetectorHandler instances. */ public class ReducerHandler extends AperiodicEventHandler { public final CDxMission mission; public final AperiodicEventHandler[] detectHandlers; public final DetectorControl control; // public final AperiodicEvent detect; /** * Pseudo object factory to manage pre-allocated objects in mission memory. */ public final PersistentData factories; // public ReducerHandler( // CDxMission mission, AperiodicEvent event, DetectorControl control) { public ReducerHandler(CDxMission mission, AperiodicEventHandler[] eventHandlers, DetectorControl control) { super(new PriorityParameters(PriorityScheduler.instance() .getNormPriority()), new AperiodicParameters(), new StorageParameters(Constants.REDUCER_HANDLER_BS_SIZE, null, 0, 0), Constants.REDUCER_HANDLER_SCOPE_SIZE, "ReducerHandler"); this.mission = mission; // this.detect = event; // this.control = control; this.detectHandlers = eventHandlers; this.control = control; /* * The use of newI() below is part of a work-around due to using a * reference implementation in which the mission object resides in * immortal memory rather than mission memory. */ // factories = (PersistentData) MemUtils.newI(PersistentData.class); // For now, there is no MissionMemory in JOP factories = new PersistentData(); } @Override public void handleAsyncEvent() { System.out.println("[ReducerHandler] called"); /* Signal that detectors are busy. */ mission.simulator.detectorReady = false; /* Clear the number of collisions (set to zero). */ mission.initColls(); /* Discard partitioning of computational work. */ mission.getWork().clear(); /* Release all objects in mission memory managed by the factories. */ factories.getListFactory().clear(); factories.getMotionFactory().clear(); /* Generate a list of Motion objects from currentFrame and state. */ final List<Motion> motions = createMotions(); // System.out.println("Motions: " + motions.size()); /* The Reducer class carries out the voxel hashing algorithm. */ final Reducer reducer = new Reducer(Constants.GOOD_VOXEL_SIZE); /* Utility method that initiates the reduction step. */ reduceAndPartitionMotions(reducer, motions); /* Initialise the detector control object. */ control.start(); /* Release all detector handlers. */ // detect.fire(); for (int i = 0; i < detectHandlers.length; i++) { detectHandlers[i].release(); } } /** * Creates a list of persistent Motion objects (in mission memory) from the * current and previous aircraft positions in currentFrame and state. We * note that though the returned list is allocated in per release memory, * the Motion objects being elements of the list live in mission memory. */ public List<Motion> createMotions() { List<Motion> result = new LinkedList<Motion>(); Aircraft aircraft; Vector3d new_pos; RawFrame currentFrame = mission.getFrame(); for (int i = 0, pos = 0; i < currentFrame.planeCnt; i++) { /* Get the current position of the next aircraft. */ final float x = currentFrame.positions[3 * i]; final float y = currentFrame.positions[3 * i + 1]; final float z = currentFrame.positions[3 * i + 2]; /* Get the call sign of the next aircraft. */ final byte[] cs = new byte[Constants.LENGTH_OF_CALLSIGN]; for (int j = 0; j < cs.length; j++) { cs[j] = currentFrame.callsigns[pos + j]; } /* Advance index for callsign. */ pos += cs.length; /* Get the last known position of this aircraft. */ final Vector3d old_pos = mission.getState().get(new CallSign(cs)); /* Allocated aircraft in per release memory. */ aircraft = new Aircraft(cs); /* Allocated new position in per release memory. */ new_pos = new Vector3d(x, y, z); /* Obtain pre-allocated Motion object. */ Motion motion = factories.getMotionFactory().getNewMotion(); if (old_pos == null) { /* If no previous position recorded use current position. */ motion.copyfrom(aircraft, new_pos, new_pos); } else { /* Otherwise record current and previous position. */ motion.copyfrom(aircraft, old_pos, new_pos); } /* Add motion object to the resulting list. */ result.add(motion); } return result; } public void reduceAndPartitionMotions(Reducer reducer, List<Motion> motions) { HashMap<Vector2d, ArrayList<?>> voxel_map = new HashMap<Vector2d, ArrayList<?>>( 128); HashMap<Vector2d, String> graph_colors = new HashMap<Vector2d, String>( 128); /* Perform the voxel hashing using the Reducer instance. */ for (Iterator<Motion> iter = motions.iterator(); iter.hasNext();) { reducer.performVoxelHashing((Motion) iter.next(), voxel_map, graph_colors); } /* Distributes the voxel motion lists between the detector handlers. */ for (Iterator<ArrayList<?>> iter = voxel_map.values().iterator(); iter .hasNext();) { List voxel_motions = (List) iter.next(); if (voxel_motions.size() > 1) { /* Obtain pre-allocated List object. */ List list = factories.getListFactory().getNewList(); /* Copy elements from voxel_motions. */ list.addAll(voxel_motions); /* Assign motion list to one of the detector handlers. */ mission.getWork().recordMotionList(list); } } } }