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
--------------------------------------------------------------------------------------Control
OFF
LOADED/
READY
PRESETTING
STOPPING
ERROR
UNKNOWN
Action
STAND-BYOFF
OFF
OFF
OFF
OFF
OFF
OFF
UNKNOWN
IDLE
IDLE
IDLE
IDLE
IDLE
ERROR
UNKNOWN
LOADED/
OFF
LOAD/SB
LOAD/SB
LOAD/SB
LOAD/SB
LOAD/SB
UNKNOWN
STAND-BYIDLE
IDLE
IDLE
IDLE
IDLE
ERROR
UNKNOWN
READY
OFF
LOAD/SB
ON-LINE
ON-LINE
ON-LINE
ON-LINE
UNKNOWN
IDLE
IDLE
ERROR
UNKNOWN
PRESETTING
OFF
LOAD/SB
ON-LINE
ON-LINE
ON-LINE
PRESETTING
UNKNOWN
IDLE
IDLE
PRESETTING
PRESETTING
PRESETTING
ERROR
UNKNOWN
STOPPING
OFF
LOAD/SB
ON-LINE
ON-LINE
ON-LINE
STOPPING
UNKNOWN
IDLE
IDLE
STOPPING
STOPPING
STOPPING
ERROR
UNKNOWN
ERROR
OFF
LOAD/SB
ON-LINE
PRESETTING
STOPPING
prev state
UNKNOWN
ERROR
ERROR
ERROR
ERROR
ERROR
ERROR
UNKNOWN
UNKNOWN
UNKNOWN
UNKNOWN
UNKNOWN
UNKNOWN
UNKNOWN
UNKNOWN
UNKNOWN
UNKNOWN
UNKNOWN
UNKNOWN
UNKNOWN
UNKNOWN
UNKNOWN
UNKNOWN
--------------------------------------------------------------------------------------
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.