The primary aim of this project is to port the prototype framework developed in the AOCS Framework Project from C++ to Java. This page describes the general principles that guided and constrained the porting process.
Back To Top, Back
to Real-Time Java Project Home
|
|
|
| Runnable | Class name was changed to ActiveObject to avoid conflict with Java Runnable class and because the framework runnable object concept coincides with the active object of HRT-HOOD |
| AocsObject.reportFailure | Parameter creator was dropped (it was never used in C++ version) |
| AocsObject.reportConfigurationError | Parameter creator was dropped (it was never used in C++ version) |
| AocsObject.reportConfigurationError | Method name was changed to: reportConfigurationEvent |
| *.initialize,
*.allocateMemory |
These initialization methods in components are changed to setter method in the spirit of the JavaBeans architecture. For instance, method ObjectList.allocateMemory is renamed to setSize where size now represents one of the properties of object lists. Similarly, method SystemManager.initialize is replaced by a setter methods for each of its parameters that are now treated as JavaBeans properties. |
| EventList.setList | Method name is changed to setEvent |
| AocsDataPool.configureDataList | Method name is changed to setDataPoolSize where the data pool size is now treated as a JavaBeans property |
| ObjectList.first,
ObjectList.next, ObjectList.getObjectByPosition |
Method names changed to firstObject, nextObject, getByPosition (see below for the reason of this change). |
| AocsData.Close(double,double) | Method removed as redundant |
| SystemManager.add | Method name changed to addAocsObject (for reasons of clarity) |
| SystemManager.remove | Method name changed to removeAocsObject (for reasons of clarity) |
| SystemManager.loadConfigurations | Method name changed to restoreConfiguration (for reasons of naming consistency) |
| ModeManager.inhibitMode | Method name changed to disableMode (for reasons of naming consistency) |
| FollowerModeManager | Parameter numberOfModes in the constructor was dropped as redundant (the number of modes is the same as the number of modes in the master mode manager) |
| RecoveryAction.enable,
RecoveryAction.disable |
Methods replaced by a single setEnabled method (for consistency with JavaBeans model) |
| RecoveryStrategy.enable,
RecoveryAction.disable |
Methods replaced by a single setEnabled method (for consistency with JavaBeans model) |
| RecoveryStrategy | The failure event repository is now a settable parameter for class RecoveryStrategy. This is because, with the new event model, there may be several failure event repositories in the same application. |
| AocsMissionModeManager | Removed method loadImplementers which behaved differently from the C++ version due to the different dynamical binding model. |
| Telecommand.execute | The set of return codes of this method has been modified. Return code TC_FAILURE has been replaced with the codes TC_FAIL_SAFE and TC_FAIL_UNSAFE. See the documentation in class TelecommandCodes. |
| Telecommand.enable,
Telecommand.disable |
Methods replaced by a single setEnabled method (for consistency with JavaBeans model) |
| Telecommand.getNumberOfTelecommands | Method name changed to getNumberOfPendingTelecommands |
| Manoeuvre.putInUse, Manoeuvre.unUse | Methods replaced by setInUse for consistency with JavaBeans property model |
| Manoeuvre.AddManoeuvreManager,
Manoeuvre.RemoveManoeuvreManager, |
Methods were removed since they were not implemented in the C++ version of the framework (they represent a possible future extension of the framework which is no longer judged interesting) |
| AbstractControlChannel | Class implements the interfaces DataSource and DataSink, in reality the methods getOutput(int i), getNumberOfOutputs(), setInput(double newValue, int i), getNumberOfInputs(). |
| AbstractControlChannel.setInputOrder | Method was replaced by: setNumberOfInputs |
| AbstractControlChannel.setOutputOrder | Method was replaced by: setNumberOfOutputs |
| AbstractControlChannel.getInputOrder | Method was replaced by: getNumberOfInputs |
| AbstractControlChannel.getOutputOrder | Method was replaced by: getNumberOfOutputs |
| AbstractControlChannel.hold | Method was replaced by: setOnHold |
| AbstractControlChannel.release | Method was replaced by: setOnHold |
| AbstractControlChannel.linkInput
(DataItemRead d, int j) |
Method was replaced by: linkInput(DataSource d, int j). DataSource is a component presenting a fixed number of outputs from which data can be read. |
| AbstractControlChannel.linkInput
(AbstractControlChannel* c, int i, int j) |
Method was replaced by: linkInput(DataSource c, int i, int j). DataSource is a component presenting a fixed number of outputs from which data can be read. |
| ControlChannelBlock | Class implements all inhereted abstract methods from the class AbstractControlChannel and implements methods defined in interfaces DataSource and DataSink. |
| ControlChannelBlock.setStateOrder | Method was replaced by: setNumberOfStates |
| ControlChannelBlock.getStateOrder | Method was replaced by: getNumberOfStates |
| ControlChannelBlock.hold | Method was replaced by: setOnHold |
| ControlChannelBlock.release | Method was replaced by: setOnHold |
| ControlChannelBlock.allocateMemory | The memory initialization method is changed to setter methods in the spirit of the JavaBeans architecture. The mehod ControlChannelBlock.allocateMemory is spilt into setInputSize, setOutputSize, and setStateSize. As a complement to these setter method is introduced a new method called resetMemory() that performs the memory reset. |
| ControlChannelSuperBlock | Class implements all inherited abstract methods from the class AbstractControlChannel and implements methods defined in interfaces DataSource and DataSink. |
| DataItemRead and DataItemWrite | DataItemRead and DataItemWrite objects encapsulates a reference to the data source or data sink. This mechanisms is used internally. |
| IoLink | The structure IoLink implemented in the class ControlChannelSuperBlock was rewritten into individual class. |
The non-localized minor changes are:
The top-level package for the framework classes is RtjAocsFramework. This package contains a number of subpackages that match the subdirectories of the Visual Studio project where the C++ version of the framework was developed.
Back To Top, Back to Real-Time Java Project Home
The C++ version of the framework used templates only to specialize the ObjectListTemplate class. The templatized classes were simply providing a type-safe wrapper for the ObjectList class. In the Java version of the framework, the template mechanism was replaced by the inheritance mechanism. The class ObjectList is functionally the same as in the C++ version of the framework. Type-safety is achieved by providing derived classes that expose type-safe methods to access the items in the object list. The names of the derived classes are as follows: <type-name>List is the wrapper that provides a type-safe list of objects of type <type-name>.
One awkward consequence of this approach is that methods like first in class ObjectList would now appear both in ObjectList and in its derived classes with different return types. This is forbidden by the Java compiler and therefore it was necessary to change the name of ObjectList.first to ObjectList.firstObject. Similar changes, and for the same reasons, were made to methods next and getObjectByPosition (see list of minor changes above).
Back To Top, Back to Real-Time Java Project Home
In a typical instantiation, to each active component, a dedicated thread is associated. How the threads are scheduled is an instantiation issue. The active components defined by the framework are written to be independent of how often they are activated and of the order in which they are activated. In a typical instantiation, all the active components are scheduled in accordance with a cyclical policy with the possible exception of the TelecommandLoader component that may be treated as a sporadic component to be awakened by the arrival of a new telecommand. Note however that this is not always the case. In some applications, the telecommand loader may be implemented to be activated cyclically to process raw telecommand data that are accumulated in a buffer by a lower level task (e.g. an interrupt processing routine).
Operation in a multithreading environment requires the implementation of mechanisms to preserve data integrity. This is done at three levels. At the first integrity level, it is necessary to ensure that objects are accessed in mutual exclusion. Consider the following method call:
a.method(...);
The implementation of the method might change the internal state of object a and therefore this method call can only be guaranteed to be thread-safe if its execution is not interrupted by other threads that perform operations on object a. In the AOCS Framework, this objective is achieved by marking all methods that may be called during the operational phase synchronized. The only methods that are not subjected to this precaution are the configuration or initialization methods. These are methods that are intended to be called only during the application initialization phase when multi-threading operation has not yet begun. Typical configuration methods are: resetConfiguration and isConfigured. Other configuration methods are identified as such in the method documentation.
At the second integrity level, it is necessary to ensure that data that are acquired from the same objects through separate operations are consistent. Consider the following situation:
v1 = a.method1(...);v2 = a.method2(...);
. . . // process v1 and v2
Suppose that there is a requirement that the two return values v1 and v2 are mutually consistent in the sense that, while they are acquired, the state of object a is not altered. There are two cases where this situation arises in the framework:
In a non-real-time environment, the simplest way to cope with the above problem would be for the processing code to clone object a and thus create an internal copy that can be processed in the absence of interference from other threads (NB: this approach only works if the clone method is implemented as a synchronized method). However, creating internal clones requires performing a dynamic memory allocation which is not compatible with hard real-time constraints. Hence, the solution adopted in the framework is as follows:
synchronized (a) {
v1 = a.method1(...);
v2 = a.method2(...);
}
. . . // process v1 and v2
The acquisition operations are enclosed in a synchronized block that ensures that the state of the object from which the data are acquired is not altered by other threads. Thus, the solution to the two examples listed above is:
At the third integrity level, it is necessary to ensure that data acquired from several sources are consistent. A typical example is the processing of sensor data by the controller. Consider for instance a situation where a controller processes data from two different sensors and produces data for two different actuators. Clearly, if the sensor acquisition task is interleaved with the control processing task and the latter is in turn interleaved with the actuator commanding task, a situation may arise where the controller takes as input data that have been acquired from the two sensors at different times or, similarly, a situation may arise where the actuators receive commands that have been computed in two different cycles.
The framework takes the view that this kind of integrity issues must be dealt with at application design level. Normally, this would be done by defining a scheduling policy that ensures that the tasks that produce certain data have terminated their execution before the task that processes those data can begin. Thus, in the example situation outlined above, one would assign a release time for the controller task that is later than the deadline for the sensor acquisition task, and a release time for the actuator commanding task that is later than the deadline for the controller task.
Back To Top, Back to Real-Time Java Project Home
This difference made the following changes necessary in the Java version of the framework:
Some of the code in a complete application is directly or indirectly inherited from the framework. This includes the components supplied by the framework, code that implements framework-supplied abstract interfaces, and code that supports framework-supplied design patterns. The framework is designed in such a manner that this code only uses standard Java constructs. This makes the framework compatible with different variants of real-time Java but also imposes the following restrictions on the design and implementation of the framework:
Back To Top, Back to Real-Time Java Project Home
A second implication of the adherence to the Java beans event model is that class the AocsEvent class is implemented in the Java version of the framework as a subclass of EventObject. It is therefore the only framework class that does not inherit from RootObject. The constructor of class EventObject requires the event source as an argument and treats it as read-only parameters. This is not adequate for the framework that requires all event parameters to be settable since events cannot be created dynamically. Hence, the framework passes to the constructor of EventObject a dummy argument that is never used. The event source is stored as a parameter defined by class AocsEvent.
In the C++ version of the framework, events are generated to be stored in event repositories. In the Java version therefore the event repositories become event listeners. In one important difference with the C++ version of the framework, each event source could fire events to only one event repository. In the Java version, instead, event sources maintain an array of event listeners and can therefore potentially send their events to multiple repositories. Thus, for instance, it would be possible to have two failure event repositories.
Event adapters are not used in the Java framework. This is because it is assumed that event processing is "quick" and can therefore be done in the thread of the event source.
Back To Top, Back to Real-Time Java Project Home
Back To Top, Back to Real-Time Java Project Home
The Java version of the framework introduces the concepts of data sink and data source. A a data sink is an object with a fixed number of inputs that participates in a data flow. Data sinks offer read-write access to their inputs. The inputs are always assumed to be of type 'double'. Data sinks are characterized by implementation of interface DataSink.
Similarly, a data source is an object with a fixed number of outputs
that partipates in a data flow. Data sources offer read-only access to
their outputs. The outputs are
always assumed to be of type 'double'. Data sinks are characterized
by implementation of interface DataSource.
Data flow components see each other as instances of type DataSink and DataSource and, as far as the flow of cyclical data is concerned, are linked to each other through these two interfaces.
Back To Top, Back to Real-Time Java Project Home
In the Java version of the framework, interface Monitorable is introduced to characterize monitorable objects. A monitorable object is an object that exposes properties that can be subjected to direct monitoring. It is therefore equivalent to a source of properties in the C++ version of the framework.
In the C++ version of the framework, some objects allow their properties to be subjected to monitoring according to the "monitoring through change notification" design pattern. This involves the monitor registering its interest in a certain property and specifying the type of change profile in which it is interested. The change profile is specified as an object of type ChangeObject. A violation of the change profile on the part of the monitored variable results in a change event being fired and in the propertyChange method of the monitoring object being invoked.
In JavaBeans application, the type of call-back action behind the monitoring through change notification design pattern should ideally be implemented using the event mechanism. Unfortunately, no satisfactory way was found to implement this design pattern using the Java event mechanism. Hence, the Java version of the framework replicates the implementation of the C++ version of the framework. The only properties upon which monitoring through change notification can be performed by default are the mode property exposed by mode managers and the manoeuvre state exposed by manoeuvre objects. In the C++ version of the framework, the reconfiguration status was exposed by configuration managers as a monitorable property. This is no longer the case in the Java version.
Monitoring through change notification in the Java version of the framework should be used only where absolutely necessary because its implementation deviates from the JavaBeans model.
Back To Top, Back to Real-Time Java Project Home
The documents describing the C++ version of the framework are:
|
|
Document Type |
|
| 1 | AocsDescription | Description of the framework domain |
| 2 | AocsArchitecture | Description of the framework at framework concept level |
| 3 | <framelet name>Framelet | Description of framelets at concept and architectural level (one document for each framelet) |
| 4 | AocsPrototypeDefinition | Description of the AOCS prototype used to test the framework prototype |
| 5 | FrameworkPrototypeDefinition | Description of the framework prototype (as opposed to the full framework defined in the design documentation) |
| 6 | TestReport | Description of the tests performed to verify the framework implementation |
| 7 | ImplementationNotes | Description of some framework implementation aspects |
| 8 | ImplementationCases | Description of implementation cases used during the framework design phase |
| 9 | Methodology | Description of the framework design methodology |
The applicability status of these documents to the Java version of the framework is as follows:
Document 1 is applicable to both the C++ and Java versions of the framework since both are targeted at the same application domain.
Document 2 remains largely applicable. A section "Applicability to Java Version of the Framework" was added to identify parts that are specific to the C++ version of the framework.
Documents 3 remain partly applicable. The concept-level description of the framelets is the same for both the C++ and Java versions of the framework. In particular, both versions of the framework use the same design patterns. The architectural descriptions of the framelets however are only applicable to the C++ version of the framework. In the Java version of the framework, the architectural-level description is generated automatically by the JavaDoc tool. The Java source code is commented in accordance with the JavaDoc conventions and gives descriptions of all the class interfaces. Additonally, package overview documents in html are also provided and integrated in the custormary manner in the JavaDoc documentation.
Documents 4 to 6 cover the instantiation and testing of the framework and are superceded by the pages on this web site that document: the framework testing approach, the framework instantiation approach, and the prototype application instatiation.
Document 7 is specific to the C++ version of the framework and is not applicable to the Java version.
Document 8 was obsolete even with respect to the C++ version of the framework as it was not maintained through the project life. No update for the Java version is provided. Examples of implementation cases for the AOCS Framework can be found in the book "Software Frameworks and Embedded Control Systems" by A. Pasetti to be published in Dec. 2001 in the LNCS serie of Springer-Verlag.
Document 9 is superceded by the book "Software Frameworks and Embedded Control Systems" by A. Pasetti published as vol. 2231 in the LNCS series of Springer-Verlag.
Back To Top, Back to Real-Time Java Project Home