File: WORKFLOW\TScanCmd.cpp
1 #include "workflow\TScanCmd.h"
2
3 extern TSteering Steering;
4 extern TMain Main; // in MAIN.CPP deklariertes Hauptprogramm
5
6 TScanCmd::TScanCmd ( TCmdTag ct ) : TCmd( ct ), Scaler(0)
7 {
8 // gibt fuer areascan im standardscan an ob psd-offset verwendet wird
9 bChannelOffset= FALSE;
10
11 // FIX Fehler 72
12 bRestart= FALSE;
13 // Schrittweitensteuerung deaktivieren + Art des Scans aus Kommando holen
14 bDynamicStepWidth= FALSE;
15 nStepScaleLevels= 0;
16 Scaler= NULL;
17 eCaller= ct.P1;
18 // abhaengig von der Art des Scans
19 switch ( ct.P1 )
20 {
21 // wenn AreaScan-kommando
22 case ForAreaScan:
23 // zum Kommando gehoeriges AreaScanFenster ermitteln + wenn keins
24 // existiert dann Fehlermeldung + abbruch
25 AreaScanW= (TAreaScanWindow*) Main.AreaScanWindow;
26 if ( !AreaScanW )
27 {
28 #ifdef GermanVersion
29 MessageBox( GetFocus(), "Kein AreaScan-Fenster offen", "Fehler", MBSTOP );
32 #endif
33 return;
34 }
35 // uebernehmen von Werten aus AreaScan + loeschen Datenbasis +
36 // neuzeichnen Fenster
37 bAbsorberUsed= AreaScanW->ReportUse.bAbsorber;
38 eScanType= AreaScanW->eScanType;
39 AreaScanW->New();
40 AreaScanW->bMeasurementActive= TRUE;
41 AreaScanW->UpdateWnd();
42 //Datum: 28.07.2002 bMonitorUsed= AreaScanW->ReportUse.bMonitor;
43 //Datum: 28.07.2002 if ( bMonitorUsed ) Monitor= AreaScanW->Monitor;
44 if ( AreaScanW->Monitor != 0 )
45 Steering.Monitor= AreaScanW->Monitor;
46
47 switch ( eScanType )
48 {
49 // bewegen omega + theta
50 case stOmega2ThetaScan:
51 // uebernehmen von Werten aus AreaScan
52 bOmega2Theta= TRUE;
53 // berechnen der Min- und Maxwerte incl. offset
54 dArgumentMin= AreaScanW->dOmegaMin - AreaScanW->dOffsetOmega;
55 dArgumentWidth= AreaScanW->dOmegaWidth;
56 dArgumentMax= AreaScanW->dOmegaMax - AreaScanW->dOffsetOmega;
57 dMoveRelation= AreaScanW->dMoveRelation;
58 dThetaMin= AreaScanW->d2ThetaStart - AreaScanW->dOffsetTheta + AreaScanW->dPsdOffset;
59 break;
60
61 // nur omega bewegen
62 case stStandardScan:
63 // uebernehmen von Werten aus AreaScan
64 // uebernehmen der 2Thetaposition ,die waehrend des scans
65 // beibehalten werden soll
66 dThetaMin= AreaScanW->d2ThetaStart;
67 bChannelOffset= mlIsAxisValid(Theta);
68 if ( AreaScanW->nMeasurementChannel != 0 )
69 dThetaMin += AreaScanW->dPsdOffset;
70 bOmega2Theta= FALSE;
71 // berechnen der Min- und Maxwerte incl. offset
72 dArgumentMin= AreaScanW->dOmegaMin - AreaScanW->dOffsetOmega;
73 dArgumentWidth= AreaScanW->dOmegaWidth;
74 dArgumentMax= AreaScanW->dOmegaMax - AreaScanW->dOffsetOmega;
75 break;
76
77 default:
78 #ifdef GermanVersion
79 MessageBox( GetFocus(), "Scan-Start fehlgeschlagen.", "Steuerung", MBSTOP );
82 #endif
83 } // switch (eScanType)
84 break; //ForAreaScan
85
86 // wenn Stepscan
87 case ForScan:
88 // zum Kommando gehöriges StepScanFenster ermitteln + wenn keins
89 // existiert, dann Fehlermeldung + abbruch
90 ScanW= (TScanWindow*) Main.ScanWindow;
91 if ( !ScanW )
92 {
93 #ifdef GermanVersion
94 MessageBox( GetFocus(), "Kein Scan-Fenster offen", "Fehler", MBSTOP );
97 #endif
98 return;
99 }
100 // FIX Fehler 15
101 //Datum: 28.07.2002 bMonitorUsed= ScanW->bMonitorUsed;
102 //Datum: 28.07.2002 if ( bMonitorUsed ) Monitor= TDList::GetDetectorListPtr()->GetDetectorPtr(ScanW->Monitor->GetId());
103 if ( ScanW->Monitor != 0 )
104 Steering.Monitor= ScanW->Monitor;
105
106 // Absorber deaktivieren (nur bei Areascan)
107 bAbsorberUsed= FALSE;
108 // Werte für dynamische Schrittweitensteuerung aus Scanfenster holen
109 bDynamicStepWidth= ScanW->bDynamicStepWidth;
110 nStepScaleLevels= ScanW->nStepScaleLevels;
111 Scaler= &ScanW->Scaler;
112 // eingestellten Scantyp ermitteln (Standard oder Omega2Theta)
113 eScanType= ScanW->eScanType;
114 // Maincurve löschen, Fenster neuzeichnen ...
115 ScanW->New();
116 // Messung als nicht unterbrochen und aktiv kennzeichnen
117 ScanW->bInterrupted= FALSE;
118 ScanW->bMeasurementActive= TRUE;
119 // neu zeichnen
120 ScanW->UpdateWnd();
121 // abhaengig von eingest. Scantyp
122 switch ( eScanType )
123 {
124 // wenn Omega2ThetaScan
125 case stOmega2ThetaScan:
126 // Omega2ThetaScan als aktiv kennzeichnen + Parameter wie
127 // Startwinkel,Endwinkel und normale Schrittweite des Omegamotors
128 // fuer den Scan aus Scanfenster holen + schrittverhaeltnis von Om.
129 // zu Theta auf 2 setzen
130 bOmega2Theta= TRUE;
131 dArgumentMin= ScanW->dArgumentMin;
132 dArgumentWidth= ScanW->dArgumentWidth;
133 dArgumentMax= ScanW->dArgumentMax;
134 dMoveRelation= 2.0;
135 // 2Thetastartpos. aus Scanfenster
136 dThetaMin= ScanW->d2ThetaStart;
137 break;
138
139 // wenn Standard-scan
140 case stStandardScan:
141 // Omega2ThetaScan als inaktiv kennzeichnen + Parameter wie
142 // Startwinkel, Endwinkel und normale Schrittweite des eingest.
143 // motors fuer den Scan aus Scanfenster holen
144 bOmega2Theta= FALSE;
145 dArgumentMin= ScanW->dArgumentMin;
146 dArgumentWidth= ScanW->dArgumentWidth;
147 dArgumentMax= ScanW->dArgumentMax;
148 break;
149
150 // unbekannter Scantyp(weder Standard- noch Omega2ThetaScan)
151 default:
152 #ifdef GermanVersion
153 MessageBox( GetFocus(), "Scan-Start fehlgeschlagen.", "Steuerung", MBSTOP );
156 #endif
157 } // switch ( eScanType )
158 break; //ForScan
159
160 // unbekannte Scanart(weder Step- noch AreaScan)
161 default:
162 #ifdef GermanVersion
163 MessageBox( GetFocus(), "Scan-Start", "Fehler", MBSTOP );
166 #endif
167 eStep= CReady;
168 bNoMeasure= TRUE;
169 return;
170 } // switch ( ct.P1 )
171
172 // aktiven motor + aktive Pos. des Motors bestimmen
173 nMotor= mlGetAxis(); // Startup
174 mlGetDistance( nMotor, Steering.dStartPoint );
175 // motor zum Startwinkel des Scans bewegen + dieser ist erster Messpunkt
176 StartMove( nMotor, dArgumentMin );
177 dArgument= dArgumentMin;
178 // bei Om.2Th. akt. Winkel des Thetamotors bestimmen + auf Startpos. bewegen
179 // bei psd-offset im areascan(standardmodus) nur auf startposition fahren
180 if ( bOmega2Theta || bChannelOffset )
181 {
182 nTheta= mlGetIdByName( Theta );
183 mlGetDistance( nTheta, dStartPointTheta );
184 // Thetaschrittweite berechnen
185 dThetaWidth= dArgumentWidth * dMoveRelation;
186 StartMove( nTheta, dThetaMin );
187 dArgument2= dThetaMin;
188 }
189 // wenn absorber benutzt wird (nur AreaScan) dann aktuelle Pos. des
190 // Absorbermotors ermitteln und ihn auf Pos. 0.0 bewegen
191 if ( bAbsorberUsed )
192 {
193 nAbsorber= mlGetIdByName( Absorber );
194 //21.04.2004 bAbsorberMovedIn= FALSE;
195 //21.04.2004 bAbsorberActivated= FALSE;
196 mlGetDistance( nAbsorber, dStartPointAbsorber );
197 StartMove( nAbsorber, 0.0 );
198 }
199 // Ausgabe in Statuszeile + akt. Schritt des Scans auf ersten Schritt
200 // setzen + Anzahl der Voraussichtlich (ohne dyn. Schrittweite) zu
201 // erwartende Messpunkte
202 #ifdef GermanVersion
203 SetInfo( "Anfahren der Startposition ..." );
206 #endif
207 eStep= CFirstStep;
208 nPointNumber= ( dArgumentMax - dArgumentMin ) / dArgumentWidth;
209 bNoMeasure= TRUE;
210 dwStartTimeTicks= 0;
211 };
212
213 void TScanCmd::GetName ( LPSTR aName )
214 {
215 strcpy( aName, "Scan" );
216 }
217
218 bool TScanCmd::GetShowData ( LPSTR buffer )
219 {
220 buffer[0]= 0;
221 float fTimeRemaining;
222 char fmt[ MaxString ];
223 DWORD dwElapsedTicks;
224
225 if ( eStep == CReady )
226 {
227 #ifdef GermanVersion
228 sprintf( buffer, "Scan abgeschlossen" );
231 #endif
232 }
233 else if ( eStep == CControlStep )
234 {
235 // ermittelt zeit seit scanstart
236 dwElapsedTicks= GetTickCount() - dwStartTimeTicks;
237
238 /* bei ersten schritt verbleibende zeit =0.0 danach jeweils berechnen
239 wieviel zeit bisher pro Messpunkt gebraucht wurde und umrechnen ,
240 wieviel dann für die folgenden Meßpunkte noch gebraucht wird
241 (funktioniert nicht bei dynam. Schrittweitensteuerung)
242 */
243 if (nPointIdx)
244 {
245 fTimeRemaining= ( dwElapsedTicks / 60000.0 ) / nPointIdx;
246 fTimeRemaining *= ( nPointNumber - nPointIdx + 1 );
247 }
248 else
249 fTimeRemaining= 0.0;
250
251 #ifdef GermanVersion
252 sprintf( fmt, "Scan ... Winkel= " );
253 strcat( fmt, mGetDF() );
254 strcat( fmt, " Intensität= %.3f" );
255 // Aenderung Dynamische Schrittweite
256 // Ausgabe der verbleibenden Zeit nur, wenn keine dyn. Schrittweite
257 if (!bDynamicStepWidth)
258 strcat( fmt, " verbl. Zeit= %.1f Min." );
267 #endif
268 // string mit Param. füllen
269 sprintf( buffer, fmt, mGetValue( Distance ), Steering.GetIntensity(), fTimeRemaining );
270 //Datum: 24.07.2002 SetInfo( buffer ); //!? scheinbar ueberfluessig (siehe Fkt.beschreibung)
271 //Datum: 24.07.2002 buffer[ 0 ]= 0; //!? scheinbar ueberfluessig (siehe Fkt.beschreibung)
272 }
273 return true;
274 }
275
276 ECmdCode TScanCmd::FirstStep ( void )
277 {
278 // akt. Schritt= Controlschritt + anzahl bereits gemessener Punkte auf 0 +
279 // akt. Zeitwert sichern
280 eStep= CControlStep;
281 nPointIdx= 0;
282 dwStartTimeTicks= GetTickCount();
283 return CMeasure;
284 };
285
286 ECmdCode TScanCmd::ControlStep ( void )
287 {
288 float fStepScaler= 1.0, fIntensity, fNorm;
289 int nScaleLevel= 0;
290
291 // wenn dyn. Schrittweite eingestellt dann vergleichen der gemessenen
292 // Intensitaet mit den Intensitaetswerten aus Scaler bei erstem
293 // Scaler-int.-wert, der groesser ist, wird die zu diesem scaler-int.-wert
294 // gehoerig Schrittweite als Schrittweitenfaktor festgelegt ansonsten
295 // bleibt dieser Faktor auf 1.0
296 // FIX Fehler 72 Diff./Refl.
297 if (!bRestart)
298 {
299 if ( bDynamicStepWidth )
300 {
301 fIntensity= Steering.GetIntensity();
302 // auch die Scalerwerte muessen durch Monit.int. normiert werden
303 fNorm= ( Steering.GetNorm() != 0.0 ) ? Steering.GetNorm() : 1.0;
304 while ( nScaleLevel < nStepScaleLevels )
305 {
306 if ( fIntensity > ( Scaler->GetAt(nScaleLevel) / fNorm ) )
307 {
308 nScaleLevel++;
309 continue;
310 }
311 fStepScaler= Scaler->GetAt(nScaleLevel + nMaxScaleIdx);
312 break;
313 }
314 }
315
316 // wenn aktuelle Pos. des motors noch kleiner als endwinkel des Scans dann
317 // anzahl gemessener Punkte erhoehen + naechsten Meßpunkt des Motors
318 // berechnen (dabei schrittweite beachten) + anfahren dieses Punktes
319 // bei Omega2Theta den Thetamotor auf neue pos. bewegen
320 // FIX Fehler 75
321 if ( Steering.GetDistance() < dArgumentMax )
322 {
323 nPointIdx++;
324 dArgument += dArgumentWidth * fStepScaler;
325 StartMove( nMotor, dArgument );
326 if ( bOmega2Theta )
327 {
328 dArgument2 += dThetaWidth * fStepScaler;
329 StartMove( nTheta, dArgument2 );
330 }
331 return CRecall;
332 }
333 }
334 else
335 { // FIX Fehler 72 Diff./Refl.
336 bRestart= FALSE;
337 StartMove( nMotor, dArgument );
338 if ( bOmega2Theta)
339 StartMove( nTheta, dArgument2 );
340 return CRecall;
341 }
342
343 // wenn endwinkel erreicht (bzw. darueber hinaus) dann naechsten Schritt als
344 // Endschritt kennzeichnen + aktiven Motor (und ev. Theta)auf Position vor
345 // start des Scan zurueckbewegen
346 eStep= CReadyStep;
347 bNoMeasure= TRUE;
348 StartMove( nMotor, Steering.dStartPoint );
349 if ( bOmega2Theta || bChannelOffset)
350 StartMove( nTheta, dStartPointTheta );
351 return CRecall;
352 };
353
354 ECmdCode TScanCmd::ReadyStep ( void )
355 {
356 // naechster schritt soll scan beenden (wird ReadyReaction aufrufen)
357 eStep= CReady;
358 switch ( eCaller )
359 {
360 // bei Stepscan die messung als nicht aktiv kennzeichnen
361 case ForScan:
362 ScanW->bMeasurementActive= FALSE;
363 break;
364 }
365 return CRecall;
366 };
367