Release of TCA Version 7.7 Summary: ======== 1) Added Global variables to TCA. 2) Added utilities to limit the number of pending messages 3) Added support for compiling on sgi machines. "makefiles" still needs some cleaning up. See src/INSTALL file for instructions on compiling. 4) Better error checking. TCA now checks for a valid connection to central before trying to send messages. 5) Fixed a bug that allowed central to send messages to modules even before they issued a "tcaWaitUntilReady" call. Details: ======== 1. GLOBAL VARIABLES =================== TCA now supports global variables that can be set and read atomically. It is intended that this mechanism be used when TCA modules need to share system state, such as the current position of a robot. Procedures are available to set and query the value of a variable. In addition, modules can be notified when the value of a variable changes. Global variables can be used to de-couple the timing constraints between producers and consumers of information. For example, one module may be keeping track of the position of the robot using dead reckoning. It might be part of the robot's control loop and produce new information frequently. Other modules such as planners, may need this information, either periodically or at specific times. Under previous versions of TCA, other modules would have to query the dead reckoning module to get the information or the dead reckoning module could broadcast a message whenever the value changed. If queries are used and many modules require position information, then the dead reckoning module will spend a lot of time replying to queries. Broadcast messages can be used to reduce the load on the dead reckoning module. Using broadcast messages, the dead reckoning module needs only send out one message every time the position changes. Modules interested in the position can register handlers for the message and be informed whenever it changes. The problem is that some modules may only be interested in getting position information at specific times or less frequently that the rate at which it changes. Using broadcast messages, these modules must still handle every broadcast messages that is sent. Using global variables can reduce the overhead. Modules can simply get the value of the variable whenever they need it. The dead reckoning module still only needs to send a single message when the position changes. If a module is interested in keeping track of the current position as often as it changes, then the module can have TCA "watch" the variable and be notified whenever it is set. If a module is interested in getting the value periodically (say every 2 seconds), then it can set up a polling monitor to query the value every 2 seconds. GLOBAL VARIABLE FUNCTIONS ========================= void tcaRegisterVar(const char* name, const char* format); ---------------------------------------------------------- Register a variable with name that has the given data format. The format string uses the same syntax as that for messages. void tcaSetVar(const char* name, const void* value); ---------------------------------------------------- Set the value of a global variable. This action happens asynchronously and is not constrained by commands and goals in the task tree. The value is stored in the central server, so this action only takes a single void tcaGetVar(const char* name, void* value); ---------------------------------------------- Get the current value of the variable. Blocks until the value is returned. void tcaGetSetVar(const char* name, void* setValue, void* getValue); -------------------------------------------------------------------- Get the current value of the variable and then set it to the given value. This is the "test and set" function. void tcaWatchVar(const char *name, const char *format, TCA_HND_FN watchFn); ---------------------------------------------------------------------------- Watch the variable given by name and call the watchFn with the new value whenever it changes. ================================================================ 2. LIMITING PENDING MESSAGES ============================ TCA limits the number of messages being handled by a module (actually, a resource) at any one time. This is called the resource's capacity, and is usually set to 1 (only one message active at a time). Additional messages destined for that module/resource are queued, pending resource availability. Messages are queued in a first-in first-out manner. If messages are being sent faster than a module can handle them, the queue of pending messages can grow quite large. Occasionally, one is interested in only the most recent messages, and it is safe to ignore older pending messages. TCA now includes mechanisms for producing the behavior of saving only the most recent messages destined for a module/resource. One can request TCA to maintain only the N most recent messages sent to a given resource, or the N most recent messages with a given name. One can limit any class of message, but it is not recommended for use with query-class messages. LIMIT PENDING FUNCTIONS ======================= void tcaLimitPendingResource (const char *resName, int limit) _______________________________________________________________________ Allow only "limit" pending messages for the resource "resName". Deletes messages in a FIFO manner to maintain this constraint. This constraint applies to *all* messages sent to the given resource. The module name (the name used in tcaConnectModule) is used to refer to the module's default resource. void tcaLimitPendingMessages (const char *msgName, const char *resName, int limit) _______________________________________________________________________ Allow only "limit" pending messages named "msgName" on the resource "resName". Deletes messages in a FIFO manner to maintain this constraint. The module name (the name used in tcaConnectModule) is used to refer to the module's default resource. 5. DELAY SENDING MESSAGES UNTIL READY ===================================== Contrary to popularly held opinion (and statements in the manual), TCA would forward messages to a module even before it issued a "tcaWaitUntilReady" call. This has now been fixed, and no messages, other than registration and internal initialization messages, are sent to modules prior to receiving an indication that the module is ready to begin processing messages. A consequent of this is that modules that want to receive messages *must* issue a "tcaWaitUntilReady" call before invoking "tcaModuleListen" or "tcaHandleMessage" (TCA issues a warning if this is not followed). Modules that only *send* messages are not required to call "tcaWaitUntilReady", but it is strongly recommended that all modules include this call following all message and handler registration calls.