ModularConvertedValue.h
Go to the documentation of this file.
1 /*
2  * This file is part of ArmarX.
3  *
4  * Copyright (C) 2012-2016, High Performance Humanoid Technologies (H2T),
5  * Karlsruhe Institute of Technology (KIT), all rights reserved.
6  *
7  * ArmarX is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License version 2 as
9  * published by the Free Software Foundation.
10  *
11  * ArmarX is distributed in the hope that it will be useful, but
12  * WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program. If not, see <http://www.gnu.org/licenses/>.
18  *
19  * @author Simon Ottenhaus (simon dot ottenhaus at kit dot edu)
20  * @copyright http://www.gnu.org/licenses/gpl-2.0.txt
21  * GNU General Public License
22  */
23 
24 
25 #pragma once
26 
27 
28 #include <cmath>
29 #include <cstdint>
30 #include <limits>
31 #include <type_traits>
32 
34 
36 
38 {
39 
40  template <typename T, typename SignedT = std::int64_t>
42  {
43 
44  public:
46  {
47  rawValue = nullptr;
48  zeroOffset = 0;
49  discontinuityOffset = 0;
50  maxValue = 0;
51  factor = 0;
52  isInverted = false;
53 
54  static_assert(std::is_signed_v<SignedT>);
55 
56  if constexpr(std::is_unsigned_v<T>)
57  {
58  static_assert(sizeof(SignedT) > sizeof(T));
59  }
60 
61  if constexpr(std::is_signed_v<T>)
62  {
63  static_assert(sizeof(SignedT) >= sizeof(T));
64  }
65  }
66 
67  void
68  init(T* raw,
70  const char* nameForDebugging = "")
71  {
72  init(raw,
73  modularConfig.getZeroOffset(),
74  modularConfig.getDiscontinuityOffset(),
75  modularConfig.getMaxValue(),
76  modularConfig.getIsInverted(),
77  nameForDebugging);
78  }
79 
80  void
81  init(T* raw,
82  float zeroOffset,
83  float discontinuityOffset,
84  float maxValue,
85  bool isInverted,
86  const char* nameForDebugging = "")
87  {
88 #if 0
89  const auto rawAsInt = reinterpret_cast<std::uint64_t>(raw);
90  ARMARX_CHECK_EQUAL((rawAsInt % alignof(T)), 0)
91  << "\nThe alignment is wrong!"
92  << "\nIt has to be " << alignof(T) << ", but the data is aligned with "
93  << rawAsInt % alignof(std::max_align_t) << "!"
94  << "\nThis is an offset of " << (rawAsInt % alignof(T)) << " bytes!"
95  << "\nThe datatype is " << GetTypeString<T>() << "\nIts size is " << sizeof(T)
96  << "\nraw = " << raw << " bytes"
97  << "\nThe name is '" << nameForDebugging << "'";
98 #endif
99  ARMARX_CHECK_POSITIVE(maxValue)
100  << "max value must not be zero (cannot divide/modulo by 0).";
101 
103  << "max value is greater than the maximum value of the datatype, "
104  << "the datatype is " << GetTypeString<T>();
105 
106  this->rawValue = raw;
107  this->zeroOffset = static_cast<SignedT>(zeroOffset);
108  this->discontinuityOffset = static_cast<SignedT>(discontinuityOffset);
109  this->maxValue = static_cast<SignedT>(maxValue);
110  this->factor = 2 * M_PIf64 / maxValue;
111  this->isInverted = isInverted;
112 
113  read();
114  }
115 
116  void
118  {
119  // "%" operator is not the real mathematical modulo operation but some creative ISO
120  // reinterpretation. This fixes it.
121  auto actual_real_modulo = [](SignedT dividend, SignedT divisor) -> SignedT
122  {
123  const SignedT result = dividend % divisor;
124  return result >= 0 ? result : result + divisor;
125  };
126 
127  const SignedT rawValueSigned = static_cast<SignedT>(*rawValue);
128  const SignedT maxValueSigned = static_cast<SignedT>(maxValue);
129 
130 
131  // Normalize direction of rotation.
132  const SignedT sign = isInverted ? -1 : 1;
133  const SignedT dirnorm = actual_real_modulo((sign * rawValueSigned), maxValueSigned);
134 
135  // Raw values within monotonic_raw_value are guaranteed to not fall into a
136  // discontinuity.
137  const SignedT monotonic_dirnorm =
138  actual_real_modulo((dirnorm + discontinuityOffset), maxValueSigned);
139 
140  // Zero shift.
141  const SignedT zeroshift_monotonic_dirnorm = monotonic_dirnorm - zeroOffset;
142 
143  // Convert ticks to rad.
144  const double zeroshift_monotonic_dirnorm_rad =
145  static_cast<double>(zeroshift_monotonic_dirnorm) * factor;
146 
147  value = zeroshift_monotonic_dirnorm_rad;
148  }
149 
150  void
152  {
153  //*rawValue = static_cast<T>((value / factor) - offset);
154  }
155 
156  double value;
157 
158  T
159  getRaw() const
160  {
161  return *rawValue;
162  }
163 
164  private:
165  T* rawValue;
166  SignedT zeroOffset;
167  SignedT discontinuityOffset;
168  T maxValue;
169  double factor;
170  bool isInverted;
171  };
172 
173 } // namespace armarx::control::ethercat
armarx::control::ethercat::ModularConvertedValue::value
double value
Definition: ModularConvertedValue.h:156
armarx::control::hardware_config::types::ModularConvertedValueConfig::getIsInverted
bool getIsInverted() const
Definition: Types.cpp:135
armarx::control::ethercat::ModularConvertedValue::ModularConvertedValue
ModularConvertedValue()
Definition: ModularConvertedValue.h:45
armarx::control::ethercat::ModularConvertedValue::read
void read()
Definition: ModularConvertedValue.h:117
armarx::sign
T sign(T t)
Definition: algorithm.h:194
armarx::control::hardware_config::types::ModularConvertedValueConfig::getDiscontinuityOffset
float getDiscontinuityOffset() const
Definition: Types.cpp:123
armarx::control::ethercat::ModularConvertedValue::write
void write()
Definition: ModularConvertedValue.h:151
armarx::control::ethercat::ModularConvertedValue::getRaw
T getRaw() const
Definition: ModularConvertedValue.h:159
armarx::control::ethercat
Definition: Bus.cpp:24
Types.h
armarx::control::hardware_config::types::ModularConvertedValueConfig::getZeroOffset
float getZeroOffset() const
Definition: Types.cpp:117
max
T max(T t1, T t2)
Definition: gdiam.h:48
armarx::control::hardware_config::types::ModularConvertedValueConfig
Definition: Types.h:68
ARMARX_CHECK_POSITIVE
#define ARMARX_CHECK_POSITIVE(number)
This macro evaluates whether number is positive (> 0) and if it turns out to be false it will throw a...
Definition: ExpressionException.h:145
armarx::control::ethercat::ModularConvertedValue::init
void init(T *raw, const hardware_config::types::ModularConvertedValueConfig modularConfig, const char *nameForDebugging="")
Definition: ModularConvertedValue.h:68
ARMARX_CHECK_LESS_EQUAL
#define ARMARX_CHECK_LESS_EQUAL(lhs, rhs)
This macro evaluates whether lhs is less or equal (<=) rhs and if it turns out to be false it will th...
Definition: ExpressionException.h:109
ExpressionException.h
armarx::control::ethercat::ModularConvertedValue::init
void init(T *raw, float zeroOffset, float discontinuityOffset, float maxValue, bool isInverted, const char *nameForDebugging="")
Definition: ModularConvertedValue.h:81
T
float T
Definition: UnscentedKalmanFilterTest.cpp:35
armarx::control::hardware_config::types::ModularConvertedValueConfig::getMaxValue
float getMaxValue() const
Definition: Types.cpp:129
ARMARX_CHECK_EQUAL
#define ARMARX_CHECK_EQUAL(lhs, rhs)
This macro evaluates whether lhs is equal (==) rhs and if it turns out to be false it will throw an E...
Definition: ExpressionException.h:130
armarx::control::ethercat::ModularConvertedValue
Definition: ModularConvertedValue.h:41