|
jAER project on SourceForge | |||||||||
PREV PACKAGE NEXT PACKAGE | FRAMES NO FRAMES |
See:
Description
Interface Summary | |
---|---|
Event<T> | Interface for any event - currently unused. |
EventInterface<T extends BasicEvent> | The basic interface for an event |
EventPacketInterface<T extends BasicEvent> | |
InputEventIterator<T extends BasicEvent> | Used to iterate over an EventPacket to obtain the events. |
OutputEventIterator<T extends BasicEvent> | Used to iterate over an EventPacket treated as an output packet. |
Class Summary | |
---|---|
BasicEvent | Base class for events. |
BinocularDisparityEvent | |
BinocularEvent | Represents an event from a binocular source |
BinocularOrientationEvent | |
EventPacket<E extends BasicEvent> | A packet of events that is used for rendering and event processing. |
MotionOrientationEvent | Represents an event with direction of motion and delay |
MotionOrientationEvent.Dir | represents a direction. |
OrientationEvent | Represents an event with an orientation that can take 4 values. |
OrientationEvent.UnitVector | represents a unit orientation. |
PolarityEvent | Represents an event with a polarity that is On or Off type |
TypedEvent | Represents an event with a byte type. |
Enum Summary | |
---|---|
BinocularEvent.Eye | |
PolarityEvent.Polarity |
Classes related to events with type information - e.g. polarity, orientation, direction of motion.
A work in progress -last update 19-may-06
Events that come from a chip are transmitted as raw events, meaning the address is the raw device address. This raw address needs to be interpreted as for example a row and column address and a cell type, e.g. ON or OFF type. Later, these events, or new ones that are synthesized, can add additional type information, e.g. orientation, direction of motion. In additions, events can take on analog characteristics, e.g. speed, amplitude, etc. The classes in this package support this functionality without giving up efficiency of processing of packets of events.
Identifcation of cell type - "elaborated events"
Consumers of packets of events need to be able to determine if their input data is of the correct form. Therefore a packet of events is packaged with information that allows the consumer to determine the contents of the packet and to access these contents.
How do you access the various fields describing the events? Certain fields are built in for historical back compatibility. These are
The last item "type" is the key point of difference that this package provides. Historically, this type indicated ON/OFF event polartiy from the retina. Later on, event processing elaborated this type. An input of ON/OFF type became in SimpleOrientationFilter an output type of value 0-3, to indicate orientation by 45 degree increments. But this representation loses the original ON/OFF information, which is in general bad if memory use is not a major concern. Later on, it became necessary to represent binocular information using the same byte type field. Awkwardness in masking the appropriate bits and the unextensibilty of this represenation has led to the development of this package.
Key architectural choices are the following
This elaborated representation brings up the problem of identifying this elaborated information, accessing it, and efficiently allocating and managing memory for it.
Memory management
In general, a processor or filter module that accepts events of one type and emits events of a different or elaborated type can re-use the output data memory to increase efficiency and decrease memory fragmentation. In this scenario, the processor will allocate memory to hold the output and will reuse this memory on successive calls.
For efficiency, packets package events as arrays of related primitives (e.g. int[] timestamps, short[] x,y) rather than arrays of objects. It is possible that prebuilt arrays of objects are not too inefficient but creating and instantiating arrays of objects is quite expensive and objects consume substantially more memory than the sum of size of the fields. It is also probably more expensive to access event information using an event object reference, as compared to iterating through the primitive arrays representing event information.
It is assumed that any producer of event packets will take care of allocating the necessary memory. This brings up the question of memory management: How should memory be managed and how should resizing be handled?
Java arrays are immutable and cannot be resized after allocation. Of course an array can hold less data than its size as long as the user does not use the array.length method to measure the amount of data this is OK. Instead the user must use the getNumEvents method and ensure that any direct manipulation of the arrays to add data calls the setNumEvents method.
At present you add data using the addEvent method. When new data is added to the array the counter of number of events is increased. This method is expensive because it travels up the hierarchy, calling ensureCapacity for each super to make sure the arrays are large enough to hold the new data. If the arrays are too small, new arrays are allocated and the data is copied to them. When the arrays are resized, they are resize by a hard-coded factor to minimize the number of times this expensive operation is done.
Another approach to this business of ensuring capacity is to simply disallow adding more events than the packet holds. The user must then make a decision about how many events can be held in the packet. This is attractive in some ways because it ensures that there are never too many events and thus, processing time is bound. But it also is bad because information can be lost.
Another approach is to take advantage of Java's built-in and efficient array bounds checking. Any loop with direct array access that could overstep the bounds is surrounded by try/catch for ArrayOutOfBoundsException. Reports indicate that try/catch blocks are very fast as long as no exception is thrown. When the exception is thrown, the user can resize the packet manually or simply throw away subsequent events. This method has the disadvantage that the user must know how to resize a packet.
Another approach is to use bounds checking internally to the EventPacket class in the addEvent method. Then if an exception is thrown, the handler resizes the packet by allocating new arrays for the primitives it is responsible for and calling the super method to do this for arrays the super classes are responsible for. This approach sheilds the user from memory managment, at the cost of moving try/catch inside the method that does the array access, instead of outside the loop.
The approach taken in many of the EventFilter2D classes at present is to reuse an output packet that grows (without bound) to hold the results of processing. Expensive allocation is minimized at the cost of possibly unbounded growth of used memory. This approach also necessitates memory management so that the filter frees the memory explicitly when the filter is not used. This is done in the SimpleOrientationFilter, for example, but it is complicated.
Defining an event type and its packets
New fields are added to event packets by using the addType(Class typeClass, Class primitiveClassType) method, e.g. This method puts the
|
jAER project on SourceForge | |||||||||
PREV PACKAGE NEXT PACKAGE | FRAMES NO FRAMES |