27 #include <unordered_map>
29 #include <ccut/utils.hpp>
32 #include "Exception.hpp"
33 #include "util/serialize.hpp"
35 using smc::units::Unit;
39 static const std::string s_empty;
40 static const std::unordered_map<Unit, std::string> s_unitToStr{
41 {{units::UNKNOWN,
"unknown"},
42 {units::MILLIMETERS,
"mm"},
44 {units::STEPS,
"steps"},
45 {units::DEGREES,
"deg"},
46 {units::RADIANS,
"rad"},
47 {units::TURNS,
"turns"},
48 {units::MILLIMETERS_PER_MINUTE,
"mm/min"},
49 {units::METERS_PER_SECOND,
"m/s"},
50 {units::STEPS_PER_MILLIMETER,
"steps/mm"},
51 {units::STEPS_PER_TURN,
"steps/turn"},
52 {units::MILLIMETERS_PER_SECOND,
"mm/s"},
53 {units::MILLIMETERS_PER_SECOND_SQUARED,
"mm/s^2"}}};
54 static const std::unordered_map<std::string, Unit> s_unitFromStr{
55 ccut::flip(s_unitToStr)};
56 static const std::set<Unit> s_unitKeys{ccut::keys(s_unitToStr)};
60 std::unordered_map<Unit, std::string>::const_iterator it = s_unitToStr.find(
62 return (it != s_unitToStr.end()) ? it->second : s_empty;
66 Unit from_string<Unit>(
const std::string &str)
68 std::unordered_map<std::string, Unit>::const_iterator it =
69 s_unitFromStr.find(str);
70 return (it != s_unitFromStr.end()) ? it->second : Unit::UNKNOWN;
81 Value::Value() : unit{UNKNOWN}, value{0.0} {}
83 Value::Value(Unit unit, value_type value) : unit{unit}, value{value} {}
85 bool Value::canConvert(unit_t unit)
const
88 return checkConvert(throwaway, unit);
91 bool Value::convert(unit_t unit)
93 if (checkConvert(this->value, unit))
101 Value &Value::operator+=(value_type raw)
107 Value &Value::operator-=(value_type raw)
113 Value &Value::operator*=(value_type raw)
119 Value &Value::operator/=(value_type raw)
125 Value operator*(Value::value_type raw, Unit unit)
127 return Value{unit, raw};
130 Value
operator"" _mm(
long double raw)
132 return Value{Unit::MILLIMETERS, Value::value_type(raw)};
135 Value
operator"" _m(
long double raw)
137 return Value{Unit::METERS, Value::value_type(raw)};
140 Value
operator"" _steps(
long double raw)
142 return Value{Unit::STEPS, Value::value_type(raw)};
145 Value
operator"" _deg(
long double raw)
147 return Value{Unit::DEGREES, Value::value_type(raw)};
150 Value
operator"" _rad(
long double raw)
152 return Value{Unit::RADIANS, Value::value_type(raw)};
155 Value
operator"" _turns(
long double raw)
157 return Value{Unit::TURNS, Value::value_type(raw)};
160 Value
operator"" _mm_per_min(
long double raw)
162 return Value{Unit::MILLIMETERS_PER_MINUTE, Value::value_type(raw)};
165 Value
operator"" _m_per_s(
long double raw)
167 return Value{Unit::METERS_PER_SECOND, Value::value_type(raw)};
170 Value
operator"" _steps_per_mm(
long double raw)
172 return Value{Unit::STEPS_PER_MILLIMETER, Value::value_type(raw)};
175 Value
operator"" _steps_per_turn(
long double raw)
177 return Value{Unit::STEPS_PER_TURN, Value::value_type(raw)};
180 Value
operator"" _mm_per_s(
long double raw)
182 return Value{Unit::MILLIMETERS_PER_SECOND, Value::value_type(raw)};
185 Value
operator"" _mm_per_s2(
long double raw)
187 return Value{Unit::MILLIMETERS_PER_SECOND_SQUARED, Value::value_type(raw)};
190 Value operator*(
const Value &value1,
const Value &value2)
194 case Unit::STEPS_PER_MILLIMETER:
195 if (value2.unit == Unit::MILLIMETERS)
196 return Value{Unit::STEPS, (value1.value * value2.value)};
198 case Unit::MILLIMETERS:
199 if (value2.unit == Unit::STEPS_PER_MILLIMETER)
200 return Value{Unit::STEPS, (value1.value * value2.value)};
202 case Unit::STEPS_PER_TURN:
203 if (value2.unit == Unit::TURNS)
204 return Value{Unit::STEPS, (value1.value * value2.value)};
208 throw Exception{ErrorCode::IncompatibleUnits};
211 Value operator/(
const Value &value1,
const Value &value2)
216 if (value2.unit == Unit::MILLIMETERS)
217 return Value{Unit::STEPS_PER_MILLIMETER,
218 (value1.value / value2.value)};
219 else if (value2.unit == Unit::STEPS_PER_MILLIMETER)
220 return Value{Unit::MILLIMETERS, (value1.value / value2.value)};
221 else if (value2.unit == Unit::STEPS_PER_TURN)
222 return Value{Unit::TURNS, (value1.value / value2.value)};
223 else if (value2.unit == Unit::TURNS)
224 return Value{Unit::STEPS_PER_TURN, (value1.value / value2.value)};
228 throw Exception{ErrorCode::IncompatibleUnits};
231 std::string Value::toString()
const
236 bool Value::checkConvert(value_type &converted, Unit unit)
const
238 if (this->unit == unit)
247 case unit_t::DEGREES:
248 if (unit == unit_t::RADIANS)
249 converted = (((this->value) * M_PI) / 180);
250 else if (unit == unit_t::TURNS)
251 converted = (this->value / 360);
255 case unit_t::RADIANS:
256 if (unit == unit_t::DEGREES)
257 converted = (((this->value) * 180) / M_PI);
258 else if (unit == unit_t::TURNS)
259 converted = (this->value / (2 * M_PI));
264 if (unit == unit_t::DEGREES)
265 converted = this->value * 360;
266 else if (unit == unit_t::RADIANS)
267 converted = this->value * (2 * M_PI);
272 case Unit::MILLIMETERS_PER_MINUTE:
273 if (unit == Unit::METERS_PER_SECOND)
275 converted = ((this->value / (60 * 1000)));
278 else if (unit == Unit::MILLIMETERS_PER_SECOND)
280 converted = ((this->value / 60));
286 case Unit::METERS_PER_SECOND:
287 if (unit == Unit::MILLIMETERS_PER_MINUTE)
289 converted = ((this->value * (60 * 1000)));
292 else if (unit == Unit::MILLIMETERS_PER_SECOND)
294 converted = ((this->value * 1000));
300 case Unit::MILLIMETERS_PER_SECOND:
301 if (unit == Unit::METERS_PER_SECOND)
303 converted = ((this->value / 1000));
306 else if (unit == Unit::MILLIMETERS_PER_MINUTE)
308 converted = ((this->value * 60));
314 case Unit::MILLIMETERS:
315 if (unit == Unit::METERS)
317 converted = ((this->value / 1000));
324 if (unit == Unit::MILLIMETERS)
326 converted = ((this->value * 1000));
332 default:
return false;
336 std::string IOPort::toString(IOPort::StrFmt format)
const
339 return std::string();
340 else if (format == StrFmt::AUTO && size == 1)
341 return value ?
"1" :
"0";
342 else if ((format == StrFmt::BIN) ||
343 ((format == StrFmt::AUTO) && (size <= 16)))
345 std::vector<char> buf(size + (size >> 3) + 3);
346 size_t off = buf.size() - 1;
351 for (
size_t i = 0; i < size; ++i)
353 if (i && !(i & 0x07))
355 buf[off--] = (v & 1) ?
'1' :
'0';
364 std::vector<char> buf(size + (size >> 5) + 3);
365 size_t off = buf.size() - 1;
370 for (
size_t i = 0; i < size;)
372 if (i && !(i & 0x1F))
374 const uint8_t quartet = (v & 0x0F);
375 buf[off--] = (quartet >= 10) ? (quartet - 10 +
'A') :
389 units::io_port_t from_string<units::io_port_t>(
const std::string &str)
392 return units::IOPort{};
393 else if (str.size() == 1)
397 case '0':
return units::IOPort{
false};
398 case '1':
return units::IOPort{
true};
399 default:
return units::IOPort{};
402 else if (str[0] ==
'0' && (str[1] ==
'x' || str[1] ==
'X'))
406 for (
size_t i = 2; i < str.size(); ++i)
408 const char c = str[i];
414 if (c >=
'0' && c <=
'9')
416 else if (c >=
'a' && c <=
'f')
417 value += c -
'a' + 10;
418 else if (c >=
'A' && c <=
'F')
419 value += c -
'A' + 10;
421 return units::IOPort{};
423 return units::IOPort{value, sz};
425 else if (str[0] ==
'0' && (str[1] ==
'b' || str[1] ==
'B'))
429 for (
size_t i = 2; i < str.size(); ++i)
431 const char c = str[i];
440 return units::IOPort{};
442 return units::IOPort{value, sz};
445 return units::IOPort{};
const std::set< AxisPositionMonitor::State > & getEnumValues()
Get devices types list (to be iterated)
const std::string & to_string(Axis::State state)
convert State to string
main motion-lib namespace