Commit c16f6991 authored by Cristina Cocho's avatar Cristina Cocho
Browse files

Merge branch 'V3.2_191' of...

Merge branch 'V3.2_191' of https://code.ill.fr/instrument-control/nomad-special-modules into V3.2_191
parents b3380597 a9ba6d5e
......@@ -153,7 +153,18 @@ void Nomad3DController::updateActualPosition(int32 i) {
writer.Key(data.name.c_str());
// Do not apply the offset.
writer.Double(data.controller->position() * data.coef);
float64 position = data.controller->position();
// Get the middle position if the position is outside the limits.
// This can be due to a unplugged encoder.
float64 minPosition = data.controller->minPosition();
float64 maxPosition = data.controller->maxPosition();
if (position < minPosition || position > maxPosition) {
position = 0.5 * (minPosition + maxPosition);
}
writer.Double(position * data.coef);
}
// Write the virtual axis controllers.
......
......@@ -62,7 +62,7 @@ CAENCfd2Controller::CAENCfd2Controller(const string& name) : CAENAdcController(n
cfdSignalZero.init(this, NOSAVE, "signal_zero");
dynamicRange.init(this, NOSAVE, "dynamic_range");
cfdTrap.init(this, SAVE, "cfd_trap");
adcTemperature.init(this, NOSAVE, "adc_temperature");
adcTemperature.init(this, NOSAVE, "adc_temperature", "ADCTemp");
m_dgtzDriver.init(this, "cfd_driver");
......
......@@ -62,7 +62,7 @@ CAENCfdController::CAENCfdController(const string& name) : CAENAdcController(nam
cfdSignalZero.init(this, NOSAVE, "signal_zero");
dynamicRange.init(this, NOSAVE, "dynamic_range");
cfdTrap.init(this, SAVE, "cfd_trap");
adcTemperature.init(this, NOSAVE, "adc_temperature");
adcTemperature.init(this, NOSAVE, "adc_temperature", "ADCTemp");
m_dgtzDriver.init(this, "cfd_driver");
......
......@@ -23,6 +23,7 @@
#include <common/base/FileUtilities.h>
#include "controllers/common/family/Families.h"
#include "InstrumentManager/InstrumentManager.h"
#include "controllers/common/acquisition/Count.h"
#include "controllers/common/acquisition/ExperimentData.h"
#include <boost/filesystem/operations.hpp>
#include <thread>
......@@ -45,9 +46,11 @@ const std::string RemoteWindeta::INDEPENDENT_PREFIX = "windeta-";
const std::string RemoteWindeta::INDEPENDENT_VALUE = "independent";
const std::string RemoteWindeta::NUMOR_VALUE = "numor";
const std::string RemoteWindeta::NUMOR_1_VALUE = "numor+1";
const std::string RemoteWindeta::COUNT_SYNC_VALUE = "sync";
RemoteWindeta::RemoteWindeta(const std::string& name) :
ExperimentController(name), controller::Stoppable(this), controller::Init(this), controller::Raz(this), Test(this), m_independentDataFileId(0), m_stopped(false) {
ExperimentController(name), controller::Stoppable(this), controller::Init(this), controller::Raz(this), Test(this),
m_independentDataFileId(0), m_countNumor(0), m_stopped(false) {
setFamily(family::ACQUISITION, family::POLARIZATIONS);
......@@ -63,17 +66,19 @@ RemoteWindeta::RemoteWindeta(const std::string& name) :
dataFilenameFormatSize.init(this, NOSAVE, "data_filename_format_size");
dataFilenameFormatValues.init(this, NOSAVE, "data_filename_format_values");
dataFilenameFormatLabels.init(this, NOSAVE, "data_filename_format_labels");
dataFilenameFormatSize = 3;
dataFilenameFormatSize = 4;
dataFilenameFormatValues.resize(dataFilenameFormatSize());
dataFilenameFormatValues.set(0, NUMOR_VALUE);
dataFilenameFormatValues.set(1, NUMOR_1_VALUE);
dataFilenameFormatValues.set(2, INDEPENDENT_VALUE);
dataFilenameFormatValues.set(3, COUNT_SYNC_VALUE);
dataFilenameFormatLabels.resize(dataFilenameFormatSize());
dataFilenameFormatLabels.set(0, "Numor");
dataFilenameFormatLabels.set(1, "Numor+1");
dataFilenameFormatLabels.set(2, "Independent");
dataFilenameFormatLabels.set(3, "Sync");
dataFilenameFormat.setEnumeratedValues(dataFilenameFormatValues);
dataFilenameFormat.setEnumeratedLabels(dataFilenameFormatLabels);
......@@ -82,13 +87,15 @@ RemoteWindeta::RemoteWindeta(const std::string& name) :
presetsSize.init(this, NOSAVE, "presets_size");
presets.init(this, NOSAVE, "presets");
m_CountSpy.init(this, "acquisition_spy");
m_driver.init(this, "driver");
initIndependentDataFileId();
}
RemoteWindeta::RemoteWindeta(const RemoteWindeta& controller) :
ExperimentController(controller), controller::Stoppable(this), controller::Init(this), controller::Raz(this), Test(this), m_independentDataFileId(0), m_stopped(false) {
ExperimentController(controller), controller::Stoppable(this), controller::Init(this), controller::Raz(this), Test(this),
m_independentDataFileId(0), m_countNumor(0), m_stopped(false) {
}
RemoteWindeta::~RemoteWindeta() {
......@@ -97,6 +104,8 @@ RemoteWindeta::~RemoteWindeta() {
void RemoteWindeta::postConfiguration() {
registerUpdater(m_CountSpy->statusMessage, &RemoteWindeta::updateStatusMessage, this);
if (m_server.get() == nullptr) {
// Create a new server if it is not already created.
// In case of a simulated server, avoid the real remote endpoint.
......@@ -117,7 +126,6 @@ void RemoteWindeta::postConfiguration() {
void RemoteWindeta::setEnabled(bool all, bool postconf) {
ExperimentController::setEnabled(all);
}
void RemoteWindeta::setDisabled(bool all) {
......@@ -176,7 +184,7 @@ bool RemoteWindeta::initApplication() {
m_subscriber = application::Subscriber::create(*m_windetaApplication, PUBLISHER_NAME);
// Start the subscriber loop
m_subscriberThread.reset(new boost::thread(boost::bind(&RemoteWindeta::subscriberLoop, this)));
m_subscriberThread.reset(new std::thread(std::bind(&RemoteWindeta::subscriberLoop, this)));
// Application initialized.
initialized = true;
......@@ -207,8 +215,6 @@ void RemoteWindeta::initPresets() {
// Send the message.
m_requester->sendTwoBinaryParts(requestType.SerializeAsString(), "");
cout << getName() << " sent request " << static_cast<int>(requestType.type()) << endl;
// Wait for the response synchronously.
// Note that responses can be processed asynchronously if the server is able to.
string data;
......@@ -216,8 +222,6 @@ void RemoteWindeta::initPresets() {
windeta::Response response;
response.ParseFromString(data);
cout << "received response " << response.errorcode() << endl;
}
void RemoteWindeta::init() {
......@@ -247,12 +251,21 @@ void RemoteWindeta::reset() {
}
}
void RemoteWindeta::updateStatusMessage() {
if (m_CountSpy->statusMessage() == acquisition::Count::COUNTING_MESSAGE) {
m_countNumor = m_CountSpy->numor();
}
}
void RemoteWindeta::start() {
if (!initApplication()) {
return;
}
commandStatus.setIdle();
// Check initial status.
if (commandStatus.isRunning()) {
log(Level::s_Error) << name << "cannot start because it is already running" << endlog;
......@@ -261,6 +274,32 @@ void RemoteWindeta::start() {
log(Level::s_Debug) << name << cursor << "preset " << preset() << endlog;
int timeout = startTimeout();
int i = 0;
m_stopped = false;
m_countNumor = 0;
// Wait for the count to have changed the numor so that we can use it in case of sync.
if (dataFilenameFormat() == COUNT_SYNC_VALUE) {
// Poll in milliseconds.
while (m_countNumor == 0 && i < timeout * 100 && !m_stopped) {
std::this_thread::sleep_for(std::chrono::milliseconds(10));
i++;
}
if (m_stopped) {
log(Level::s_Info) << name << "preset " << preset() << " stopped" << endlog;
return;
}
if (m_countNumor == 0) {
log(Level::s_Error) << name << "preset " << preset() << " start timeout" << endlog;
return;
}
}
// Serialize the request.
windeta::Request requestType;
requestType.set_type(windeta::Request::START_MEASURE);
......@@ -271,8 +310,6 @@ void RemoteWindeta::start() {
// Send the message.
m_requester->sendTwoBinaryParts(requestType.SerializeAsString(), requestMessage.SerializeAsString());
cout << getName() << " sent request " << static_cast<int>(requestType.type()) << endl;
// Wait for the response synchronously.
// Note that responses can be processed asynchronously if the server is able to.
string data;
......@@ -281,22 +318,17 @@ void RemoteWindeta::start() {
windeta::Response response;
response.ParseFromString(data);
cout << "received response " << response.errorcode() << endl;
m_stopped = false;
// Set the data filename.
setDataFilename();
// The status must pass to running within a timeout.
int i = 0;
int timeout = startTimeout();
while (!commandStatus.isRunning() && i < timeout && !m_stopped) {
// The status must become running within a timeout.
i = 0;
while (!commandStatus.isRunning() && !commandStatus.isError() && i < timeout && !m_stopped) {
std::this_thread::sleep_for(std::chrono::seconds(1));
i++;
}
if (!commandStatus.isRunning()) {
if (!commandStatus.isRunning() && !commandStatus.isError() && !m_stopped) {
log(Level::s_Error) << name << "preset " << preset() << " to " << m_dataFilename << " start timeout" << endlog;
return;
}
......@@ -306,10 +338,11 @@ void RemoteWindeta::start() {
std::this_thread::sleep_for(std::chrono::seconds(1));
}
// Check the execution.
if (m_stopped) {
log(Level::s_Info) << name << "preset " << preset() << " to " << m_dataFilename << " stopped" << endlog;
} else if (commandStatus.isError()) {
}
else if (commandStatus.isError()) {
log(Level::s_Error) << name << "preset " << preset() << " to " << m_dataFilename << " on error" << endlog;
}
else {
......@@ -376,8 +409,6 @@ void RemoteWindeta::stopApplication() {
// Send the message.
m_requester->sendTwoBinaryParts(requestType.SerializeAsString(), "");
cout << getName() << " sent request " << static_cast<int>(requestType.type()) << endl;
// Wait for the response synchronously.
// Note that responses can be processed asynchronously if the server is able to.
string data;
......@@ -386,8 +417,6 @@ void RemoteWindeta::stopApplication() {
windeta::Response response;
response.ParseFromString(data);
cout << "received response " << response.errorcode() << endl;
// Stop the remote application.
m_windetaApplication->stop();
......@@ -443,12 +472,17 @@ void RemoteWindeta::setDataFilename() {
m_independentDataFileId++;
m_dataFilename = ServerProperties::getInstance()->getNomadDataPath() + INDEPENDENT_PREFIX + lexical_cast<string>(m_independentDataFileId) + ".diel";
cout << "Independent data filename " << m_dataFilename << endl;
}
else {
// Set the filename related to numor.
int numor = 0;
if (dataFilenameFormat() == NUMOR_VALUE || dataFilenameFormat() == NUMOR_1_VALUE) {
numor = experimentData->numor();
}
else {
numor = m_countNumor;
}
int numor = experimentData->numor();
if (dataFilenameFormat() == NUMOR_1_VALUE) {
numor++;
}
......@@ -476,8 +510,6 @@ void RemoteWindeta::setDataFilename() {
}
m_dataFilename = dataFilename;
cout << "Numor data filename " << m_dataFilename << endl;
}
}
......@@ -530,8 +562,6 @@ void RemoteWindeta::subscriberLoop() {
numberOfPoints = data.points();
saveData(data.data());
cout << "Data " << data.points() << " points" << endl;
}
else if (event.type() == windeta::Event::PRESETS) {
windeta::Presets messagePresets;
......
......@@ -21,7 +21,9 @@
#include <Controller.h>
#include <cameo/cameo.h>
#include "controllers/common/utilities/CountSpy.h"
#include "drivers/utilities/null/NullDriver.h"
#include <thread>
namespace dielectrics {
......@@ -89,6 +91,7 @@ private:
void stopApplication();
void subscriberLoop();
void updateStatusMessage();
void initPresets();
void initIndependentDataFileId();
void setDataFilename();
......@@ -102,16 +105,19 @@ private:
static const std::string INDEPENDENT_VALUE;
static const std::string NUMOR_VALUE;
static const std::string NUMOR_1_VALUE;
static const std::string COUNT_SYNC_VALUE;
std::unique_ptr<cameo::Server> m_server;
std::unique_ptr<cameo::application::Instance> m_windetaApplication;
std::unique_ptr<cameo::application::Requester> m_requester;
std::unique_ptr<cameo::application::Subscriber> m_subscriber;
std::unique_ptr<boost::thread> m_subscriberThread;
std::unique_ptr<std::thread> m_subscriberThread;
ControllerPtr<utilities::CountSpy> m_CountSpy;
DriverPtr<driver::NullDriver> m_driver;
int m_independentDataFileId;
int m_countNumor;
bool m_stopped;
std::string m_dataFilename;
};
......
......@@ -63,32 +63,21 @@ VEXPController::VEXPController(const string& name) :
a1.init(this, NOSAVE, "a1");
a2.init(this, NOSAVE, "a2");
a3.init(this, NOSAVE, "a3");
a3p.init(this, NOSAVE, "a3p");
a4.init(this, NOSAVE, "a4");
a5.init(this, NOSAVE, "a5");
a6.init(this, NOSAVE, "a6");
calcqh.init(this, NOSAVE, "calcqh");
calcqk.init(this, NOSAVE, "calcqk");
calcql.init(this, NOSAVE, "calcql");
calcen.init(this, NOSAVE, "calcen");
calcqm.init(this, NOSAVE, "calcqm");
calcki.init(this, NOSAVE, "calcki");
calckf.init(this, NOSAVE, "calckf");
calcvalues.init(this, NOSAVE, "calcvalues");
calca1.init(this, NOSAVE, "calca1");
calca2.init(this, NOSAVE, "calca2");
calca3.init(this, NOSAVE, "calca3");
calca3p.init(this, NOSAVE, "calca3p");
calca4.init(this, NOSAVE, "calca4");
calca5.init(this, NOSAVE, "calca5");
calca6.init(this, NOSAVE, "calca6");
calctrigger.init(this, NOSAVE, "calctrigger");
calculationStatus.init(this, NOSAVE, "calculation_status");
errorMessage.init(this, NOSAVE, "error_message");
moveModel.init(this, SAVE, "move_model");
......@@ -102,6 +91,7 @@ VEXPController::VEXPController(const string& name) :
a1Controller.init(this, "A1");
a2Controller.init(this, "A2");
a3Controller.init(this, "A3");
a3pController.init(this, "A3P");
a4Controller.init(this, "A4");
a5Controller.init(this, "A5");
a6Controller.init(this, "A6");
......@@ -157,12 +147,6 @@ double toDouble(double value) {
return value;
}
void VEXPController::refreshCalcTrigger(int32 value) {
//cout << "refreshCalcTrigger " << value << endl;
calculate(calcki(), calckf(), calcqh(), calcqk(), calcql());
}
void VEXPController::refreshFloat64Property(SimpleProperty<float64>& property, float64 value) {
// Update the value.
......@@ -208,6 +192,7 @@ void VEXPController::updateProperties() {
a1.update(a1Controller->position());
a2.update(a2Controller->position());
a3.update(a3Controller->position());
a3p.update(a3pController->position());
a4.update(a4Controller->position());
a5.update(a5Controller->position());
a6.update(a6Controller->position());
......@@ -244,19 +229,20 @@ void VEXPController::postConfiguration() {
registerPropertyCopierByUpdate(a1Controller->position, a1);
registerPropertyCopierByUpdate(a2Controller->position, a2);
registerPropertyCopierByUpdate(a3Controller->position, a3);
registerPropertyCopierByUpdate(a3pController->position, a3p);
registerPropertyCopierByUpdate(a4Controller->position, a4);
registerPropertyCopierByUpdate(a5Controller->position, a5);
registerPropertyCopierByUpdate(a6Controller->position, a6);
// To calculate the angles.
registerRefresher(calctrigger, &VEXPController::refreshCalcTrigger, this);
registerRefresher(calcvalues, &VEXPController::refreshCalcParameters, this);
// To move the model.
registerRefresher(calca1, &VEXPController::refreshFloat64PropertyToMoveModel, this, a1Controller->position);
registerRefresher(calca2, &VEXPController::refreshFloat64PropertyToMoveModel, this, a2Controller->position);
registerRefresher(calca3, &VEXPController::refreshFloat64PropertyToMoveModel, this, a3Controller->position);
registerRefresher(calca3p, &VEXPController::refreshFloat64PropertyToMoveModel, this, a3pController->position);
registerRefresher(calca4, &VEXPController::refreshFloat64PropertyToMoveModel, this, a4Controller->position);
registerRefresher(calca5, &VEXPController::refreshFloat64PropertyToMoveModel, this, a5Controller->position);
registerRefresher(calca6, &VEXPController::refreshFloat64PropertyToMoveModel, this, a6Controller->position);
......@@ -278,12 +264,13 @@ void VEXPController::calculate(float64 ki, float64 kf, float64 qh, float64 qk, f
calca1 = toDouble(incidentBeam->calca1());
calca2 = toDouble(incidentBeam->calca2());
cout << "calc A1 " << calca1() << endl;
cout << "calc A2 " << calca2() << endl;
cout << "calc A3 " << calca3() << endl;
cout << "calc A4 " << calca4() << endl;
cout << "calc A5 " << calca5() << endl;
cout << "calc A6 " << calca6() << endl << endl;
// 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;
// Manage the status.
if (incidentBeam->calcStatus.isError()) {
......@@ -326,6 +313,7 @@ void VEXPController::calculate(float64 ki, float64 kf, float64 qh, float64 qk, f
scattering->calculate(tas::Beam::K_MODE, 1);
calca3 = toDouble(scattering->calca3());
calca3p = toDouble(scattering->calca3p());
calca4 = toDouble(scattering->calca4());
// cout << "calc A1 " << calca1() << endl;
......
......@@ -31,6 +31,18 @@
namespace vexp {
/**
* The VEXPController is the bridge between Nomad and the vEXP application.
* It groups the properties needed by vEXP:
* - Sample properties: as, bs, ... U, B matrices.
* - Scattering properties: qh, ... qm, ki, kf.
* - Angle properties: A1...A6.
* These properties are synchronized with the Nomad controllers.
*
* The vEXP application is reading these properties when it synchronizes with Nomad (startup and resync).
* When the vEXP application requests a calculation of the angles, it sends the property calcvalues.
* Then the calculation is triggered and calca1...calca6 are calculated by the other Nomad controllers.
*/
class VEXPController : public ExperimentController {
public:
......@@ -45,7 +57,6 @@ public:
void updateBMatrix();
void refreshCalcParameters(const std::string& value);
void refreshCalcTrigger(int32 value);
void refreshFloat64Property(SimpleProperty<float64>& property, float64 value);
void refreshFloat64PropertyToMoveModel(SimpleProperty<float64>& property, float64 value);
......@@ -84,32 +95,22 @@ public:
Property<float64> a1;
Property<float64> a2;
Property<float64> a3;
Property<float64> a3p;
Property<float64> a4;
Property<float64> a5;
Property<float64> a6;
// Calculated properties.
Property<float64> calcqh;
Property<float64> calcqk;
Property<float64> calcql;
Property<float64> calcen;
Property<float64> calcqm;
Property<float64> calcki;
Property<float64> calckf;
// JSON String property containing the calculated properties. Use it or the direct properties.
Property<std::string> calcvalues;
Property<float64> calca1;
Property<float64> calca2;
Property<float64> calca3;
Property<float64> calca3p;
Property<float64> calca4;
Property<float64> calca5;
Property<float64> calca6;
Property<int32> calctrigger;
StatusProperty calculationStatus;
Property<std::string> errorMessage;
Property<bool> moveModel;
......@@ -123,6 +124,7 @@ public:
ControllerPtr<axis::AxisController> a1Controller;
ControllerPtr<axis::AxisController> a2Controller;
ControllerPtr<axis::AxisController> a3Controller;
ControllerPtr<axis::AxisController> a3pController;
ControllerPtr<axis::AxisController> a4Controller;
ControllerPtr<axis::AxisController> a5Controller;
ControllerPtr<axis::AxisController> a6Controller;
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment