/**
* This file is part of miniCDx benchmark for oSCJ.
*
* miniCDx is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* miniCDx is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with miniCDx. If not, see <http://www.gnu.org/licenses/>.
*
*
* Copyright 2009, 2010
* @authors Daniel Tang, Ales Plsek
*
* See: http://sss.cs.purdue.edu/projects/oscj/
*/
package minicdj.cdx;
import minicdj.collision.Vector3d;
import minicdj.util.HashMap;
import minicdj.util.HashSet;
import minicdj.util.Iterator;
import minicdj.util.LinkedList;
import minicdj.util.List;
/**
* The constructor runs and the instance lives in the persistent detector scope.
* The state table passed to it lives in the persistent detector scope. The
* thread runs in transient detector scope. The frame (currentFrame) lives in
* immortal memory. The real collision detection starts here.
*/
/* @javax.safetycritical.annotate.Scope("cdx.Level0Safelet") */
/* @javax.safetycritical.annotate.RunsIn("cdx.CollisionDetectorHandler") */
public class TransientDetectorScopeEntry implements Runnable {
private StateTable state;
private float voxelSize;
private RawFrame currentFrame;
/*
* public TransientDetectorScopeEntry(final StateTable s, final float
* voxelSize) { state = s; this.voxelSize = voxelSize; }
*/
public TransientDetectorScopeEntry(StateTable s, float voxelSize) {
state = s;
this.voxelSize = voxelSize;
}
public void run() {
Benchmarker.set(1);
Benchmarker.set(Benchmarker.RAPITA_REDUCER_INIT);
final Reducer reducer = new Reducer(voxelSize);
Benchmarker.done(Benchmarker.RAPITA_REDUCER_INIT);
Benchmarker.set(Benchmarker.LOOK_FOR_COLLISIONS);
int numberOfCollisions = lookForCollisions(reducer, createMotions());
Benchmarker.done(Benchmarker.LOOK_FOR_COLLISIONS);
if (ImmortalEntry.recordedRuns < ImmortalEntry.maxDetectorRuns) {
ImmortalEntry.detectedCollisions[ImmortalEntry.recordedRuns] = numberOfCollisions;
}
if (Constants.SYNCHRONOUS_DETECTOR || Constants.DEBUG_DETECTOR) {
devices.Console.println("CD detected " + numberOfCollisions
+ " collisions.");
/*
* for(final Iterator iter = collisions.iterator(); iter.hasNext();)
* { Collision col = (Collision) iter.next(); // fixme update /*
* List aircraft = col.getAircraftInvolved();
* devices.Console.println("CD collision "
* +colIndex+" occured at location "+col.getLocation() +
* " with "+aircraft.size()+" involved aircraft.");
*
* for(final Iterator aiter = aircraft.iterator(); aiter.hasNext();)
* { Aircraft a = (Aircraft) aiter.next();
*
*
*
*
*
* devices.Console.println("CD collision "+colIndex+" includes aircraft "+
* a); }
*/
/*
* colIndex++; }
*/
devices.Console.println("");
}
Benchmarker.done(1);
}
public int lookForCollisions(final Reducer reducer, final List motions) {
Benchmarker.set(2);
final List check = reduceCollisionSet(reducer, motions);
// final CollisionCollector c = new CollisionCollector();
int suspectedSize = check.size();
if (ImmortalEntry.recordedRuns < ImmortalEntry.maxDetectorRuns) {
ImmortalEntry.suspectedCollisions[ImmortalEntry.recordedRuns] = suspectedSize;
}
int c = 0;
final List ret = new LinkedList();
for (final Iterator iter = check.iterator(); iter.hasNext();)
c += determineCollisions((List) iter.next(), ret);
Benchmarker.done(2);
return c; // .getCollisions();
}
/**
* Takes a List of Motions and returns an List of Lists of Motions, where
* the inner lists implement RandomAccess. Each Vector of Motions that is
* returned represents a set of Motions that might have collisions.
*/
public List reduceCollisionSet(final Reducer it, final List motions) {
Benchmarker.set(3);
final HashMap voxel_map = new HashMap();
final HashMap graph_colors = new HashMap();
for (final Iterator iter = motions.iterator(); iter.hasNext();)
it.performVoxelHashing((Motion) iter.next(), voxel_map,
graph_colors);
final List ret = new LinkedList();
for (final Iterator iter = voxel_map.values().iterator(); iter
.hasNext();) {
final List cur_set = (List) iter.next();
if (cur_set.size() > 1)
ret.add(cur_set);
}
Benchmarker.done(3);
return ret;
}
public boolean checkForDuplicates(final List collisions, Motion one,
Motion two) {
// (Peta) I have also changed the comparison employed in this method as
// it is another major source of overhead
// Java was checking all the callsign elements, while C just checked the
// callsign array addresses
byte c1 = one.getAircraft().getCallsign()[5];
byte c2 = two.getAircraft().getCallsign()[5];
for (final Iterator iter = collisions.iterator(); iter.hasNext();) {
Collision c = (Collision) iter.next();
if ((c.first().getCallsign()[5] == c1)
&& (c.second().getCallsign()[5] == c2)) {
// Benchmarker.done(4);
return false;
}
}
return true;
/*
* old code: Benchmarker.set(4); for (int i=0;i<collisions.size();i++) {
* Collision c=(Collision)collisions.get(i); if
* ((c.first().equals(one.getAircraft())) &&
* (c.second().equals(two.getAircraft()))) { Benchmarker.done(4); return
* false; } } Benchmarker.done(4); return true;
*/
}
public int determineCollisions(final List motions, List ret) {
// (Peta) changed to iterators so that it's not killing the algorithm
Benchmarker.set(5);
int _ret = 0;
Motion[] _motions = (Motion[]) motions.toArray(new Motion[motions
.size()]);
// Motion[] _motions= (Motion)motions.toArray();
for (int i = 0; i < _motions.length - 1; i++) {
final Motion one = _motions[i]; // m2==two, m=one
for (int j = i + 1; j < _motions.length; j++) {
final Motion two = _motions[j];
// if (checkForDuplicates(ret, one, two)) { // This is removed
// because it is very very slow...
final Vector3d vec = one.findIntersection(two);
if (vec != null) {
ret.add(new Collision(one.getAircraft(), two.getAircraft(),
vec));
_ret++;
}
// }
}
}
Benchmarker.done(5);
return _ret;
/*
* Old code: Benchmarker.set(5); int _ret=0; for (int i = 0; i <
* motions.size() - 1; i++) { final Motion one = (Motion)
* motions.get(i); //m2==two, m=one for (int j = i + 1; j <
* motions.size(); j++) { final Motion two = (Motion) motions.get(j); if
* (checkForDuplicates(ret, one, two)) { final Vector3d vec =
* one.findIntersection(two); if (vec != null) { ret.add(new
* Collision(one.getAircraft(), two.getAircraft(), vec)); _ret++; }
*
* } } } Benchmarker.done(5); return _ret; //
*/
}
public void dumpFrame(String debugPrefix) {
String prefix = debugPrefix + frameno + " ";
int offset = 0;
for (int i = 0; i < currentFrame.planeCnt; i++) {
int cslen = currentFrame.lengths[i];
devices.Console.println(prefix
+ new String(currentFrame.callsigns, offset, cslen) + " "
+ currentFrame.positions[3 * i] + " "
+ currentFrame.positions[3 * i + 1] + " "
+ currentFrame.positions[3 * i + 2] + " ");
offset += cslen;
}
}
int frameno = -1; // just for debug
public void setFrame(final RawFrame f) {
if (Constants.DEBUG_DETECTOR || Constants.DUMP_RECEIVED_FRAMES
|| Constants.SYNCHRONOUS_DETECTOR) {
frameno++;
}
currentFrame = f;
if (Constants.DUMP_RECEIVED_FRAMES) {
dumpFrame("CD-R-FRAME: ");
}
}
/**
* This method computes the motions and current positions of the aircraft
* Afterwards, it stores the positions of the aircrafts into the StateTable
* in the persistentScope
*
* @return
*/
public List createMotions() {
Benchmarker.set(6);
final List ret = new LinkedList();
final HashSet poked = new HashSet();
Aircraft craft;
Vector3d new_pos;
for (int i = 0, pos = 0; i < currentFrame.planeCnt; i++) {
final float x = currentFrame.positions[3 * i], y = currentFrame.positions[3 * i + 1], z = currentFrame.positions[3 * i + 2];
final byte[] cs = new byte[currentFrame.lengths[i]];
for (int j = 0; j < cs.length; j++)
cs[j] = currentFrame.callsigns[pos + j];
pos += cs.length;
craft = new Aircraft(cs);
new_pos = new Vector3d(x, y, z);
poked.add(craft);
// get the last known position of this aircraft
final minicdj.statetable.Vector3d old_pos = state
.get(new CallSign(craft.getCallsign()));
if (old_pos == null) {
// we have detected a new aircraft
// here, we create a new callsign and store the aircraft into
// the state table.
state.put(mkCallsignInPersistentScope(craft.getCallsign()),
new_pos.x, new_pos.y, new_pos.z);
final Motion m = new Motion(craft, new_pos);
if (minicdj.cdx.Constants.DEBUG_DETECTOR
|| minicdj.cdx.Constants.SYNCHRONOUS_DETECTOR) {
devices.Console
.println("createMotions: old position is null, adding motion: "
+ m);
}
ret.add(m);
} else {
// this is already detected aircraft, we we need to update its
// position
final Vector3d save_old_position = new Vector3d(old_pos.x,
old_pos.y, old_pos.z);
// updating position in the StateTable
old_pos.set(new_pos.x, new_pos.y, new_pos.z);
final Motion m = new Motion(craft, save_old_position, new_pos);
if (minicdj.cdx.Constants.DEBUG_DETECTOR
|| minicdj.cdx.Constants.SYNCHRONOUS_DETECTOR) {
devices.Console.println("createMotions: adding motion: " + m);
}
ret.add(m);
}
}
Benchmarker.done(6);
return ret;
}
/**
* This Runnable enters the StateTable in order to allocate the callsign in
* the PersistentScope
*/
/* @javax.safetycritical.annotate.RunsIn("cdx.Level0Safelet") */
static class R implements Runnable {
CallSign c;
byte[] cs;
public void run() {
c = new CallSign(cs);
}
}
private final R r = new R();
CallSign mkCallsignInPersistentScope(final byte[] cs) {
//try {
// r.cs = (byte[]) MemoryArea.newArrayInArea(r, byte.class, cs.length);
//MemoryArea mem = MemoryArea.getMemoryArea(r); // HSO
//r.cs = (byte[]) mem.newArray(byte.class, cs.length); // HSO
// }
/*catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}*/
for (int i = 0; i < cs.length; i++)
r.cs[i] = cs[i];
// MemoryArea.getMemoryArea(state).executeInArea(r);
//mem.executeInArea(r); // HSO
return r.c;
}
}