\subsubsection{The Anti Collider} In some cases certain instrument positions can only be reached through special sequences of drive instructions. Usually because some concrete blocks or unduly bulky sample environment devices are in the path of the instrument. Such cases can not be handled through primitive motor limits. Handling such cases is the objective of the Anti Collider. The first thing needed is that motors involved with such complex movements are registered with the Anti Collider. In this stage the Anti Collider will take over the SetValue and CheckStatus functions of the drivable interface of the motor. SetValue will be replaced by a function which will register the drive request with the Anti Collider. CheckStatus will be replaced by a version which checks with the Anti Collider if the complex movement has finished. It is expected that coordinated and complex movements are initiated within a single command. The first checkpoint where the complex movement can be analyzed and coordinated the is when the device executor calls CheckStatus for the first time. CheckStatus will detect this condition and proceeds to call a Tcl procedure which then has to create a r\"unb\"uffer which holds the necessary commands to drive the complex movement. Or returns an error if the movement is not possible. This scheme allows the instrument scientist to adapt the way how the instrument moves to new sample environment devices, new ideas or the growth of experience. Moreover this scheme allows to handle all instruments with just a single module. As the Anti Collider has taken over the SetValue method of the drivable interface of the motor a command is provided which allows to start the actual motor. The user supplied Tcl script receives as arguments a list of motor and target values to be driven. The script then has to return either an error if the movement is not possible or the name of a r\"unb\"uffer which performs the movement. The first thing needed for all this is a data structure which holds the registration information and status of the controlled motor. This information will be kept in a list holding the data tsrucutre given below: @d motreg @{ typedef struct __MOTREG { void *motorData; char *motorName; float targetPosition; long (*originalSetValue)(void *motorData, SConnection *pCon, float fTarget); int (*originalCheckStatus)(void *motorData, SConnection *pCon); int iActive; } MotReg, *pMotReg; @} The fields are: \begin{description} \item[motorData] The motor data structure. \item[motorName] The name of the motor operating. \item[targetPosition] The requested target position for this motor. \item[originalSetValue] the original motor starting function. \item[originalCheckStatus] The original status checking function. \item[iActive] A flag denoting if the motor has been started by the Anti Collider. This causes the motors status to be checked which checking status. If the motor becomes idle, this is set to 0 again. \end{description} The following interface functions are defined for this datastructure: @d motregint @{ pMotReg RegisterMotor(char *name, SicsInterp *pSics, long (*SetValue)(void *pData, SConnection *pCon, float fTarget), int (*CheckStatus)(void *pData, SConnection *pCon)); void KillRegMot(void *self); void SetRegMotTarget(pMotReg self, float target); void CreateTargetString(pMotReg self, char pBueffel[80]); int RegMotMatch(pMotReg self, char *name); int StartRegMot(pMotReg self, SConnection *pCon, float fValue); int CheckRegMot(pMotReg self, SConnection *pCon); @} The functions in detail: \begin{description} \item[RegisterMotor] tries to find the motor name in the interpreter pSics. Then all necessary manipulations are performed in order to register the motor. In ths case of success a pointer to a new RegMot data structure is returned. In the event of failure, NULL is returned. Of course this function has to take the function pointers to the drivable interface functions to replace as parameters. \item[KillRegMot] kills a RegMot structure. \item[SetRegMotTarget] sets a new target for a complex movement. \item[CreateTragetString] creates in pBueffel this motors contribution to a complex movement. \item[RegMotMatch] returns 1 (true) if the string name matches the name stored for this motor. Else 0. This will be used when searching for a registered motor in the list. \item[StartRegMot] will actually cause a real motor to start driving towards the target given in fValue. The return value is the result of the original motors SetValue method. \item[CheckRegMot] checks for error conditions on the motor. \end{description} Moreover it is convenient to define a couple of convenience functions for handling the list of registered motors. The actual list is managed through the lld functions as everywhere within SICS. @d motlist @{ int MakeMotList(); pMotReg FindMotEntry(int iList,char *name); pMotReg FindMotFromDataStructure(int iList, void *pData); int CheckAllMotors(int iList, SConnection *pCon); void KillMotList(int iList); void StopAllMotors(int iList); void DeactivateAllMotors(int iList); @} The functions: \begin{description} \item[MakeMotList] creates a new list for MotReg structures and returns the handle for it. \item[FindMotEntry] locates a motor in the list by name. If a matching motor can be found, this function returns a pointer to the motors MotReg structure. In the case of failure NULL is returned. \item[FindMotFromDataStructure] locates a motor in the list through the pointer to its data structure. . If a matching motor can be found, this function returns a pointer to the motors MotReg structure. In the case of failure NULL is returned. \item[CheckAllMotors] checks all the active motors for the finished condition. The number of running motors is returned. 0 if none is running. \item[KillMotList] kills the list and all entries in it. \end{description} In order to know how the anticollider has to run the motors a means is needed to hold the sequence of motors to drive. This information must be configured from the anticollider script. The information is held in another list in a special data structure. @d seqlist @{ typedef struct { int level; char pMotor[80]; float target; }Sequence; int StartLevel(int level, int sequenceList, int motorList, SConnection *pCon); @} The fields and functions are: \begin{description} \item[level] The level at which this motor shall be started. \item[pMotor] The name of the motor to start. \item[target] The target value for the motor. \item[StartLevel] starts all motors belonging to a the level specified. Returns the number of motors started or ) if none is started. This last condition is also the condition when levels are exhausted and we need to finish running the anticollider. \end{description} The anticollider itself is characterized through the following data structure: @d antidat @{ typedef struct __ANTICOLLIDER{ pObjectDescriptor pDes; pIDrivable pDriv; int motorList; int sequenceList; char *colliderScript; int isDirty; int level; }AntiCollider, *pAntiCollider; @} The fields are: \begin{description} \item[pDes] The object descriptor required by SICS. \item[motorList] The list of registered motors. \item[colliderScript] the Tcl script called to calculate the movement. \item[iDirty] a flag which is set to 1 (true) when a new movement must be calculated. \end{description} Most of the anticolliders functionality is implemented in interface functions. The interface to the outside world is purely defined through the interpreter functions. @d antiint @{ int AntiColliderFactory(SConnection *pCon, SicsInterp *pSics, void *pData, int argc, char *argv[]); int AntiColliderAction(SConnection *pCon, SicsInterp *pSics, void *pData, int argc, char *argv[]); @} @o motreg.h @{ /*------------------------------------------------------------------------- R e g M o t This is a helper module for the Anti Collider. It handles all the stuff necessary for dealing with a single motor. For more information see the file anticollider.tex. copyright: see file copyright Mark Koennecke, August 2002 -----------------------------------------------------------------------*/ #ifndef REGMOT #define REGMOT #include "sics.h" @ /*----------------------------------------------------------------------*/ @ #endif @} @o motreglist.h @{ /*----------------------------------------------------------------------- A couple of utility functions for handling a list of MotReg structures . This is a helper module for the anticollider collision control system. See anticollider.tex for more details. copyright: see file copyright Mark Koennecke, August 2002 -------------------------------------------------------------------------*/ #ifndef MOTREGLIST #define MOTREGLIST #include "motreg.h" @ #endif @} @o anticollider.i @{ /*------------------------------------------------------------------------- Anticollider internal data structure definition. Generated from anticollider.w. Do not edit. -------------------------------------------------------------------------*/ @ @ @} @o anticollider.h @{ /*---------------------------------------------------------------------- This is the header file for the AntiCollider, a complex movements control module for SICS. See anticoliider.tex for more information. copyright: see file copyright Mark Koennecke, August 2002 ------------------------------------------------------------------------*/ #ifndef ANTICOLLIDER #define ANTICOLLIDER @ #endif @}