DynExp
Highly flexible laboratory automation for dynamically changing experiments.
Loading...
Searching...
No Matches
HardwareAdapterSmarAct.cpp
Go to the documentation of this file.
1// This file is part of DynExp.
2
3#include "stdafx.h"
5
6namespace DynExpHardware
7{
9 {
10 // Since C++17, writing to std::string's internal buffer is allowed.
11 std::string DeviceList;
12 DeviceList.resize(256);
13 size_t RequiredSize = DeviceList.size();
14 auto Result = SmarActSyms::SA_CTL_FindDevices("", DeviceList.data(), &RequiredSize);
15
16 // In case buffer of DeviceList is to small, RequiredSize now contains the required size. So, try again.
17 if (DeviceList.size() < RequiredSize)
18 {
19 DeviceList.resize(RequiredSize + 1);
20 RequiredSize = DeviceList.size();
21 Result = SmarActSyms::SA_CTL_FindDevices("", DeviceList.data(), &RequiredSize);
22 }
23
24 // Adjust length of string to length of data written by SA_CTL_FindDevices()
25 DeviceList.resize(RequiredSize);
26
27 if (Result != SA_CTL_ERROR_NONE)
28 throw SmarActException("Error enumerating SmarAct controllers.", Result);
29
30 // All descriptors are separated by '\n'. Replace that by ' ' and use std::istringstream to split by ' '.
31 std::replace(DeviceList.begin(), DeviceList.end(), '\n', ' ');
32 std::istringstream ss(DeviceList);
33 std::vector<std::string> DeviceDescriptors{ std::istream_iterator<std::string>(ss), std::istream_iterator<std::string>() };
34
35 return DeviceDescriptors;
36 }
37
39 {
40 auto SmarActDevices = SmarActHardwareAdapter::Enumerate();
41 if (!DeviceDescriptor.Get().empty() &&
42 std::find(SmarActDevices.cbegin(), SmarActDevices.cend(), DeviceDescriptor) == std::cend(SmarActDevices))
43 SmarActDevices.push_back(DeviceDescriptor);
44 if (SmarActDevices.empty())
45 throw Util::EmptyException("There is not any available SmarAct controller.");
46 DeviceDescriptor.SetTextList(std::move(SmarActDevices));
47
49 }
50
52 : HardwareAdapterBase(OwnerThreadID, std::move(Params))
53 {
54 Init();
55 }
56
58 {
59 // Not locking, since the object is being destroyed. This should be inherently thread-safe.
61 }
62
64 {
65 auto DerivedParams = dynamic_Params_cast<SmarActHardwareAdapter>(GetParams());
66
67 DeviceDescriptor = DerivedParams->DeviceDescriptor.Get();
68
69 SmarActHandleValid = false;
70 SmarActHandle = SmarActSyms::SA_CTL_DeviceHandle_t();
71 }
72
74 {
75 // auto lock = AcquireLock(); not necessary here, since DynExp ensures that Object::Reset() can only
76 // be called if respective object is not in use.
77
79 Init();
80
82 }
83
90
92 {
94
95 auto Exception = GetExceptionUnsafe();
96 Util::ForwardException(Exception);
97
98 return IsOpened();
99 }
100
102 {
103 return IsOpened();
104 }
105
106 void SmarActHardwareAdapter::CheckError(const SmarActSyms::SA_CTL_Result_t Result, const std::source_location Location) const
107 {
108 if (Result == SA_CTL_ERROR_NONE)
109 return;
110
111 std::string ErrorString(SmarActSyms::SA_CTL_GetResultInfo(Result));
112
113 // AcquireLock() has already been called by an (in)direct caller of this function.
114 ThrowExceptionUnsafe(std::make_exception_ptr(SmarActException(ErrorString, Result, Location)));
115 }
116
118 {
119 if (IsOpened())
120 return;
121
122 auto Result = SmarActSyms::SA_CTL_Open(&SmarActHandle, DeviceDescriptor.c_str(), "");
123 CheckError(Result);
124
125 SmarActHandleValid = true;
126 }
127
129 {
130 if (IsOpened())
131 {
132 // Handle now considered invalid, even if SA_CTL_Close() fails.
133 SmarActHandleValid = false;
134
135 auto Result = SmarActSyms::SA_CTL_Close(SmarActHandle);
136 CheckError(Result);
137 }
138 }
139
141 {
143
144 PositionType Position;
145 auto Result = SmarActSyms::SA_CTL_GetProperty_i64(SmarActHandle, Channel, SA_CTL_PKEY_POSITION, &Position, nullptr);
146 CheckError(Result);
147
148 return Position;
149 }
150
152 {
154
155 PositionType TargetPosition;
156 auto Result = SmarActSyms::SA_CTL_GetProperty_i64(SmarActHandle, Channel, SA_CTL_PKEY_TARGET_POSITION, &TargetPosition, nullptr);
157 CheckError(Result);
158
159 return TargetPosition;
160 }
161
163 {
165
166 PositionType Velocity;
167 auto Result = SmarActSyms::SA_CTL_GetProperty_i64(SmarActHandle, Channel, SA_CTL_PKEY_MOVE_VELOCITY, &Velocity, nullptr);
168 CheckError(Result);
169
170 return Velocity;
171 }
172
174 {
176
177 int32_t State;
178 auto Result = SmarActSyms::SA_CTL_GetProperty_i32(SmarActHandle, Channel, SA_CTL_PKEY_CHANNEL_STATE, &State, 0);
179 CheckError(Result);
180
181 return State;
182 }
183
185 {
187
188 auto Result = SmarActSyms::SA_CTL_Calibrate(SmarActHandle, Channel, 0);
189 CheckError(Result);
190 }
191
193 {
195
196 // Using direction configured as 'Safe Direction' on the SmarAct controller. Not allwing
197 // to change this setting, because this requires recalibration.
198 auto Result = SmarActSyms::SA_CTL_Reference(SmarActHandle, Channel, 0);
199 CheckError(Result);
200 }
201
203 {
205
206 auto Result = SmarActSyms::SA_CTL_SetProperty_i64(SmarActHandle, Channel, SA_CTL_PKEY_MOVE_VELOCITY, Velocity);
207 CheckError(Result);
208 }
209
211 {
213
214 auto Result = SmarActSyms::SA_CTL_SetProperty_i32(SmarActHandle, Channel, SA_CTL_PKEY_MOVE_MODE, SA_CTL_MOVE_MODE_CL_ABSOLUTE);
215 CheckError(Result);
216
217 Result = SmarActSyms::SA_CTL_Move(SmarActHandle, Channel, Position, 0);
218 CheckError(Result);
219 }
220
222 {
224
225 auto Result = SmarActSyms::SA_CTL_SetProperty_i32(SmarActHandle, Channel, SA_CTL_PKEY_MOVE_MODE, SA_CTL_MOVE_MODE_CL_RELATIVE);
226 CheckError(Result);
227
228 Result = SmarActSyms::SA_CTL_Move(SmarActHandle, Channel, Position, 0);
229 CheckError(Result);
230 }
231
233 {
235
236 if (!IsOpened())
237 return;
238
239 auto Result = SmarActSyms::SA_CTL_Stop(SmarActHandle, Channel, 0);
240 CheckError(Result);
241 }
242}
Implementation of a hardware adapter to control SmarAct MCS2 hardware.
void ConfigureParamsImpl(dispatch_tag< HardwareAdapterParamsBase >) override final
PositionType GetVelocity(const ChannelType Channel) const
int32_t GetChannelState(const ChannelType Channel) const
void MoveAbsolute(const ChannelType Channel, PositionType Position) const
bool IsConnectedChild() const noexcept override final
Determines the connection status of the hardware interface.
void ResetImpl(dispatch_tag< HardwareAdapterBase >) override final
void MoveRelative(const ChannelType Channel, PositionType Position) const
void CheckError(const SmarActSyms::SA_CTL_Result_t Result, const std::source_location Location=std::source_location::current()) const
PositionType GetTargetPosition(const ChannelType Channel) const
SmarActSyms::SA_CTL_DeviceHandle_t SmarActHandle
void EnsureReadyStateChild() override final
Ensures that this Object instance is ready by possibly starting its worker thread or by opening conne...
void Calibrate(const ChannelType Channel) const
void SetVelocity(const ChannelType Channel, PositionType Velocity) const
void Reference(const ChannelType Channel) const
SmarActHardwareAdapter(const std::thread::id OwnerThreadID, DynExp::ParamsBasePtrType &&Params)
bool IsReadyChild() const override final
Returns wheter this Object instance is ready (e.g. it is running or connected to a hardware device) a...
void StopMotion(const ChannelType Channel) const
PositionType GetCurrentPosition(const ChannelType Channel) const
static constexpr auto HardwareOperationTimeout
Default timeout used to lock the mutex provided by the base class Util::ILockable to synchronize acce...
void ThrowExceptionUnsafe(std::exception_ptr Exception) const
Stores Exception in LastException, wraps it in a Util::ForwardedException and throws the wrapped exce...
auto GetExceptionUnsafe() const
Getter for LastException.
ParamsConstTypeSyncPtrType GetParams(const std::chrono::milliseconds Timeout=GetParamsTimeoutDefault) const
Locks the mutex of the parameter class instance Params assigned to this Object instance and returns a...
Definition Object.cpp:436
Refer to ParamsBase::dispatch_tag.
Definition Object.h:2018
Tag for function dispatching mechanism within this class used when derived classes are not intended t...
Definition Object.h:349
Thrown when a list is expected to contain entries and when a query results in an empty answer or an e...
Definition Exception.h:224
LockType AcquireLock(const std::chrono::milliseconds Timeout=DefaultTimeout) const
Locks the internal mutex. Blocks until the mutex is locked or until the timeout duration is exceeded.
Definition Util.cpp:8
DynExp's hardware namespace contains the implementation of DynExp hardware adapters which extend DynE...
std::unique_ptr< ParamsBase > ParamsBasePtrType
Alias for a pointer to the parameter system base class ParamsBase.
Definition Object.h:1807
void ForwardException(std::exception_ptr e)
Wraps the exception passed to the function in a ForwardedException and throws the ForwardedException....
Definition Exception.cpp:30
Accumulates include statements to provide a precompiled header.