MotionLib  1.0.0
SamBuCa motion library
MockPlatform.cpp
1 /*
2  * Copyright (C) 2021 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: 2021-10-29
21  * Author: Michal Mysior <mmysior> <michal.mysior@cern.ch>
22  *
23  */
24 
25 #include "MockPlatform.hpp"
26 
27 #include <mutex>
28 #include <sstream>
29 #include <string>
30 
31 #include <ccut/yml.hpp>
32 #include <logger/Logger.hpp>
33 
34 #include "Exception.hpp"
35 #include "MockAxis.hpp"
36 #include "MockGpio.hpp"
37 #include "MockPositionSensor.hpp"
38 #include "Units.hpp"
39 
40 using namespace logger;
41 namespace yml = ccut::yml;
42 
43 static const std::string s_platformPrefix = "mock://";
44 static const uint32_t s_motorStepsPerMM = 250;
45 static const float s_lvdtStepsPerDegree = 4;
46 static const int32_t s_lvdtConstDegrees = 90;
47 
48 namespace smc {
49 
50 using namespace units;
51 
52 namespace internal {
53 
54 const std::string MockPlatform::s_loggerCat{"smc:mock"};
55 
56 MockPlatform::~MockPlatform() {}
57 
58 MockPlatform::MockPlatform(const yml::NodeRef &node)
59 {
60  yml::get(node, "id") >> yml::default_to(m_platformId, 0);
61 
62  yml::NodeRef elts = yml::get(node, "axis");
63  if (!elts.valid())
64  info(s_loggerCat) << "no axis configured";
65  else if (!elts.is_seq())
66  throw Exception(ErrorCode::InvalidArguments, "invalid axis type");
67  else
68  {
69  for (yml::NodeRef elt : elts)
70  {
71  std::string token;
72  elt >> token;
73  MotorLocation motor = motorFromStr(token);
74 
75  std::stringstream uri;
76  uri << s_platformPrefix << m_platformId << "/axis/" << motor;
77  debug(s_loggerCat) << "motor created: " << uri.str();
78  m_motors[uri.str()] = motor;
79  }
80  }
81 
82  elts = yml::get(node, "positions");
83  if (!elts.valid())
84  info(s_loggerCat) << "no positions configured";
85  else if (!elts.is_seq())
86  throw Exception(ErrorCode::InvalidArguments, "invalid positions type");
87  else
88  {
89  for (yml::NodeRef elt : elts)
90  {
91  uint8_t token;
92  elt >> token;
93 
94  std::stringstream uri;
95  uri << s_platformPrefix << m_platformId << "/position/"
96  << int(token);
97  debug(s_loggerCat) << "position created: " << uri.str();
98  m_lvdts[uri.str()] = token;
99  }
100  }
101 
102  elts = yml::get(node, "gpios");
103  if (!elts.valid())
104  info(s_loggerCat) << "no gpios configured";
105  else if (!elts.is_seq())
106  throw Exception(ErrorCode::InvalidArguments, "invalid gpios type");
107  else
108  {
109  for (yml::NodeRef elt : elts)
110  {
111  uint8_t token;
112  elt >> token;
113 
114  std::stringstream uri;
115  uri << s_platformPrefix << m_platformId << "/gpio/" << int(token);
116  debug(s_loggerCat) << "gpio created: " << uri.str();
117  m_gpios[uri.str()] = token;
118  }
119  }
120 
121  // Generate list of motor positions
122  for (const auto &motor : m_motors)
123  {
124  // All motors used initially at origin
125  m_motorPositions.insert(
126  std::pair<MotorLocation, units::Value::value_type>(motor.second,
127  0.0));
128  }
129 
130  // Generate list of POSITION position
131  for (const auto &lvdt : m_lvdts)
132  {
133  m_lvdtPositions.insert(std::pair<uint8_t, units::Value::value_type>(
134  lvdt.second, s_lvdtConstDegrees));
135  }
136 
137  // Generate list of GPIO states
138  for (const auto &gpio : m_gpios)
139  {
140  m_gpioStates.insert(
141  std::pair<uint8_t, io_port_t>(gpio.second, IOPort{false}));
142  }
143 }
144 
145 size_t MockPlatform::getPlatformId() const
146 {
147  return (m_platformId);
148 }
149 
150 void MockPlatform::setMotorPosition(const std::string &motor,
151  units::Value::value_type destPosition)
152 {
153  std::lock_guard<std::mutex> lock(m_lock);
154  auto it = m_motors.find(motor);
155 
156  if (it == m_motors.end())
157  {
158  error(s_loggerCat)
159  << "Bad motor address (" << motor
160  << ") referenced on MockPlatform id: " << m_platformId;
161  throw Exception(ErrorCode::InvalidArguments);
162  }
163 
164  m_motorPositions.find(it->second)->second = destPosition;
165 }
166 
167 units::Value::value_type MockPlatform::getMotorPosition(const std::string &motor)
168 {
169  std::lock_guard<std::mutex> lock(m_lock);
170  auto it = m_motors.find(motor);
171 
172  if (it == m_motors.end())
173  {
174  error(s_loggerCat)
175  << "Bad motor address (" << motor
176  << ") referenced on MockPlatform id: " << m_platformId;
177  throw Exception(ErrorCode::InvalidArguments);
178  }
179 
180  return m_motorPositions.find(it->second)->second;
181 }
182 
183 units::Value::value_type MockPlatform::getLvdtAngle(const std::string &lvdt)
184 {
185  std::lock_guard<std::mutex> lock(m_lock);
186  auto it = m_lvdts.find(lvdt);
187 
188  if (it == m_lvdts.end())
189  {
190  error(s_loggerCat)
191  << "Bad lvdt address (" << lvdt
192  << ") referenced on MockPlatform id: " << m_platformId;
193  throw Exception(ErrorCode::InvalidArguments);
194  }
195 
196  return m_lvdtPositions.find(it->second)->second;
197 }
198 
199 void MockPlatform::setLvdtAngle(const std::string &lvdt,
200  units::Value::value_type value)
201 {
202  std::lock_guard<std::mutex> lock(m_lock);
203  auto it = m_lvdts.find(lvdt);
204 
205  if (it == m_lvdts.end())
206  {
207  error(s_loggerCat)
208  << "Bad lvdt address (" << lvdt
209  << ") referenced on MockPlatform id: " << m_platformId;
210  throw Exception(ErrorCode::InvalidArguments);
211  }
212 
213  m_lvdtPositions.find(it->second)->second = value;
214 }
215 
216 void MockPlatform::setGpioState(const std::string &gpio,
217  const units::io_port_t &state)
218 {
219  std::lock_guard<std::mutex> lock(m_lock);
220  auto it = m_gpios.find(gpio);
221 
222  if (it == m_gpios.end())
223  {
224  error(s_loggerCat)
225  << "Bad gpio address (" << gpio
226  << ") referenced on MockPlatform id: " << m_platformId;
227  throw Exception(ErrorCode::InvalidArguments);
228  }
229 
230  m_gpioStates.find(it->second)->second = state;
231 }
232 
233 io_port_t MockPlatform::getGpioState(const std::string &gpio)
234 {
235  std::lock_guard<std::mutex> lock(m_lock);
236  auto it = m_gpios.find(gpio);
237 
238  if (it == m_gpios.end())
239  {
240  error(s_loggerCat)
241  << "Bad gpio address (" << gpio
242  << ") referenced on MockPlatform id: " << m_platformId;
243  throw Exception(ErrorCode::InvalidArguments);
244  }
245 
246  return m_gpioStates.find(it->second)->second;
247 }
248 
249 std::set<DeviceBase::DeviceType> MockPlatform::getSupportedDevices() const
250 {
251  std::set<DeviceBase::DeviceType> supported = {
252  DeviceBase::DeviceType::AXIS, DeviceBase::DeviceType::POSITION_SENSOR,
253  DeviceBase::DeviceType::GPIO};
254  return supported;
255 }
256 
257 PlatformBase::DeviceList MockPlatform::generateDevices(
258  const DeviceTypeList &deviceType)
259 {
260  DeviceList devices;
261 
262  if (deviceType.count(DeviceBase::DeviceType::AXIS))
263  {
264  for (std::pair<const std::string,
266  m_motors)
267  {
268  DeviceBase::Shared motor = std::make_shared<MockAxis>(
269  motorEntry.first, shared_from_this());
270  devices.push_back(motor);
271  }
272  }
273  if (deviceType.count(DeviceBase::DeviceType::POSITION_SENSOR))
274  {
275  for (std::pair<const std::string, uint8_t> lvdtEntry : m_lvdts)
276  {
277  DeviceBase::Shared lvdt = std::make_shared<MockPositionSensor>(
278  lvdtEntry.first, shared_from_this());
279  devices.push_back(lvdt);
280  }
281  }
282  if (deviceType.count(DeviceBase::DeviceType::GPIO))
283  {
284  for (std::pair<const std::string, uint8_t> gpioEntry : m_gpios)
285  {
286  DeviceBase::Shared gpio = std::make_shared<MockGpio>(
287  gpioEntry.first, shared_from_this());
288  devices.push_back(gpio);
289  }
290  }
291 
292  return devices;
293 }
294 
295 } /* namespace internal */
296 } /* namespace smc */
MotorLocation
Location of motor within given platform instance (e.g.
main motion-lib namespace
Definition: Client.cpp:30