source: trunk/FACT++/src/feedback.cc@ 12238

Last change on this file since 12238 was 12234, checked in by tbretz, 13 years ago
Allow STOP in all states.
File size: 27.3 KB
Line 
1#include <valarray>
2
3#include "Dim.h"
4#include "Event.h"
5#include "Shell.h"
6#include "StateMachineDim.h"
7#include "Connection.h"
8#include "Configuration.h"
9#include "Console.h"
10#include "Converter.h"
11#include "DimServiceInfoList.h"
12#include "PixelMap.h"
13
14#include "tools.h"
15
16#include "LocalControl.h"
17
18#include "HeadersFAD.h"
19#include "HeadersBIAS.h"
20
21namespace ba = boost::asio;
22namespace bs = boost::system;
23namespace dummy = ba::placeholders;
24
25using namespace std;
26
27// ------------------------------------------------------------------------
28
29#include "DimDescriptionService.h"
30
31// ------------------------------------------------------------------------
32
33class StateMachineFeedback : public StateMachineDim, public DimInfoHandler
34{
35 /*
36 int Wrap(boost::function<void()> f)
37 {
38 f();
39 return T::GetCurrentState();
40 }
41
42 boost::function<int(const EventImp &)> Wrapper(boost::function<void()> func)
43 {
44 return bind(&StateMachineMCP::Wrap, this, func);
45 }*/
46
47private:
48 enum states_t
49 {
50 kStateDimNetworkNA = 1,
51 kStateDisconnected,
52 kStateConnecting,
53 kStateConnected,
54 kStateTempCtrlIdle,
55 kStateFeedbackCtrlIdle,
56 kStateTempCtrlRunning,
57 kStateFeedbackCtrlRunning,
58 };
59
60 PixelMap fMap;
61
62 DimServiceInfoList fNetwork;
63
64 pair<Time, int> fStatusDim;
65 pair<Time, int> fStatusFAD;
66 pair<Time, int> fStatusFSC;
67 pair<Time, int> fStatusBias;
68
69 DimStampedInfo fDim;
70 DimStampedInfo fFAD;
71 DimStampedInfo fFSC;
72 DimStampedInfo fBias;
73
74 DimStampedInfo *fBiasData;
75 DimStampedInfo *fCameraTemp;
76
77 DimDescribedService fDimReference;
78 DimDescribedService fDimDeviation;
79
80 vector<vector<float>> fData;
81
82 uint64_t fCursor;
83
84 Time fBiasLast;
85 Time fStartTime;
86
87 valarray<double> fPV[3]; // Process variable (intgerated/averaged amplitudes)
88 valarray<double> fSP; // Set point (target amplitudes)
89
90 double fKp; // Proportional constant
91 double fKi; // Integral constant
92 double fKd; // Derivative constant
93 double fT; // Time constant (cycle time)
94 double fGain; // Gain (conversion from a DRS voltage deviation into a BIAS voltage change at G-APD reference voltage)
95
96 double fT21;
97
98 bool fOutputEnabled;
99
100 pair<Time, int> GetNewState(DimStampedInfo &info) const
101 {
102 const bool disconnected = info.getSize()==0;
103
104 // Make sure getTimestamp is called _before_ getTimestampMillisecs
105 const int tsec = info.getTimestamp();
106 const int tms = info.getTimestampMillisecs();
107
108 return make_pair(Time(tsec, tms*1000),
109 disconnected ? -2 : info.getQuality());
110 }
111
112 void ResetData()
113 {
114 fData.clear();
115 fData.resize(500);
116 fCursor = 0;
117 fStartTime = Time();
118
119 fSP.resize(416);
120 fSP = valarray<double>(0., 416);
121
122 vector<float> vec(2*BIAS::kNumChannels);
123 fDimDeviation.Update(vec);
124
125 fPV[0].resize(0);
126 fPV[1].resize(0);
127 fPV[2].resize(0);
128
129 if (fKp==0 && fKi==0 && fKd==0)
130 Warn("Control loop parameters are all set to zero.");
131 }
132
133 void infoHandler()
134 {
135 DimInfo *curr = getInfo(); // get current DimInfo address
136 if (!curr)
137 return;
138
139 if (curr==&fBias)
140 {
141 fStatusBias = GetNewState(fBias);
142 return;
143 }
144
145 if (curr==&fFAD)
146 {
147 fStatusFAD = GetNewState(fFAD);
148 return;
149 }
150
151 if (curr==&fFSC)
152 {
153 fStatusFSC = GetNewState(fFSC);
154 return;
155 }
156
157 if (curr==&fDim)
158 {
159 fStatusDim = GetNewState(fDim);
160 fStatusDim.second = curr->getSize()==4 ? curr->getInt() : 0;
161 return;
162 }
163
164 if (curr==fCameraTemp)
165 {
166 if (curr->getSize()==0)
167 return;
168 if (curr->getSize()!=60*sizeof(float))
169 return;
170
171 const float *ptr = (float*)curr->getData();
172
173 double avg = 0;
174 int num = 0;
175 for (int i=1; i<32; i++)
176 if (ptr[i]!=0)
177 {
178 avg += ptr[i];
179 num++;
180 }
181
182 if (num==0)
183 return;
184
185 avg /= num;
186
187
188 const float diff = (avg-25)*0.057;
189
190 vector<float> vec(2*BIAS::kNumChannels);
191 for (int i=0; i<BIAS::kNumChannels; i++)
192 vec[i+416] = diff;
193
194 fDimDeviation.Update(vec);
195
196 if (fOutputEnabled)
197 {
198 Info("Sending correction to feedback.");
199
200 DimClient::sendCommandNB((char*)"BIAS_CONTROL/SET_GAPD_REFERENCE_OFFSET",
201 (void*)&diff, sizeof(float));
202 }
203 return;
204 }
205
206 if (curr==fBiasData)
207 {
208 if (curr->getSize()==0)
209 return;
210 if (curr->getSize()!=1440*sizeof(float))
211 return;
212
213 // -------- Check age of last stored event --------
214
215 // Must be called in this order
216 const int tsec = curr->getTimestamp();
217 const int tms = curr->getTimestampMillisecs();
218
219 const Time tm(tsec, tms*1000);
220
221 if (Time()-fBiasLast>boost::posix_time::seconds(30))
222 {
223 Warn("Last received event data older than 30s... resetting average calculation.");
224 ResetData();
225 }
226 fBiasLast = tm;
227
228 // -------- Store new event --------
229
230 fData[fCursor%fData.size()].assign(reinterpret_cast<float*>(curr->getData()),
231 reinterpret_cast<float*>(curr->getData())+1440);
232
233
234 fCursor++;
235
236 if (fCursor<fData.size())
237 return;
238
239 // -------- Calculate statistics --------
240
241 valarray<double> med(1440);
242
243 for (int ch=0; ch<1440; ch++)
244 {
245 vector<float> arr(fData.size());
246 for (size_t i=0; i<fData.size(); i++)
247 arr[i] = fData[i][ch];
248
249 sort(arr.begin(), arr.end());
250
251 med[ch] = arr[arr.size()/2];
252 }
253
254 /*
255 vector<float> med(1440);
256 vector<float> rms(1440);
257 for (size_t i=0; i<fData.size(); i++)
258 {
259 if (fData[i].size()==0)
260 return;
261
262 for (int j=0; j<1440; j++)
263 {
264 med[j] += fData[i][j];
265 rms[j] += fData[i][j]*fData[i][j];
266 }
267 }
268 */
269
270 vector<double> avg(BIAS::kNumChannels);
271 vector<int> num(BIAS::kNumChannels);
272 for (int i=0; i<1440; i++)
273 {
274 const PixelMapEntry &ch = fMap.hw(i);
275
276 // FIXME: Add a consistency check if the median makes sense...
277 // FIXME: Add a consistency check to remove pixels with bright stars (median?)
278
279 avg[ch.hv()] += med[i];
280 num[ch.hv()]++;
281 }
282
283 for (int i=0; i<BIAS::kNumChannels; i++)
284 {
285 if (num[i])
286 avg[i] /= num[i];
287
288 }
289
290 // -------- Calculate correction --------
291
292 // http://bestune.50megs.com/typeABC.htm
293
294 // CO: Controller output
295 // PV: Process variable
296 // SP: Set point
297 // T: Sampling period (loop update period)
298 // e = SP - PV
299 //
300 // Kp : No units
301 // Ki : per seconds
302 // Kd : seconds
303
304 // CO(k)-CO(k-1) = - Kp[ PV(k) - PV(k-1) ] + Ki * T * (SP(k)-PV(k)) - Kd/T [ PV(k) - 2PV(k-1) + PV(k-2) ]
305
306 if (fCursor%fData.size()==0)
307 {
308 // FIXME: Take out broken / dead boards.
309
310 const Time tm0 = Time();
311
312 const double T21 = fT>0 ? fT : (tm0-fStartTime).total_microseconds()/1000000.;
313 const double T10 = fT21;
314 fT21 = T21;
315
316 fStartTime = tm0;
317
318 ostringstream out;
319 out << "New " << fData.size() << " event received: " << fCursor << " / " << setprecision(3) << T21 << "s";
320 Info(out);
321
322 if (fPV[0].size()==0)
323 {
324 fPV[0].resize(avg.size());
325 fPV[0] = valarray<double>(avg.data(), avg.size());
326 }
327 else
328 if (fPV[1].size()==0)
329 {
330 fPV[1].resize(avg.size());
331 fPV[1] = valarray<double>(avg.data(), avg.size());
332 }
333 else
334 if (fPV[2].size()==0)
335 {
336 fPV[2].resize(avg.size());
337 fPV[2] = valarray<double>(avg.data(), avg.size());
338 }
339 else
340 {
341 fPV[0] = fPV[1];
342 fPV[1] = fPV[2];
343
344 fPV[2].resize(avg.size());
345 fPV[2] = valarray<double>(avg.data(), avg.size());
346
347 if (T10<=0 || T21<=0)
348 return;
349
350 cout << "Calculating (" << fCursor << ":" << T21 << ")... " << endl;
351
352 // fKi[j] = response[j]*gain;
353 // Kp = 0;
354 // Kd = 0;
355
356 // => Kp = 0.01 * gain = 0.00005
357 // => Ki = 0.8 * gain/20s = 0.00025
358 // => Kd = 0.1 * gain/20s = 0.00003
359
360 //valarray<double> correction =
361 // - Kp * (PV[2] - PV[1])
362 // + dT * Ki * (SP - PV[2])
363 // - Kd / dT * (PV[2] - 2*PV[1] + PV[0]);
364 //
365 // - (Kp+Kd/dT1) * (PV[2] - PV[1])
366 // + dT2 * Ki * (SP - PV[2])
367 // + Kd / dT1 * (PV[1] - PV[0]);
368 //
369 // - Kp * (PV[2] - PV[1])
370 // + Ki * (SP - PV[2])*dT
371 // - Kd * (PV[2] - PV[1])/dT
372 // + Kd * (PV[1] - PV[0])/dT;
373 //
374 //valarray<double> correction =
375 // - Kp*(PV[2] - PV[1]) + Ki * T21 * (SP-PV[2]) - Kd*(PV[2]-PV[1])/T21 - Kd*(PV[0]-PV[1])/T01;
376 const valarray<double> correction = fGain/1000*
377 (
378 - (fKp+fKd/T21)*(fPV[2] - fPV[1])
379 + fKi*T21*(fSP-fPV[2])
380 + fKd/T10*(fPV[1]-fPV[0])
381 );
382
383 /*
384 integral = 0
385 start:
386 integral += (fSP - fPV[2])*dt
387
388 output = Kp*(fSP - fPV[2]) + Ki*integral - Kd*(fPV[2] - fPV[1])/dt
389
390 wait(dt)
391
392 goto start
393 */
394
395 vector<float> vec(2*BIAS::kNumChannels);
396 for (int i=0; i<BIAS::kNumChannels; i++)
397 vec[i] = fPV[2][i]-fSP[i];
398
399 for (int i=0; i<BIAS::kNumChannels; i++)
400 vec[i+416] = correction[i];
401
402 fDimDeviation.Update(vec);
403
404 if (fOutputEnabled)
405 {
406 Info("Sending correction to feedback.");
407
408 DimClient::sendCommandNB((char*)"BIAS_CONTROL/ADD_REFERENCE_VOLTAGES",
409 (void*)(vec.data()+416), 416*sizeof(float));
410
411 /*
412 if (!Dim::SendCommand("BIAS_CONTROL/ADD_REFERENCE_VOLTAGES",
413 (const void*)(vec.data()+416), 416*sizeof(float)))
414 {
415 Error("Sending correction to bias control failed... switching off.");
416 fOutputEnabled=false;
417 }
418 else
419 Info("Success!");
420 */
421 }
422 }
423
424 }
425
426 /*
427 vector<float> correction(416);
428 vector<float> response(416);
429 vector<float> dev(416);
430
431 double gain = 0;
432
433 for (int j=0; j<416; j++)
434 {
435 //avg[j] /= fData.size();
436 //rms[j] /= sqrt((rms[j]*fData.size() - avg[j]*avg[j]))/fData.size();
437
438 dev[j] = avg[j] - target[j];
439
440 // Determine correction from response maxtrix and change voltages
441 correction[j] = -dev[j]*response[j]*gain;
442
443 if (correction[j]==0)
444 continue;
445
446 // Limit voltage steps // Limit changes to 100 mV
447// if (fabs(correction[j]) > 0.1)
448// correction[j] = 0.1*fabs(correction[j])/correction[j];
449
450 // Add voltage change command if not too noisy
451// if (fabs(Average[i]) > 2*Sigma[i])
452// Cmd << fIDTable[i] << " " << std::showpos << Correction/Multiplicity[i] << " ";
453
454 }
455 */
456 return;
457 }
458
459 }
460
461 bool CheckEventSize(size_t has, const char *name, size_t size)
462 {
463 if (has==size)
464 return true;
465
466 ostringstream msg;
467 msg << name << " - Received event has " << has << " bytes, but expected " << size << ".";
468 Fatal(msg);
469 return false;
470 }
471
472 void PrintState(const pair<Time,int> &state, const char *server)
473 {
474 const State rc = fNetwork.GetState(server, state.second);
475
476 Out() << state.first.GetAsStr("%H:%M:%S.%f").substr(0, 12) << " - ";
477 Out() << kBold << server << ": ";
478 Out() << rc.name << "[" << rc.index << "]";
479 Out() << kReset << " - " << kBlue << rc.comment << endl;
480 }
481
482 int Print()
483 {
484 Out() << fStatusDim.first.GetAsStr("%H:%M:%S.%f").substr(0, 12) << " - ";
485 Out() << kBold << "DIM_DNS: ";
486 if (fStatusDim.second==0)
487 Out() << "Offline" << endl;
488 else
489 Out() << "V" << fStatusDim.second/100 << 'r' << fStatusDim.second%100 << endl;
490
491 PrintState(fStatusFAD, "FAD_CONTROL");
492 PrintState(fStatusBias, "BIAS_CONTROL");
493
494 return GetCurrentState();
495 }
496
497 int SetConstant(const EventImp &evt, int constant)
498 {
499 if (!CheckEventSize(evt.GetSize(), "SetConstant", 8))
500 return kSM_FatalError;
501
502 switch (constant)
503 {
504 case 0: fKi = evt.GetDouble(); break;
505 case 1: fKp = evt.GetDouble(); break;
506 case 2: fKd = evt.GetDouble(); break;
507 case 3: fT = evt.GetDouble(); break;
508 case 4: fGain = evt.GetDouble(); break;
509 default:
510 Fatal("SetConstant got an unexpected constant id -- this is a program bug!");
511 return kSM_FatalError;
512 }
513
514 return GetCurrentState();
515 }
516
517 int EnableOutput(const EventImp &evt)
518 {
519 if (!CheckEventSize(evt.GetSize(), "EnableOutput", 1))
520 return kSM_FatalError;
521
522 fOutputEnabled = evt.GetBool();
523
524 return GetCurrentState();
525 }
526
527 int StartFeedback()
528 {
529 fBiasData = new DimStampedInfo("FAD_CONTROL/FEEDBACK_DATA", (void*)NULL, 0, this);
530
531 ResetData();
532
533 return GetCurrentState();
534 }
535
536 int StartTempCtrl()
537 {
538 fCameraTemp = new DimStampedInfo("FSC_CONTROL/TEMPERATURE", (void*)NULL, 0, this);
539
540 return GetCurrentState();
541 }
542
543 int StopFeedback()
544 {
545 if (fBiasData)
546 {
547 delete fBiasData;
548 fBiasData = 0;
549 }
550
551 if (fCameraTemp)
552 {
553 delete fCameraTemp;
554 fCameraTemp = 0;
555 }
556
557 return GetCurrentState();
558 }
559
560 int StoreReference()
561 {
562 if (!fPV[0].size() && !fPV[1].size() && !fPV[2].size())
563 {
564 Warn("No values in memory. Take enough events first!");
565 return GetCurrentState();
566 }
567
568 // FIXME: Check age
569
570 if (!fPV[1].size() && !fPV[2].size())
571 fSP = fPV[0];
572
573 if (!fPV[2].size())
574 fSP = fPV[1];
575 else
576 fSP = fPV[2];
577
578 vector<float> vec(BIAS::kNumChannels);
579 for (int i=0; i<BIAS::kNumChannels; i++)
580 vec[i] = fSP[i];
581 fDimReference.Update(vec);
582
583 return GetCurrentState();
584 }
585
586 int SetReference(const EventImp &evt)
587 {
588 if (!CheckEventSize(evt.GetSize(), "SetReference", 4))
589 return kSM_FatalError;
590
591 const float val = evt.GetFloat();
592 if (!fPV[0].size() && !fPV[1].size() && !fPV[2].size())
593 {
594 Warn("No values in memory. Take enough events first!");
595 return GetCurrentState();
596 }
597
598 vector<float> vec(BIAS::kNumChannels);
599 for (int i=0; i<BIAS::kNumChannels; i++)
600 vec[i] = fSP[i] = val;
601 fDimReference.Update(vec);
602
603 return GetCurrentState();
604 }
605
606
607 int Execute()
608 {
609 // Dispatch (execute) at most one handler from the queue. In contrary
610 // to run_one(), it doesn't wait until a handler is available
611 // which can be dispatched, so poll_one() might return with 0
612 // handlers dispatched. The handlers are always dispatched/executed
613 // synchronously, i.e. within the call to poll_one()
614 //poll_one();
615
616 if (fStatusDim.second==0)
617 return kStateDimNetworkNA;
618
619 // All subsystems are not connected
620 if (fStatusFAD.second<FAD::kConnected &&
621 fStatusBias.second<BIAS::kConnecting &&
622 fStatusFSC.second<2)
623 return kStateDisconnected;
624
625 // At least one subsystem is not connected
626 if (fStatusFAD.second<FAD::kConnected ||
627 fStatusBias.second<BIAS::kConnected ||
628 fStatusFSC.second<2)
629 return kStateConnecting;
630
631 // All subsystems are connected
632
633 if (fBiasData)
634 return fOutputEnabled ? kStateFeedbackCtrlRunning : kStateFeedbackCtrlIdle;
635
636 if (fCameraTemp)
637 return fOutputEnabled ? kStateTempCtrlRunning : kStateTempCtrlIdle;
638
639 return kStateConnected;
640 }
641
642public:
643 StateMachineFeedback(ostream &out=cout) : StateMachineDim(out, "FEEDBACK"),
644 fStatusDim(make_pair(Time(), -2)),
645 fStatusFAD(make_pair(Time(), -2)),
646 fStatusBias(make_pair(Time(), -2)),
647 fDim("DIS_DNS/VERSION_NUMBER", (void*)NULL, 0, this),
648 fFAD("FAD_CONTROL/STATE", (void*)NULL, 0, this),
649 fFSC("FSC_CONTROL/STATE", (void*)NULL, 0, this),
650 fBias("BIAS_CONTROL/STATE", (void*)NULL, 0, this),
651 fBiasData(0), fCameraTemp(0),
652 fDimReference("FEEDBACK/REFERENCE", "F:416", ""),
653 fDimDeviation("FEEDBACK/DEVIATION", "F:416;F:416", ""),
654 fKp(0), fKi(0), fKd(0), fT(-1), fOutputEnabled(false)
655 {
656 // ba::io_service::work is a kind of keep_alive for the loop.
657 // It prevents the io_service to go to stopped state, which
658 // would prevent any consecutive calls to run()
659 // or poll() to do nothing. reset() could also revoke to the
660 // previous state but this might introduce some overhead of
661 // deletion and creation of threads and more.
662
663 // State names
664 AddStateName(kStateDimNetworkNA, "DimNetworkNotAvailable",
665 "The Dim DNS is not reachable.");
666
667 AddStateName(kStateDisconnected, "Disconnected",
668 "The Dim DNS is reachable, but the required subsystems are not available.");
669
670 AddStateName(kStateConnecting, "Connecting",
671 "Not all subsystems (FAD, FSC, Bias) are connected to their hardware.");
672
673 AddStateName(kStateConnected, "Connected",
674 "All needed subsystems are connected to their hardware, no action is performed.");
675
676 AddStateName(kStateFeedbackCtrlIdle, "FeedbackIdle",
677 "Feedback control activated, but voltage output disabled.");
678
679 AddStateName(kStateTempCtrlIdle, "FeedbackIdle",
680 "Temperature control activated, but voltage output disabled.");
681
682 AddStateName(kStateFeedbackCtrlRunning, "FeedbackControl",
683 "Feedback control activated and voltage output enabled.");
684
685 AddStateName(kStateTempCtrlRunning, "TempControl",
686 "Temperature control activated and voltage output enabled.");
687
688 AddEvent("START_FEEDBACK_CONTROL", kStateConnected)
689 (bind(&StateMachineFeedback::StartFeedback, this))
690 ("Start the feedback control loop");
691
692 AddEvent("START_TEMP_CONTROL", kStateConnected)
693 (bind(&StateMachineFeedback::StartTempCtrl, this))
694 ("Start the temperature control loop");
695
696 // kStateTempCtrlIdle, kStateFeedbackCtrlIdle, kStateTempCtrlRunning, kStateFeedbackCtrlRunning
697 AddEvent("STOP")
698 (bind(&StateMachineFeedback::StopFeedback, this))
699 ("Stop any control loop");
700
701 AddEvent("ENABLE_OUTPUT", "B:1")//, kStateIdle)
702 (bind(&StateMachineFeedback::EnableOutput, this, placeholders::_1))
703 ("Enable sending of correction values caluclated by the control loop to the biasctrl");
704
705 AddEvent("STORE_REFERENCE")//, kStateIdle)
706 (bind(&StateMachineFeedback::StoreReference, this))
707 ("Store the last (averaged) value as new reference (for debug purpose only)");
708
709 AddEvent("SET_REFERENCE", "F:1")//, kStateIdle)
710 (bind(&StateMachineFeedback::SetReference, this, placeholders::_1))
711 ("Set a new global reference value (for debug purpose only)");
712
713 AddEvent("SET_Ki", "D:1")//, kStateIdle)
714 (bind(&StateMachineFeedback::SetConstant, this, placeholders::_1, 0))
715 ("Set integral constant Ki");
716
717 AddEvent("SET_Kp", "D:1")//, kStateIdle)
718 (bind(&StateMachineFeedback::SetConstant, this, placeholders::_1, 1))
719 ("Set proportional constant Kp");
720
721 AddEvent("SET_Kd", "D:1")//, kStateIdle)
722 (bind(&StateMachineFeedback::SetConstant, this, placeholders::_1, 2))
723 ("Set derivative constant Kd");
724
725 AddEvent("SET_T", "D:1")//, kStateIdle)
726 (bind(&StateMachineFeedback::SetConstant, this, placeholders::_1, 3))
727 ("Set time-constant. (-1 to use the cycle time, i.e. the time for the last average cycle, instead)");
728
729 // Verbosity commands
730// AddEvent("SET_VERBOSE", "B:1")
731// (bind(&StateMachineMCP::SetVerbosity, this, placeholders::_1))
732// ("set verbosity state"
733// "|verbosity[bool]:disable or enable verbosity for received data (yes/no), except dynamic data");
734
735 AddEvent("PRINT")
736 (bind(&StateMachineFeedback::Print, this))
737 ("");
738 }
739
740 int EvalOptions(Configuration &conf)
741 {
742 if (!fMap.Read(conf.Get<string>("pixel-map-file")))
743 {
744 Error("Reading mapping table from "+conf.Get<string>("pixel-map-file")+" failed.");
745 return 1;
746 }
747
748 // -110 / -110 (-23 DAC / -0.51V)
749 // Reference voltage: -238 / -203
750 // -360 / -343 ( 23 DAC / 0.51V)
751
752 // 0.005 A/V
753 // 220 Amplitude / 1V
754
755 // Gain = 1V / 200 = 0.005
756
757 fGain = 5; // (BIAS)V / (DRS)V ( 1V / 0.22V )
758
759 fKp = 0;
760 fKd = 0;
761 fKi = 0.12;
762 fT = 1;
763
764 ostringstream msg;
765 msg << "Control loop parameters: ";
766 msg << "Kp=" << fKp << ", Kd=" << fKd << ", Ki=" << fKi << ", ";
767 if (fT>0)
768 msg << fT;
769 else
770 msg << "<auto>";
771 msg << ", Gain(BIAS/DRS)=" << fGain << "V/V";
772
773 Message(msg);
774
775 return -1;
776 }
777};
778
779// ------------------------------------------------------------------------
780
781#include "Main.h"
782
783template<class T>
784int RunShell(Configuration &conf)
785{
786 return Main::execute<T, StateMachineFeedback>(conf);
787}
788
789void SetupConfiguration(Configuration &conf)
790{
791 po::options_description control("Feedback options");
792 control.add_options()
793 ("pixel-map-file", var<string>("FACTmapV5a.txt"), "Pixel mapping file. Used here to get the default reference voltage.")
794 ;
795
796 conf.AddOptions(control);
797}
798
799/*
800 Extract usage clause(s) [if any] for SYNOPSIS.
801 Translators: "Usage" and "or" here are patterns (regular expressions) which
802 are used to match the usage synopsis in program output. An example from cp
803 (GNU coreutils) which contains both strings:
804 Usage: cp [OPTION]... [-T] SOURCE DEST
805 or: cp [OPTION]... SOURCE... DIRECTORY
806 or: cp [OPTION]... -t DIRECTORY SOURCE...
807 */
808void PrintUsage()
809{
810 cout <<
811 "The feedback control the BIAS voltages based on the calibration signal.\n"
812 "\n"
813 "The default is that the program is started without user intercation. "
814 "All actions are supposed to arrive as DimCommands. Using the -c "
815 "option, a local shell can be initialized. With h or help a short "
816 "help message about the usuage can be brought to the screen.\n"
817 "\n"
818 "Usage: feedback [-c type] [OPTIONS]\n"
819 " or: feedback [OPTIONS]\n";
820 cout << endl;
821}
822
823void PrintHelp()
824{
825 Main::PrintHelp<StateMachineFeedback>();
826
827 /* Additional help text which is printed after the configuration
828 options goes here */
829
830 /*
831 cout << "bla bla bla" << endl << endl;
832 cout << endl;
833 cout << "Environment:" << endl;
834 cout << "environment" << endl;
835 cout << endl;
836 cout << "Examples:" << endl;
837 cout << "test exam" << endl;
838 cout << endl;
839 cout << "Files:" << endl;
840 cout << "files" << endl;
841 cout << endl;
842 */
843}
844
845int main(int argc, const char* argv[])
846{
847 Configuration conf(argv[0]);
848 conf.SetPrintUsage(PrintUsage);
849 Main::SetupConfiguration(conf);
850 SetupConfiguration(conf);
851
852 if (!conf.DoParse(argc, argv, PrintHelp))
853 return -1;
854
855 //try
856 {
857 // No console access at all
858 if (!conf.Has("console"))
859 {
860// if (conf.Get<bool>("no-dim"))
861// return RunShell<LocalStream, StateMachine, ConnectionFSC>(conf);
862// else
863 return RunShell<LocalStream>(conf);
864 }
865 // Cosole access w/ and w/o Dim
866/* if (conf.Get<bool>("no-dim"))
867 {
868 if (conf.Get<int>("console")==0)
869 return RunShell<LocalShell, StateMachine, ConnectionFSC>(conf);
870 else
871 return RunShell<LocalConsole, StateMachine, ConnectionFSC>(conf);
872 }
873 else
874*/ {
875 if (conf.Get<int>("console")==0)
876 return RunShell<LocalShell>(conf);
877 else
878 return RunShell<LocalConsole>(conf);
879 }
880 }
881 /*catch (std::exception& e)
882 {
883 cerr << "Exception: " << e.what() << endl;
884 return -1;
885 }*/
886
887 return 0;
888}
Note: See TracBrowser for help on using the repository browser.