278 lines
9.7 KiB
OpenEdge ABL
278 lines
9.7 KiB
OpenEdge ABL
\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"
|
|
|
|
@<motreg@>
|
|
|
|
/*----------------------------------------------------------------------*/
|
|
@<motregint@>
|
|
|
|
#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"
|
|
|
|
@<motlist@>
|
|
|
|
|
|
#endif
|
|
|
|
|
|
@}
|
|
|
|
|
|
@o anticollider.i @{
|
|
/*-------------------------------------------------------------------------
|
|
Anticollider internal data structure definition. Generated from
|
|
anticollider.w. Do not edit.
|
|
-------------------------------------------------------------------------*/
|
|
@<antidat@>
|
|
@<seqlist@>
|
|
|
|
@}
|
|
|
|
@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
|
|
|
|
@<antiint@>
|
|
|
|
#endif
|
|
|
|
|
|
|
|
@} |