MotionLib  1.0.0
SamBuCa motion library
MFEPositionSensor.cpp
1 /*
2 ** Copyright (C) 2025 CERN
3 **
4 ** This software is provided 'as-is', without any express or implied
5 ** warranty. In no event will the authors be held liable for any damages
6 ** arising from the use of this software.
7 **
8 ** Permission is granted to anyone to use this software for any purpose,
9 ** including commercial applications, and to alter it and redistribute it
10 ** freely, subject to the following restrictions:
11 **
12 ** 1. The origin of this software must not be misrepresented; you must not
13 ** claim that you wrote the original software. If you use this software
14 ** in a product, an acknowledgment in the product documentation would be
15 ** appreciated but is not required.
16 ** 2. Altered source versions must be plainly marked as such, and must not be
17 ** misrepresented as being the original software.
18 ** 3. This notice may not be removed or altered from any source distribution.
19 **
20 ** Created on: 2025-04-17T16:21:03
21 ** Author: Sylvain Fargier <sylvain.fargier@cern.ch>
22 */
23 
24 #include "MFEPositionSensor.hpp"
25 
26 #include <ccut/async.hpp>
27 #include <ccut/utils.hpp>
28 
29 #include "MFEPlatform.hpp"
30 #include "Units.hpp"
31 #include "platform/specialized/MGrblPlatform/MGrblPlatform.hpp"
32 #include "util/grbl/GrblTypes.hpp"
33 
34 using namespace smc;
35 using namespace smc::internal;
38 
39 MFEPositionSensor::MFEPositionSensor(const std::string &uid,
40  const std::shared_ptr<MFEPlatform> &mfe) :
41  PositionSensor{uid},
42  m_mfe{mfe}
43 {}
44 
45 std::future<units::value_t> MFEPositionSensor::getPosition(
46  units::unit_t unit) const
47 {
48  try
49  {
50  std::shared_ptr<MFEPlatform> mfe(m_mfe.lock());
51  if (!mfe)
52  throw Exception(ErrorCode::Canceled, "platform stopped (deleted)");
53 
54  const std::string uid{this->uid()};
55  return mfe->run<units::value_t>(
56  [uid, unit](ImmediateCmd &cmd,
57  const MGrblPlatform::Context &mgrblCtx) {
58  const MFEPlatform::Context &ctx(
59  static_cast<const MFEPlatform::Context &>(mgrblCtx));
60 
61  const std::string regUid = uid + "/" + to_string(unit);
62  RegInfo info;
63  if (!ctx.edge)
64  throw Exception{ErrorCode::InvalidArguments,
65  "edge driver not available"};
66  else if (!ctx.getRegInfo(regUid, info))
67  throw Exception{ErrorCode::InvalidArguments,
68  "failed to get reg info: " + regUid};
69 
70  uint32_t value;
71  ctx.edge->read(info.reg, info.shift, value);
72 
73  switch (unit)
74  {
75  case units::steps:
76 
77  cmd.prom->get<units::value_t>().set_value(units::value_t{
78  unit,
79  units::value_t::value_type(
80  reinterpret_cast<const int32_t &>(value))});
81  break;
82 
83  case units::radians:
84  cmd.prom->get<units::value_t>().set_value(units::value_t{
85  unit,
86  units::value_t::value_type(
87  reinterpret_cast<const float &>(value))});
88  break;
89  default:
90  throw Exception(ErrorCode::IncompatibleUnits,
91  "failed to convert to " + to_string(unit));
92  }
93  });
94  }
95  catch (const Exception &ex)
96  {
97  return ccut::make_future_error<units::value_t>(ex);
98  }
99 }
100 
102  const units::value_t &value) const
103 {
104  try
105  {
106  units::value_t stepsValue{value};
107 
108  if (value.unit == units::radians)
109  throw Exception(
110  ErrorCode::IncompatibleUnits,
111  "can't modify resolver readout position (in radians)");
112  else if (!convert(stepsValue, units::steps))
113  throw Exception(ErrorCode::IncompatibleUnits,
114  "failed to convert in steps");
115 
116  return setConfig("position", std::to_string(uint32_t(stepsValue.value)));
117  }
118  catch (const Exception &ex)
119  {
120  return ccut::make_future_error<void>(ex);
121  }
122 }
123 
124 units::value_t MFEPositionSensor::lastPosition(const units::unit_t unit) const
125 {
126  std::shared_ptr<MFEPlatform> mfe(m_mfe.lock());
127  if (!mfe)
128  throw Exception(ErrorCode::Canceled, "platform stopped (deleted)");
129 
130  return mfe->getResolverPosition(uid(), unit);
131 }
132 
133 std::future<std::set<std::string>> MFEPositionSensor::listConfig() const
134 {
135  try
136  {
137  std::shared_ptr<MFEPlatform> mfe(m_mfe.lock());
138  if (!mfe)
139  throw Exception(ErrorCode::Canceled, "platform stopped (deleted)");
140 
141  grbl::Axis grblAxis = mfe->getResolverAxis(uid());
142 
143  return mfe->run<std::set<std::string>>(
144  [grblAxis, mfe](ImmediateCmd &cmd, MGrblPlatform::Context &ctx) {
145  std::set<std::string> ret;
146  mfe->runOnInstance(
147  ctx,
148  [&ret, grblAxis](GrblPlatform::Shared &,
149  GrblPlatform::Context &ctx) {
150  for (const std::string &name : ctx.listConfig(grblAxis))
151  {
152  if (ccut::startsWith(
153  name, MFEPlatform::s_resolverSettingPrefix))
154  {
155  const std::string setting{name.substr(
156  MFEPlatform::s_resolverSettingPrefix.size())};
157  if (!MFEPlatform::s_resolverConfigHidden.count(
158  setting))
159  ret.insert(setting);
160  }
161  }
162  },
163  true);
164 
165  cmd.prom->get<std::set<std::string>>().set_value(ret);
166  });
167  }
168  catch (const Exception &ex)
169  {
170  return ccut::make_future_error<std::set<std::string>>(ex);
171  }
172 }
173 
174 std::future<std::string> MFEPositionSensor::getConfig(
175  const std::string &name) const
176 {
177  try
178  {
179  std::shared_ptr<MFEPlatform> mfe(m_mfe.lock());
180  if (!mfe)
181  throw Exception(ErrorCode::Canceled, "platform stopped (deleted)");
182 
183  const std::string uid{this->uid()};
184  grbl::Axis grblAxis = mfe->getResolverAxis(uid);
185 
186  return mfe->run<std::string>(
187  [grblAxis, mfe, uid, name](ImmediateCmd &cmd,
188  MGrblPlatform::Context &ctx) {
189  std::string ret;
190  mfe->runOnInstance(
191  ctx,
192  [&ret, grblAxis, mfe, uid,
193  name](GrblPlatform::Shared &, GrblPlatform::Context &ctx) {
194  grbl::SettingId id =
195  ctx.findSetting(
196  MFEPlatform::s_resolverSettingPrefix + name,
197  grblAxis)
198  .id;
199 
200  ret = ctx._sendGetSetting(id);
201  mfe->updateResolverSetting(uid, id, ret);
202  },
203  true);
204 
205  cmd.prom->get<std::string>().set_value(ret);
206  });
207  }
208  catch (const Exception &ex)
209  {
210  return ccut::make_future_error<std::string>(ex);
211  }
212 }
213 
214 std::future<void> MFEPositionSensor::setConfig(const std::string &name,
215  const std::string &value) const
216 {
217  try
218  {
219  std::shared_ptr<MFEPlatform> mfe(m_mfe.lock());
220  if (!mfe)
221  throw Exception(ErrorCode::Canceled, "platform stopped (deleted)");
222 
223  const std::string uid{this->uid()};
224  grbl::Axis grblAxis = mfe->getResolverAxis(uid);
225 
226  return mfe->run<void>([grblAxis, mfe, uid, name,
227  value](ImmediateCmd &cmd,
228  MGrblPlatform::Context &ctx) {
229  mfe->runOnInstance(
230  ctx,
231  [grblAxis, mfe, uid, name, value](GrblPlatform::Shared &,
232  GrblPlatform::Context &ctx) {
233  grbl::SettingId id =
234  ctx.findSetting(
235  MFEPlatform::s_resolverSettingPrefix + name,
236  grblAxis)
237  .id;
238 
239  ctx._sendSetSetting(id, value);
240  mfe->updateResolverSetting(uid, id, value);
241  },
242  false);
243 
244  cmd.prom->get<void>().set_value();
245  });
246  }
247  catch (const Exception &ex)
248  {
249  return ccut::make_future_error(ex);
250  }
251 }
252 
254  units::unit_t unit) const
255 {
256  units::value_t temp{value};
257  return convert(temp, unit);
258 }
259 
260 static const std::set<units::unit_t> s_angle{
261  units::unit_t::degrees, units::unit_t::radians, units::unit_t::turns};
262 
263 bool MFEPositionSensor::convert(units::value_t &value, units::unit_t unit) const
264 {
265  std::shared_ptr<MFEPlatform> mfe(m_mfe.lock());
266  if (!mfe)
267  throw Exception(ErrorCode::Canceled, "platform stopped (deleted)");
268 
269  if (unit == value.unit)
270  return true;
271  else if (value.unit == units::steps && s_angle.count(unit))
272  {
273  units::value_t mode = mfe->getResolverMode(uid());
274  if (mode.value <= 0)
275  {
276  logger::warning(MFEPlatform::s_loggerCat)
277  << "resolver mode not set";
278  return false;
279  }
280  value = value / mode;
281  value.convert(unit);
282  return true;
283  }
284  else if (s_angle.count(value.unit) && unit == units::steps)
285  {
286  units::value_t mode = mfe->getResolverMode(uid());
287  if (mode.value <= 0)
288  {
289  logger::warning(MFEPlatform::s_loggerCat)
290  << "resolver mode not set";
291  return false;
292  }
293  value.convert(units::turns);
294  value = mode * value;
295  return true;
296  }
297  else
298  return convert(value, unit);
299 }
DeviceId uid() const
Get the address of device.
Definition: DeviceBase.cpp:76
Exception thrown by MotionController in case of issues with command.
Definition: Exception.hpp:61
std::future< std::string > getConfig(const std::string &name) const override
get device configuration value
bool convert(units::Value &value, units::unit_t unit) const override
Convert value in a manner specific to this device.
std::future< void > setActualPosition(const units::value_t &value) const override
Set the current position value.
units::value_t lastPosition(units::unit_t unit) const override
Get last known position.
bool canConvert(const units::Value &value, units::unit_t unit) const override
Check if unit conversion is possible in a manner specific to this device.
std::future< std::set< std::string > > listConfig() const override
list device configuration options
std::future< void > setConfig(const std::string &name, const std::string &value) const override
set device configuration value
const std::string & to_string(Axis::State state)
convert State to string
Definition: Axis.cpp:78
main motion-lib namespace
Definition: Client.cpp:30
void _sendSetSetting(grbl::SettingId settingId, const std::string &value)
set a setting on Grbl
std::set< std::string > listConfig()
list config values
const grbl::GrblParser::SettingDesc & findSetting(const std::string &name, grbl::Axis axis) const
find setting id for axis
std::string _sendGetSetting(grbl::SettingId settingId)
retrieve a setting from Grbl, eventually update internal cache
bool getRegInfo(const std::string &uid, RegInfo &info) const
Get the RegInfo object.