Flow of development
The following illustrates the flow of development using the OPEN-R SDK.
(1) Design your objects
You must design the functions of the objects you are going to create, as well as
the flow of data between these objects. For example, in the case of designing an
object for tracking a pink ball, the object must receive image data, it must detect
a pink ball in the image, and it must send command data for moving the head
toward the ball.
(2) Design the data type for inter-object communication
You must choose an appropriate data type to carry messages between objects.
For example, you can choose OFbkImageVectorData for input data and
OCommandVectorData for output data.
(3) Description of stub.cfg
The connection between the entry points (where the message is received) and the
actual member functions of the core class is described with specified form in a
file called stub.cfg (stub configuration file).
In stub.cfg, we also describe the services that send and receive data to/from other
objects. By executing a tool named ¡¥stubgen2¡¦, the intermediate files are created
from stub.cfg, which are needed for compiling purposes.
(4) Implementation of a core class
You must implement the core class of your object, which includes the functions
specified by stub.cfg, the four DoXXX() member functions (which are always
implemented on the core class) and other member functions.
(5) Decide the configuration of your .ocf file
The configuration of objects at run-time is specified here.
(6) Build
You build an executable file for your object by linking with other necessary libraries.
(7) Edit the setting files
You must edit the setting files needed at run-time. The following are the relevant setting files. OBJECT.CFG Description of objects to be executed CONNECT.CFG Description of connections between objects DESIGNDB.CFG Description of files with paths, which are accessed by objects at run-time
(8) Execution on AIBO
The following files are copied to the specified directory on an AIBO
Programming Memory Stick.
¡E OPEN-R directory
¡E Execution file (.BIN)
¡E Edited setting files
¡E Data files such as motion and sound
After creating a wireless LAN environment for connecting AIBO with your PC,
insert an AIBO Programming Memory Stick into AIBO and boot it.
(9) Debugging
If you happen to have bugs in your program, you can debug them by using
special debugging macros, such as OSYSPRINT and OSYSLOG1, as well as
other error information, from the messages that are printed in the wireless LAN
console.
An OPENR object is more like a UNIX process. Each executable file in the final
program (with a .bin extension) corresponds to one object. Each object communicates
with other objects by passing messages. Each message consists of a selector (which is
an integer) and some data The flow of execution is event-driven.
1. Object waits for messages to arrive.
2. Once a message arrives, it calls the corresponding method based on the selector. The method ¡V selector combinations are specified in the stub.cfg file. The arguments for the method are the data included in the message.
The method might pass messages to other objects.
3. Wait for more messages.
The object that sends a message is called the ¡§subject¡¨, while the object that receives
the message is called the ¡§observer¡¨.
To send a message, the subject first sends a ¡¥NotifyEvent¡¦ to an observer or set of
observers. The subject then waits for a ¡¥ReadyEvent¡¦ from the observer. The
¡¥ReadyEvent¡¦ from the observer back to the subject can either be:
a) ASSERT_READY ¡V if the observer is ready to receive a message
from the subject.
b) DEASSERT-READY ¡V if the observer is not ready to receive a
message
Objects are single-threaded. They cannot process more than one message at a time. If
the observer receives a new message when it is processing some other message, then
the new message is put in the message-queue. Each object has one message-queue.
Each object has a corresponding core class. A core classes is a C++ class that defines
the object¡¦s data and methods.
Here is an example of a simple Class[1].
#include <OPENR/OObject.h>
#include <OPENR/OSubject.h>
#include <OPENR/OObserver.h>
#include "def.h"
class SampleClass : public OObject {
public:
SampleClass();
virtual ~SampleClass() {}
OSubject* subject[numOfSubject];
OObserver* observer[numOfObserver];
virtual OStatus DoInit(const OSystemEvent& event);
virtual OStatus DoStart(const OSystemEvent& event);
virtual OStatus DoStop(const OSystemEvent& event);
virtual OStatus DoDestroy(const OSystemEvent& event);
//Describe the member functions corresponding to Notify,
//Control, Ready, Connect method.
};
The different parts of the sample program are explained below:
#include <OPENR/OObject.h>
#include <OPENR/OSubject.h>
#include <OPENR/OObserver.h>
#include "def.h"
OSubject.h has the necessary method declarations for the Subjects while
OObserver.h has the corresponding declarations for the Observers. The def.h
file is generated by the stubgen program (which will be discussed later).
class SampleClass : public OObject {
All core classes in OPENR are and must be inherited from OObject. This is very
similar to Object class in Java.
OSubject* subject[numOfSubject];
OObserver* observer[numOfObserver];
This indicates the number of subjects and the observers that the class will have.
Every program must have these. The def.h file defines the numOfSubject and
numOfObserver.
virtual OStatus DoInit(const OSystemEvent& event);
The DoInit() method is called at startup to initialize all the instances and variables.
virtual OStatus DoStart(const OSystemEvent& event);
The DoStart() Method executes right after DoInit() finishes execution.
virtual OStatus DoStop(const OSystemEvent& event);
virtual OStatus DoDestroy(const OSystemEvent& event);
The DoStop() Method is called at shutdown. This is followed by DoDestroy() Method
which destroys all the subject and observer instances, and calls the destructor
function.
In addition to these four methods, at least four other methods have to be defined to
enable inter object communication:
Control Method
This method is used by the subject to receive the connection results with its
observers.
Connect Method
This method is used by the observer to receive the connection results.
Notify Method
This method is used by the observer to receive a message from the subject.
Ready Method
This method is used by the subject to receive the ASSERT-READY and the
DEASSERT-READY notifications.
In most cases, you will have to include all these macros in every core
class you make.
DoInit( )
NEW_ALL_SUBJECT_AND_OBSERVER
This registers the necessary number of subjects and observers.
REGISTER_ALL_ENTRY
This registers the connection to services offered by other objects.
SET_ALL_READY_AND_NOTIFY_ENTRY
This registers all entry points.
DoStart( )
ENABLE_ALL_SUBJECT
This enables all the subjects
ASSERT_READY_TO_ALL_OBSERVER
This sends ASSERT_READY to all subjects.
DoStop( )
DISABLE_ALL_SUBJECT
This disables all subjects of core class.
DEASSERT_READY_TO_ALL_OBSERVER
This sends a DEASSERT_READY to all connecting subjects.
DoDestroy( )
DELETE_ALL_SUBJECT_AND_OBSERVER
This deletes all observer and subjects.
When the observer is ready to receive data from the subject, the observer sends the
subject an ASSERT-READY message.
___________________________________________________________________________________
void SampleObserver::SendAssertReady()
{
observer[obsfunc1]->AssertReady( );
}
___________________________________________________________________________________
When the subject receives the ASSERT-READY signal, it sends the observer the
data.
___________________________________________________________________________________
void SampleSubject::Ready(const OReadyEvent& event)
{
char str[32];
strcpy(str, ¡§Some Text Message¡¨);
subject[sbjFunc2]->SetData(str,sizeof(str));
subject[sbjFunc2]->NotifyObservers( );
}
___________________________________________________________________________________
When the observer receives the data, it sends an ASSERT_READY again.
___________________________________________________________________________________
void SampleObserver::Notify(const ONotifyEvent& event)
{
const char* text = (const char*)event.Data(0);
observer[sbjFunc1]->AssertReady();
}