VEXPController.cpp 10.4 KB
Newer Older
legoc's avatar
legoc committed
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
/*
 * Nomad Instrument Control Software
 *
 * Copyright 2011 Institut Laue-Langevin
 *
 * Licensed under the EUPL, Version 1.1 only (the "License");
 * You may not use this work except in compliance with the Licence.
 * You may obtain a copy of the Licence at:
 *
 * http://joinup.ec.europa.eu/software/page/eupl
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the Licence is distributed on an "AS IS" basis,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the Licence for the specific language governing permissions and
 * limitations under the Licence.
 */

#include "VEXPController.h"
#include "controllers/common/family/Families.h"
ics's avatar
ics committed
21
22
23
24
25
#include "contrib/rapidjson/document.h"
#include "contrib/rapidjson/reader.h"
#include "contrib/rapidjson/writer.h"
#include "contrib/rapidjson/stringbuffer.h"
#include "contrib/rapidjson/prettywriter.h"
legoc's avatar
legoc committed
26

legoc's avatar
legoc committed
27
using namespace boost;
ics's avatar
ics committed
28
using namespace std;
legoc's avatar
legoc committed
29

legoc's avatar
legoc committed
30
31
32
33
34
namespace vexp {

const string VEXPController::TYPE = "vexp_controller";

VEXPController::VEXPController(const string& name) :
35
	ExperimentController(name) {
36

legoc's avatar
legoc committed
37
38
	setFamily(family::HIDDEN);

legoc's avatar
legoc committed
39
40
41
42
43
44
45
46
47
48
49
50
	as.init(this, NOSAVE, "as");
	bs.init(this, NOSAVE, "bs");
	cs.init(this, NOSAVE, "cs");
	aa.init(this, NOSAVE, "aa");
	bb.init(this, NOSAVE, "bb");
	cc.init(this, NOSAVE, "cc");
	ax.init(this, NOSAVE, "ax");
	ay.init(this, NOSAVE, "ay");
	az.init(this, NOSAVE, "az");
	bx.init(this, NOSAVE, "bx");
	by.init(this, NOSAVE, "by");
	bz.init(this, NOSAVE, "bz");
legoc's avatar
legoc committed
51
52
53
	u.init(this, NOSAVE, "Umatrix");
	b.init(this, NOSAVE, "Bmatrix");

legoc's avatar
legoc committed
54
55
56
57
58
	qh.init(this, NOSAVE, "qh");
	qk.init(this, NOSAVE, "qk");
	ql.init(this, NOSAVE, "ql");
	en.init(this, NOSAVE, "en");
	qm.init(this, NOSAVE, "qm");
59
	fx.init(this, NOSAVE, "fx");
legoc's avatar
legoc committed
60
61
62
63
64
65
66

	ki.init(this, NOSAVE, "ki");
	kf.init(this, NOSAVE, "kf");

	a1.init(this, NOSAVE, "a1");
	a2.init(this, NOSAVE, "a2");
	a3.init(this, NOSAVE, "a3");
yannick legoc's avatar
yannick legoc committed
67
	a3p.init(this, NOSAVE, "a3p");
legoc's avatar
legoc committed
68
69
70
71
	a4.init(this, NOSAVE, "a4");
	a5.init(this, NOSAVE, "a5");
	a6.init(this, NOSAVE, "a6");

ics's avatar
ics committed
72
73
74
75
76
	calcvalues.init(this, NOSAVE, "calcvalues");

	calca1.init(this, NOSAVE, "calca1");
	calca2.init(this, NOSAVE, "calca2");
	calca3.init(this, NOSAVE, "calca3");
yannick legoc's avatar
yannick legoc committed
77
	calca3p.init(this, NOSAVE, "calca3p");
ics's avatar
ics committed
78
79
80
81
	calca4.init(this, NOSAVE, "calca4");
	calca5.init(this, NOSAVE, "calca5");
	calca6.init(this, NOSAVE, "calca6");

82
	calculationStatus.init(this, NOSAVE, "calculation_status");
83
84
	calculationError.init(this, NOSAVE, "calculation_error");

legoc's avatar
legoc committed
85
	errorMessage.init(this, NOSAVE, "error_message");
86
	moveModel.init(this, SAVE, "move_model");
legoc's avatar
legoc committed
87
88
89
90
91
92

	tasSettings.init(this, "tas_settings");
	sample.init(this, "sample");
	scattering.init(this, "scattering");
	incidentBeam.init(this, "incident_beam");
	scatteredBeam.init(this, "scattered_beam");
legoc's avatar
legoc committed
93
94
95
96

	a1Controller.init(this, "A1");
	a2Controller.init(this, "A2");
	a3Controller.init(this, "A3");
yannick legoc's avatar
yannick legoc committed
97
	a3pController.init(this, "A3P");
legoc's avatar
legoc committed
98
99
100
101
102
103
	a4Controller.init(this, "A4");
	a5Controller.init(this, "A5");
	a6Controller.init(this, "A6");
}

VEXPController::VEXPController(const VEXPController& controller) :
104
	ExperimentController(controller) {
legoc's avatar
legoc committed
105
106
107
}

VEXPController::~VEXPController() {
108
}
legoc's avatar
legoc committed
109
110
111
112

void VEXPController::updateUMatrix() {
	u.update(sample->uRef());
	u.setSize(sample->uRef.getSize());
113
	u.sendEvent();
legoc's avatar
legoc committed
114
115
116
117
118
}

void VEXPController::updateBMatrix() {
	b.update(tasSettings->b());
	b.setSize(tasSettings->b.getSize());
119
	b.sendEvent();
legoc's avatar
legoc committed
120
121
}

ics's avatar
ics committed
122
void VEXPController::refreshCalcParameters(const std::string& value) {
123

124
	//cout << "refreshCalcParameters " << value << endl;
125

ics's avatar
ics committed
126
127
128
	// Parse the values.
	rapidjson::Document document;
	document.Parse(value.c_str());
129

ics's avatar
ics committed
130
131
132
133
134
	rapidjson::Value& ki = document["ki"];
	rapidjson::Value& kf = document["kf"];
	rapidjson::Value& qh = document["qh"];
	rapidjson::Value& qk = document["qk"];
	rapidjson::Value& ql = document["ql"];
135
	rapidjson::Value& fx = document["fx"];
136

ics's avatar
ics committed
137
	// Calculate the angles and the status.
138
	calculate(ki.GetDouble(), kf.GetDouble(), qh.GetDouble(), qk.GetDouble(), ql.GetDouble(), fx.GetInt());
139
140
}

141
double toDouble(double value) {
ics's avatar
ics committed
142

143
144
145
	if (isinf(value)) {
		return numeric_limits<double>::max();
	}
ics's avatar
ics committed
146

147
148
149
	if (isnan(value)) {
		return 0.0;
	}
legoc's avatar
legoc committed
150

151
152
	return value;
}
ics's avatar
ics committed
153

154
void VEXPController::refreshFloat64Property(SimpleProperty<float64>& property, float64 value) {
legoc's avatar
legoc committed
155
156
157

	// Update the value.
	property = value;
legoc's avatar
legoc committed
158
159
}

160
161
162
163
164
165
166
167
void VEXPController::refreshFloat64PropertyToMoveModel(SimpleProperty<float64>& property, float64 value) {

	// Update the value only in case moveModel is true.
	if (moveModel()) {
		property = value;
	}
}

ics's avatar
ics committed
168
void VEXPController::updateProperties() {
legoc's avatar
legoc committed
169

legoc's avatar
legoc committed
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
	// Copy the values.
	as.update(tasSettings->as());
	bs.update(tasSettings->bs());
	cs.update(tasSettings->cs());
	aa.update(tasSettings->aa());
	bb.update(tasSettings->bb());
	cc.update(tasSettings->cc());
	ax.update(tasSettings->ax());
	ay.update(tasSettings->ay());
	az.update(tasSettings->az());
	bx.update(tasSettings->bx());
	by.update(tasSettings->by());
	bz.update(tasSettings->bz());

	updateUMatrix();
	updateBMatrix();

ics's avatar
ics committed
187
188
189
190
191
	qh.update(scattering->qh());
	qk.update(scattering->qk());
	ql.update(scattering->ql());
	en.update(scattering->en());
	qm.update(scattering->qm());
192
	fx.update(scattering->fx());
ics's avatar
ics committed
193
194
195
196
197
198
199

	ki.update(incidentBeam->ki());
	kf.update(scatteredBeam->kf());

	a1.update(a1Controller->position());
	a2.update(a2Controller->position());
	a3.update(a3Controller->position());
yannick legoc's avatar
yannick legoc committed
200
	a3p.update(a3pController->position());
ics's avatar
ics committed
201
202
203
204
205
206
	a4.update(a4Controller->position());
	a5.update(a5Controller->position());
	a6.update(a6Controller->position());
}

void VEXPController::postConfiguration() {
207
208
209
210
211
212
213
214
215
216
217
218
219
220

	// Register the property updaters.
	registerPropertyCopierByUpdate(tasSettings->as, as);
	registerPropertyCopierByUpdate(tasSettings->bs, bs);
	registerPropertyCopierByUpdate(tasSettings->cs, cs);
	registerPropertyCopierByUpdate(tasSettings->aa, aa);
	registerPropertyCopierByUpdate(tasSettings->bb, bb);
	registerPropertyCopierByUpdate(tasSettings->cc, cc);
	registerPropertyCopierByUpdate(tasSettings->ax, ax);
	registerPropertyCopierByUpdate(tasSettings->ay, ay);
	registerPropertyCopierByUpdate(tasSettings->az, az);
	registerPropertyCopierByUpdate(tasSettings->bx, bx);
	registerPropertyCopierByUpdate(tasSettings->by, by);
	registerPropertyCopierByUpdate(tasSettings->bz, bz);
legoc's avatar
legoc committed
221
222
223
224

	registerUpdater(sample->uRef, &VEXPController::updateUMatrix, this);
	registerUpdater(sample->b, &VEXPController::updateBMatrix, this);

ics's avatar
ics committed
225
226
227
228
229
	registerPropertyCopierByUpdate(scattering->qh, qh);
	registerPropertyCopierByUpdate(scattering->qk, qk);
	registerPropertyCopierByUpdate(scattering->ql, ql);
	registerPropertyCopierByUpdate(scattering->en, en);
	registerPropertyCopierByUpdate(scattering->qm, qm);
230
	registerPropertyCopierByUpdate(scattering->fx, fx);
ics's avatar
ics committed
231
232
233
234
235
236
237

	registerPropertyCopierByUpdate(incidentBeam->ki, ki);
	registerPropertyCopierByUpdate(scatteredBeam->kf, kf);

	registerPropertyCopierByUpdate(a1Controller->position, a1);
	registerPropertyCopierByUpdate(a2Controller->position, a2);
	registerPropertyCopierByUpdate(a3Controller->position, a3);
yannick legoc's avatar
yannick legoc committed
238
	registerPropertyCopierByUpdate(a3pController->position, a3p);
ics's avatar
ics committed
239
240
241
242
243
244
245
246
247
	registerPropertyCopierByUpdate(a4Controller->position, a4);
	registerPropertyCopierByUpdate(a5Controller->position, a5);
	registerPropertyCopierByUpdate(a6Controller->position, a6);


	// To calculate the angles.
	registerRefresher(calcvalues, &VEXPController::refreshCalcParameters, this);

	// To move the model.
248
249
250
	registerRefresher(calca1, &VEXPController::refreshFloat64PropertyToMoveModel, this, a1Controller->position);
	registerRefresher(calca2, &VEXPController::refreshFloat64PropertyToMoveModel, this, a2Controller->position);
	registerRefresher(calca3, &VEXPController::refreshFloat64PropertyToMoveModel, this, a3Controller->position);
yannick legoc's avatar
yannick legoc committed
251
	registerRefresher(calca3p, &VEXPController::refreshFloat64PropertyToMoveModel, this, a3pController->position);
252
253
254
	registerRefresher(calca4, &VEXPController::refreshFloat64PropertyToMoveModel, this, a4Controller->position);
	registerRefresher(calca5, &VEXPController::refreshFloat64PropertyToMoveModel, this, a5Controller->position);
	registerRefresher(calca6, &VEXPController::refreshFloat64PropertyToMoveModel, this, a6Controller->position);
ics's avatar
ics committed
255
256
257
258

	updateProperties();
}

259
void VEXPController::calculate(float64 ki, float64 kf, float64 qh, float64 qk, float64 ql, int32 fx) {
ics's avatar
ics committed
260
261
262

	// Reset status.
	calculationStatus.setIdle();
263
	calculationError = 0;
ics's avatar
ics committed
264

ics's avatar
ics committed
265
266
267
268
269
270
271
272
273
274
275
276
277
	try {
		// Ki.
		incidentBeam->calcki = ki;

		// calca1, calca2, calcStatus are calculated.
		incidentBeam->calculate(tas::Beam::K_MODE);

		calca1 = toDouble(incidentBeam->calca1());
		calca2 = toDouble(incidentBeam->calca2());

		// Manage the status.
		if (incidentBeam->calcStatus.isError()) {
			calculationStatus.setError();
278
			calculationError = incidentBeam->calcError();
ics's avatar
ics committed
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
		}
		else if (incidentBeam->calcStatus.isWarning()) {
			calculationStatus.setWarning();
		}

		//cout << "Ki -> status " << incidentBeam->calcStatus() << endl;

		// Kf.
		scatteredBeam->calckf = kf;

		// calca1, calca2, calcStatus are calculated.
		scatteredBeam->calculate(tas::Beam::K_MODE);

		calca5 = toDouble(scatteredBeam->calca5());
		calca6 = toDouble(scatteredBeam->calca6());

		// Manage the status.
		if (scatteredBeam->calcStatus.isError()) {
			calculationStatus.setError();
298
			calculationError = scatteredBeam->calcError();
ics's avatar
ics committed
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
		}
		else if (scatteredBeam->calcStatus.isWarning() && !calculationStatus.isError()) {
			calculationStatus.setWarning();
		}

		//cout << "Kf -> status " << scatteredBeam->calcStatus() << endl;

		// Q.
		scattering->calcqh = qh;
		scattering->calcqk = qk;
		scattering->calcql = ql;
		scattering->calcen = 2.072 * (ki * ki - kf * kf);
		scattering->calcki = ki;
		scattering->calckf = kf;

		// Calculate by fixing Ki.
315
		scattering->calculate(tas::Beam::K_MODE, fx);
ics's avatar
ics committed
316
317
318
319
320

		calca3 = toDouble(scattering->calca3());
		calca3p = toDouble(scattering->calca3p());
		calca4 = toDouble(scattering->calca4());

321
322
323
324
325
326
327
//		cout << "calc A1 " << calca1() << endl;
//		cout << "calc A2 " << calca2() << endl;
//		cout << "calc A3 " << calca3() << endl;
//		cout << "calc A3P " << calca3p() << endl;
//		cout << "calc A4 " << calca4() << endl;
//		cout << "calc A5 " << calca5() << endl;
//		cout << "calc A6 " << calca6() << endl << endl;
ics's avatar
ics committed
328
329
330
331
332


		// Manage the status.
		if (scattering->calcStatus.isError()) {
			calculationStatus.setError();
333
			calculationError = scattering->calcError();
ics's avatar
ics committed
334
335
336
337
338
		}
		else if (scattering->calcStatus.isWarning() && !calculationStatus.isError()) {
			calculationStatus.setWarning();
			cerr << "Warning: Calculated Kf are different" << endl;
		}
ics's avatar
ics committed
339
	}
ics's avatar
ics committed
340
	catch (...) {
ics's avatar
ics committed
341
		calculationStatus.setError();
342
		calculationError = 0;
ics's avatar
ics committed
343
344
	}

345
346
347
//	if (calculationError() != 0) {
//		cout << "VEXP error " << calculationError() << endl;
//	}
legoc's avatar
legoc committed
348
349
350
}

}