G.Chiozzi
12/06/96
The Telescope Control Software for the VLT (and for the NTT Upgrade) has been designed and implemented using OO methodologies.
The workstation components are implemented in C++ and are based on the EVH toolkit.
Purpose of this presentation is:
The presentation is focused on
technical and implementation issues
and not on
functional specifications
The TCS workstation contains the TCS Online database.
TCS module's are as much as possible independent,
so that it is possible
to develop and test them one by one
A few unavoidable dependencies are due to the fact that some modules need services provided by other ones. No circular dependencies between modules are allowed.
Common services are provided through:
This define the hierarchy between modules.
The online database is used to have "configurable" any dependency between modules. For example:
are always stored in the database.
All workstation modules
have the same architecture
Table 1 - TCS Preset Global State
--------------------------------------------------------------------------------------ControlOFFLOADED/READYPRESETTINGSTOPPINGERRORUNKNOWNActionSTAND-BYOFFOFFOFFOFFOFFOFFOFFUNKNOWNIDLEIDLEIDLEIDLEIDLEERRORUNKNOWNLOADED/OFFLOAD/SBLOAD/SBLOAD/SBLOAD/SBLOAD/SBUNKNOWNSTAND-BYIDLEIDLEIDLEIDLEIDLEERRORUNKNOWNREADYOFFLOAD/SBON-LINEON-LINEON-LINEON-LINEUNKNOWNIDLEIDLEERRORUNKNOWNPRESETTINGOFFLOAD/SBON-LINEON-LINEON-LINEPRESETTINGUNKNOWNIDLEIDLEPRESETTINGPRESETTINGPRESETTINGERRORUNKNOWNSTOPPINGOFFLOAD/SBON-LINEON-LINEON-LINESTOPPINGUNKNOWNIDLEIDLESTOPPINGSTOPPINGSTOPPINGERRORUNKNOWNERROROFFLOAD/SBON-LINEPRESETTINGSTOPPINGprev stateUNKNOWNERRORERRORERRORERRORERRORERRORUNKNOWNUNKNOWNUNKNOWNUNKNOWNUNKNOWNUNKNOWNUNKNOWNUNKNOWNUNKNOWNUNKNOWNUNKNOWNUNKNOWNUNKNOWNUNKNOWNUNKNOWNUNKNOWN--------------------------------------------------------------------------------------
The database calculation engine formula:
ATTRIBUTE int32 state prsSTATE_OFF
BEGIN
Definition \
IF([<relative>control.state]=evhSTATE_UNK OR \
[<relative>action.state] =evhSTATE_UNK, evhSTATE_UNK, \
IF([<relative>control.state]=prsSTATE_OFF OR \
[<relative>action.state] =prsSTATE_OFF, prsSTATE_OFF, \
IF([<relative>control.state]=prsSTATE_LOADED OR \
[<relative>action.state] =prsSTATE_LOADED, prsSTATE_LOADED, \
IF([<relative>control.state]=prsSTATE_STANDBY OR \
[<relative>action.state] =prsSTATE_STANDBY, prsSTATE_STANDBY, \
prsSTATE_ONLINE ))))
END
ATTRIBUTE int32 substate prsSTATE_STEADY
BEGIN
Definition \
IF([<relative>control.state]=evhSTATE_UNK OR \
[<relative>action.state] =evhSTATE_UNK, evhSTATE_UNK, \
IF([<relative>control.state]=prsSTATE_OFF OR \
[<relative>action.state] =prsSTATE_OFF, prsSTATE_STEADY, \
IF([<relative>control.state]=prsSTATE_LOADED OR \
[<relative>action.state] =prsSTATE_LOADED, prsSTATE_STEADY, \
IF([<relative>control.state]=prsSTATE_STANDBY OR \
[<relative>action.state] =prsSTATE_STANDBY, prsSTATE_STEADY, \
IF([<relative>control.state]=prsSTATE_ERROR OR \
[<relative>action.state] =prsSTATE_ERROR, prsSTATE_ERROR , \
IF([<relative>control.state]=prsSTATE_STOPPING, prsSTATE_STOPPING, \
IF([<relative>control.state]=prsSTATE_PRESETTING, prsSTATE_PRESETTING, \
prsSTATE_READY )))))))
END
ATTRIBUTE prsCONTROL control
ATTRIBUTE prsACTION action
END
This area is not yet standardized.
The modules use different strategies
depending on the specific needs
Some action is necessary in this area
prs, msw, trkws:
evhDB_CMD_SEND
agws, pom:
evhCOMMAND
evhCB_COMPL_STAT prsAH_MAIN_TASK_VLT::ExePresetCB(msgMESSAGE &, void *)
{
evhCB_COMPL_STAT stat = evhCB_DELETE;
ccsCOMPL_STAT res = SUCCESS;
prsTRACK_MODE target;
evhDB_SEND_ID id = 0;
errFlag(res, track.Preset(*currentSetupFile,&target));
//#= If target != altaz, asks for preset of the other subsystems
if( (target != prsTARG_NONE) && (target != prsTARG_ALAZ))
{
id = 0;
//#= Executes a focus correction based on calibrated values
errFlag(res,ao.CalibratedFocusCorrection(*currentSetupFile));
//#= Preset of Auto Guide
errFlag(res,guide.Preset(*currentSetupFile));
errFlag(res,guide.FindGuideStar(*currentSetupFile, &id));
errFlag(res,guide.ObjectCenter(*currentSetupFile, &id, id));
//#= Offset step. When step ObjectCentering is completed
errFlag(res,track.OffsetStep(*currentSetupFile, &id, id));
//#= Execute an accurate focus correction
errFlag(res,ao.FocusCorrection(*currentSetupFile, &id, id));
//#= Acquisition of final guide star and start guiding
errFlag(res,guide.Start(*currentSetupFile, &id, id));
}
//#= Ask the stdMod object to request a SETUP for all the other standard
//#= modules registered in the application:
stdMod.Setup(*currentSetupFile, &id, id);
//#= Activates a syncronizzation object to wait until all the subsystems
//#= are ready (or a timeout occurrs):
//#= Events: DB:prsAction.track.state >= IDLE
//#= DB:prsAction.guide.state >= IDLE
//#= DB:prsAction.ao.state >= IDLE
//#= DB:prsAction.stdMod.state >= IDLE
//#= Action CB: ReadyCB
//#= Timeout: ErrorCB Time: DB:prsAction.readyTimeout
dbSYMADDRESS objDbName;
waitAllReady.ClearConditions();
sprintf(objDbName, "%s.%s",track.DbPoint(),"state");
waitAllReady.AddCondition(objDbName,evhSTATE_IDLE,TRUE);
sprintf(objDbName, "%s.%s",guide.DbPoint(),"state");
waitAllReady.AddCondition(objDbName,evhSTATE_IDLE,TRUE);
sprintf(objDbName, "%s.%s",ao.DbPoint(),"state");
waitAllReady.AddCondition(objDbName,evhSTATE_IDLE,TRUE);
sprintf(objDbName, "%s.%s",stdMod.DbPoint(),"state");
waitAllReady.AddCondition(objDbName,evhSTATE_IDLE,TRUE);
waitAllReady.Run();
if(res == FAILURE).....
return stat;
}
class pomMAIN_TASK : public evhDB_TASK {
public:
virtual evhCB_COMPL_STAT ReadPosReceiveCB(msgMESSAGE &msg, void *);
private:
virtual evhCB_COMPL_STAT ReadPosReplyCB(msgMESSAGE &msg, int seq);
virtual evhCB_COMPL_STAT ReadPosErrorCB(msgMESSAGE &msg, int seq);
msgMESSAGE readPosMsg;
evhDB_COMMAND readPos_1Cmd;
evhDB_COMMAND readPos_2Cmd;
vltINT8 readPosFlag;
};
evhCB_COMPL_STAT pomMAIN_TASK::ReadPosReceiveCB(msgMESSAGE &msg, void *)
{
msgMESSAGE sendMsg;
ErrReset();
// Save received message, to send final reply later on
readPosMsg = msg;
// Prepare and send the 1st command
sendMsg.Command(xxxFIRST_CMD).Buffer("test buffer send to process 1");
readPos_1Cmd.Send(sendMsg);
// Prepare and send the 2nd command
sendMsg.Command(xxxSECOND_CMD).Buffer("test buffer send to process 2");
readPos_2Cmd.Send(sendMsg);
readPosFlag = 2; // Set the counter flag
return evhCB_NO_DELETE;
}
evhCB_COMPL_STAT pomMAIN_TASK::ReadPosReplyCB(msgMESSAGE &msg, int seq)
{
evhCB_COMPL_STAT stat = evhCB_NO_DELETE;
ErrReset();
// If it is the last reply, I am done
if( msg.LastReply()) {
readPosFlag = readPosFlag -1;
if(readPosFlag == 0)
if( readPosMsg.SendReply(tcsOK_MSG) == FAILURE ) {
ErrAdd("evh",evhERR_SEND_REPLY,__FILE_LINE__);
ErrStackClose();
}
stat = evhCB_DELETE;
}
return stat;
}
evhCB_COMPL_STAT pomMAIN_TASK::ReadPosErrorCB(msgMESSAGE &msg, int seq)
{
ErrReset();
ErrAdd("eccs",eccsERR_GENERIC, __FILE_LINE__);
readPosFlag = readPosFlag - 1; // we decrement the flag first
/* If there is still a pending command we must abort it */
if(readPosFlag & (seq == 1)) readPos_2Cmd.Reset();
if(readPosFlag & (seq == 2)) readPos_1Cmd.Reset();
// Send back the final error reply
if( readPosMsg.SendReply(ErrStack()) == FAILURE ) {
ErrAdd("evh",evhERR_SEND_REPLY,__FILE_LINE__);
ErrStackClose();
}
else
ErrStackReset();
return evhCB_DELETE;
}
In the modular test it is necessary to test:
Tests on different modules are independent one another:
All TCS workstation modules have the same general architecture.
This makes the software coherent and easier to maintain.
A periodic parallel cleanup of all modules is very important to factorize common problems and solutions.
Handling of command dispatching is still implemented using different strategies in the various modules.
It is important to codify the allowed strategies in design patterns and to develop common classes to implement them.