DynExp
Highly flexible laboratory automation for dynamically changing experiments.
Loading...
Searching...
No Matches
Trajectory1D.cpp
Go to the documentation of this file.
1// This file is part of DynExp.
2
3#include "stdafx.h"
4#include "moc_Trajectory1D.cpp"
5#include "Trajectory1D.h"
6
7namespace DynExpModule
8{
9 Trajectory1DWidget::Trajectory1DWidget(Trajectory1D& Owner, QModuleWidget* parent) : QModuleWidget(Owner, parent)
10 {
11 ui.setupUi(this);
12 }
13
18
20 {
22 RepeatCount = 1;
23 DwellTime = std::chrono::milliseconds(100);
24
26 Samples.clear();
27
30 Ready = false;
32 }
33
35 {
37 { "Trigger disabled (start immediately)", Trajectory1DData::TriggerModeType::Continuous },
38 { "Trigger only manually and stop after playback", Trajectory1DData::TriggerModeType::ManualOnce },
39 { "Trigger only manually each time a trigger event occurs", Trajectory1DData::TriggerModeType::Manual },
40 { "Trigger when the trajectory data stream changes", Trajectory1DData::TriggerModeType::OnStreamChanged }
41 };
42
43 return List;
44 }
45
47 {
48 try
49 {
50 auto ModuleData = DynExp::dynamic_ModuleData_cast<Trajectory1D>(Instance.ModuleDataGetter());
51
54
56 } // ModuleData and instruments' data unlocked here.
57 catch (const Util::TimeoutException& e)
58 {
59 if (NumFailedUpdateAttempts++ >= 3)
60 Instance.GetOwner().SetWarning(e);
61 }
62
64 }
65
70
71 std::unique_ptr<DynExp::QModuleWidget> Trajectory1D::MakeUIWidget()
72 {
73 auto Widget = std::make_unique<Trajectory1DWidget>(*this);
74
75 Connect(Widget->GetUI().BStart, &QPushButton::clicked, this, &Trajectory1D::OnStartClicked);
76 Connect(Widget->GetUI().BStop, &QPushButton::clicked, this, &Trajectory1D::OnStopClicked);
77 Connect(Widget->GetUI().BForce, &QPushButton::clicked, this, &Trajectory1D::OnTriggerClicked);
78
79 return Widget;
80 }
81
82 void Trajectory1D::UpdateUIChild(const ModuleBase::ModuleDataGetterType& ModuleDataGetter)
83 {
84 auto Widget = GetWidget<Trajectory1DWidget>();
85 auto ModuleData = DynExp::dynamic_ModuleData_cast<Trajectory1D>(ModuleDataGetter());
86
87 Widget->GetUI().LESampleCount->setText(QString::number(ModuleData->GetSamples().size()));
88
89 Widget->GetUI().LProgress->setVisible(ModuleData->IsReady() && ModuleData->GetSamples().size());
90 Widget->GetUI().PBProgress->setVisible(ModuleData->IsReady() && ModuleData->GetSamples().size());
91 Widget->GetUI().LRepetition->setVisible(ModuleData->IsReady() && ModuleData->GetSamples().size());
92 if (ModuleData->GetSamples().size())
93 Widget->GetUI().PBProgress->setValue(static_cast<int>((static_cast<double>(ModuleData->GetCurrentRepeatCount()) / ModuleData->GetRepeatCount() +
94 std::max(0.0, static_cast<double>(ModuleData->GetCurrentPlaybackPos()) - 1.0)
95 / ModuleData->GetRepeatCount() / ModuleData->GetSamples().size()) * 100.0));
96 Widget->GetUI().LRepetition->setText(QString("Repetition ") + QString::number(ModuleData->GetCurrentRepeatCount() + 1)
97 + " / " + QString::number(ModuleData->GetRepeatCount()));
98
99 Widget->GetUI().BStart->setEnabled(!ModuleData->IsReady());
100 Widget->GetUI().BStop->setEnabled(ModuleData->IsReady());
101 Widget->GetUI().BForce->setEnabled(ModuleData->IsReady());
102 }
103
105 {
106 auto TrajectoryDataInstrData = DynExp::dynamic_InstrumentData_cast<DynExpInstr::DataStreamInstrument>(ModuleData->GetTrajectoryDataInstr()->GetInstrumentData());
107 auto SampleStream = TrajectoryDataInstrData->GetSampleStream();
108
109 if (SampleStream->GetNumSamplesWritten() != ModuleData->GetLastWrittenSampleID())
110 {
111 if (SampleStream->GetNumSamplesWritten() < ModuleData->GetLastWrittenSampleID())
112 ModuleData->SetLastWrittenSampleID(0); // e.g. if SampleStream has been cleared.
113
114 SampleStream->SeekBeg(std::ios_base::in);
115 ModuleData->SetSamples(SampleStream->ReadBasicSamples(SampleStream->GetStreamSizeRead()));
116 ModuleData->SetLastWrittenSampleID(SampleStream->GetNumSamplesWritten());
117
118 if (ModuleData->GetSamples().empty())
119 return;
120
121 if (!SampleStream->IsBasicSampleTimeUsed())
122 for (size_t i = 0; i < ModuleData->GetSamples().size(); ++i)
123 ModuleData->GetSamples()[i].Time = static_cast<DynExpInstr::BasicSample::DataType>(ModuleData->GetDwellTime().count())
124 * i / decltype(ModuleData->GetDwellTime())::period::den;
125
126 switch (ModuleData->GetTriggerMode())
127 {
131 break;
133 ModuleData->SetCurrentPlaybackPos(0);
134 ModuleData->SetCurrentRepeatCount(0);
135 break;
136 default:
138 }
139 }
140 }
141
143 {
144 if (!ModuleData->IsReady() || !ModuleData->GetCurrentPlaybackPos())
145 return;
146
147 std::chrono::system_clock::duration TimeEllapsed;
148 if (ModuleData->GetCurrentPlaybackPos() == 1)
149 {
150 ModuleData->SetTrajectoryStartedTime(std::chrono::system_clock::now());
151 TimeEllapsed = std::chrono::milliseconds(0);
152 }
153 else
154 TimeEllapsed = std::chrono::system_clock::now() - ModuleData->GetTrajectoryStartedTime();
155
156 const auto& Samples = ModuleData->GetSamples();
157 for (size_t i = ModuleData->GetCurrentPlaybackPos() - 1; i < Samples.size(); ++i)
158 {
159 auto ThisSampleStart = std::chrono::milliseconds(Util::NumToT<std::chrono::milliseconds::rep>(Samples[i].Time * std::chrono::milliseconds::period::den));
160 auto NextSampleStart = i + 1 >= Samples.size() ? std::chrono::milliseconds(0)
161 : std::chrono::milliseconds(Util::NumToT<std::chrono::milliseconds::rep>(Samples[i + 1].Time * std::chrono::milliseconds::period::den));
162
163 // Move to sample i if time for next, but not for second-next sample has ellapsed or if time for next sample has ellapsed and end of sample list.
164 if ((ThisSampleStart <= TimeEllapsed && NextSampleStart > TimeEllapsed) ||
165 (ThisSampleStart <= TimeEllapsed && i + 1 == Samples.size()))
166 {
167 ModuleData->GetPositionerStage()->MoveAbsolute(Samples[i].Value);
168 ModuleData->SetCurrentPlaybackPos(i + 2);
169
170 break;
171 }
172 }
173
174 // End reached? If applicable, retrigger.
175 if (ModuleData->GetCurrentPlaybackPos() > ModuleData->GetSamples().size())
176 {
177 ModuleData->SetCurrentRepeatCount(ModuleData->GetCurrentRepeatCount() + 1);
178 if (ModuleData->GetCurrentRepeatCount() < ModuleData->GetRepeatCount())
179 ModuleData->SetCurrentPlaybackPos(1);
180 else
181 {
182 switch (ModuleData->GetTriggerMode())
183 {
186 break;
187 case Trajectory1DData::TriggerModeType::Manual: [[fallthrough]];
189 ModuleData->SetCurrentPlaybackPos(0);
190 ModuleData->SetCurrentRepeatCount(0);
191 break;
192 default:
193 ModuleData->SetReady(false); // Do not call Stop() to let the positioner complete its motion.
194 }
195 }
196 }
197 }
198
200 {
201 if (ModuleData->GetSamples().size())
202 {
203 ModuleData->SetReady(true);
204 ModuleData->SetCurrentPlaybackPos(0);
205 ModuleData->SetCurrentRepeatCount(0);
206
209 }
210 }
211
213 {
214 ModuleData->GetPositionerStage()->StopMotion();
215 ModuleData->SetReady(false);
216 }
217
219 {
220 if (ModuleData->IsReady() && ModuleData->GetSamples().size() &&
222 (!ModuleData->GetCurrentPlaybackPos() && !ModuleData->GetCurrentRepeatCount())))
223 {
224 ModuleData->SetCurrentPlaybackPos(1);
225 ModuleData->SetCurrentRepeatCount(0);
226 }
227 }
228
230 {
234
235 auto ModuleParams = DynExp::dynamic_Params_cast<Trajectory1D>(Instance->ParamsGetter());
236 auto ModuleData = DynExp::dynamic_ModuleData_cast<Trajectory1D>(Instance->ModuleDataGetter());
237
238 Instance->LockObject(ModuleParams->TrajectoryDataInstr, ModuleData->GetTrajectoryDataInstr());
239 Instance->LockObject(ModuleParams->PositionerStage, ModuleData->GetPositionerStage());
240 if (ModuleParams->Communicator.ContainsID())
241 Instance->LockObject(ModuleParams->Communicator, ModuleData->GetCommunicator());
242
243 ModuleData->SetTriggerMode(ModuleParams->TriggerMode);
244 ModuleData->SetRepeatCount(std::max(static_cast<size_t>(1), Util::NumToT<size_t>(ModuleParams->RepeatCount)));
245 ModuleData->SetDwellTime(std::chrono::milliseconds(Util::NumToT<std::chrono::milliseconds::rep>(std::max(1.0, ModuleParams->DwellTime.Get()))));
246
248 }
249
251 {
252 auto ModuleData = DynExp::dynamic_ModuleData_cast<Trajectory1D>(Instance->ModuleDataGetter());
253
255
256 Instance->UnlockObject(ModuleData->GetTrajectoryDataInstr());
257 Instance->UnlockObject(ModuleData->GetPositionerStage());
258 Instance->UnlockObject(ModuleData->GetCommunicator());
259
263 }
264
266 {
267 auto ModuleData = DynExp::dynamic_ModuleData_cast<Trajectory1D>(Instance->ModuleDataGetter());
268
270 }
271
273 {
274 auto ModuleData = DynExp::dynamic_ModuleData_cast<Trajectory1D>(Instance->ModuleDataGetter());
275
277 }
278
280 {
281 auto ModuleData = DynExp::dynamic_ModuleData_cast<Trajectory1D>(Instance->ModuleDataGetter());
282
284 }
285}
Implementation of a module to interpret samples stored in a data stream instrument as trajectories of...
size_t CurrentPlaybackPos
0 means waiting for trigger. Values > 0 mean running. They indicate the sample to be written next.
DynExpInstr::DataStreamBase::BasicSampleListType Samples
std::chrono::time_point< std::chrono::system_clock > TrajectoryStartedTime
void ResetImpl(dispatch_tag< QModuleDataBase >) override final
bool Ready
Running (not necessarily triggered yet) if true.
std::chrono::milliseconds DwellTime
static Util::TextValueListType< Trajectory1DData::TriggerModeType > TriggerModeTypeStrList()
Trajectory1DWidget(Trajectory1D &Owner, QModuleWidget *parent=nullptr)
void ResetImpl(dispatch_tag< QModuleBase >) override final
void UpdateStream(Util::SynchronizedPointer< ModuleDataType > &ModuleData)
std::unique_ptr< DynExp::QModuleWidget > MakeUIWidget() override final
Used by InitUI() as a factory function for the module's user interface widget. Create the widget here...
void Start(Util::SynchronizedPointer< ModuleDataType > &ModuleData) const
void OnTriggerClicked(DynExp::ModuleInstance *Instance, bool) const
void OnTrigger(DynExp::ModuleInstance *Instance) const
void Trigger(Util::SynchronizedPointer< ModuleDataType > &ModuleData) const
void OnInit(DynExp::ModuleInstance *Instance) const override final
This event is triggered right before the module thread starts. Override it to lock instruments this m...
void OnStartClicked(DynExp::ModuleInstance *Instance, bool) const
void Stop(Util::SynchronizedPointer< ModuleDataType > &ModuleData) const
void OnExit(DynExp::ModuleInstance *Instance) const override final
This event is triggered right before the module thread terminates (not due to an exception,...
void OnStopClicked(DynExp::ModuleInstance *Instance, bool) const
void OnStop(DynExp::ModuleInstance *Instance) const
Util::DynExpErrorCodes::DynExpErrorCodes ModuleMainLoop(DynExp::ModuleInstance &Instance) override final
Module main loop. The function is executed periodically by the module thread. Also refer to GetMainLo...
void OnStart(DynExp::ModuleInstance *Instance) const
void Move(Util::SynchronizedPointer< ModuleDataType > &ModuleData)
void UpdateUIChild(const ModuleBase::ModuleDataGetterType &ModuleDataGetter) override final
static void Register(const ModuleBase &Listener, CallableT EventFunc)
Registers/Subscribes module Listener to the event with the event function EventFunc....
Definition Module.h:1028
static void Deregister(const ModuleBase &Listener)
Deregisters/unsubscribes module Listener from the event. Indirectly calls ModuleBase::RemoveRegistere...
Definition Module.h:1034
const std::unique_ptr< ModuleDataType > ModuleData
Module data belonging to this ModuleBase instance.
Definition Module.h:743
Refer to ParamsBase::dispatch_tag.
Definition Module.h:189
Defines data for a thread belonging to a ModuleBase instance. Refer to RunnableInstance.
Definition Module.h:793
const ModuleBase::ModuleDataGetterType ModuleDataGetter
Getter for module's data. Refer to ModuleBase::ModuleDataGetterType.
Definition Module.h:825
Refer to ParamsBase::dispatch_tag.
Definition Object.h:2018
QModuleWidget * Widget
User interface widget belonging to the module.
Definition Module.h:1491
void Connect(SenderType *Sender, SignalType Signal, ReceiverType *Receiver, EventType Event)
Uses Qt's connect mechanism to connect a QObject's signal to a DynExp module's event....
Definition Module.h:1500
const Object::ParamsGetterType ParamsGetter
Invoke to obtain the parameters (derived from ParamsBase) of Owner.
Definition Object.h:3671
void UnlockObject(LinkedObjectWrapperContainer< ObjectT > &ObjectWrapperContainer)
Unlocks an Object instance stored in the LinkedObjectWrapperContainer ObjectWrapperContainer....
Definition Object.h:3570
void LockObject(const ParamsBase::Param< ObjectLink< ObjectT > > &LinkParam, LinkedObjectWrapperContainer< ObjectT > &ObjectWrapperContainer, std::chrono::milliseconds Timeout=ObjectLinkBase::LockObjectTimeoutDefault)
Locks an Object instance referenced by a parameter LinkParam of type ParamsBase::Param< ObjectLink< O...
Definition Object.h:3554
const auto & GetOwner() const noexcept
Returns Owner.
Definition Object.h:3524
Pointer to lock a class derived from ISynchronizedPointerLockable for synchronizing between threads....
Definition Util.h:170
Thrown when an operation timed out before it could be completed, especially used for locking shared d...
Definition Exception.h:261
DynExp's module namespace contains the implementation of DynExp modules which extend DynExp's core fu...
DynExpErrorCodes
DynExp's error codes
Definition Exception.h:22
std::vector< std::pair< TextType, ValueType > > TextValueListType
Type of a list containing key-value pairs where key is a text of type Util::TextType.
Definition QtUtil.h:37
Accumulates include statements to provide a precompiled header.
double DataType
Data type of time and value.