FTSensor.cpp
Go to the documentation of this file.
1 #include <boost/algorithm/clamp.hpp>
2 
3 #include <SimoxUtility/json.h>
4 #include <SimoxUtility/math/compare/is_equal.h>
5 #include <SimoxUtility/math/convert/mat4f_to_pos.h>
6 #include <SimoxUtility/math/convert/mat4f_to_quat.h>
7 //#include <RobotAPI/libraries/core/json_conversions.h>
8 #include <VirtualRobot/MathTools.h>
9 
11 
12 #include "../utils.h"
13 #include "FTSensor.h"
14 
16 {
17 
18  void
19  FTSensor::initialize(const VirtualRobot::RobotNodeSetPtr& rns,
20  const RobotUnitPtr& robotUnit,
21  const FTConfig& c)
22  {
23  ARMARX_INFO << "Initializing force torque sensor " << c.sensorName;
24  const SensorValueBase* svlf = robotUnit->getSensorDevice(c.sensorName)->getSensorValue();
25  forceSensor = svlf->asA<SensorValueForceTorque>();
26 
28  sensorNode = rns->getRobot()->getSensor(c.sensorName)->getRobotNode();
29 
30  if (c.sensorName == "FT R")
31  {
32  tcpMass = calibDefaults.tcpMassRight;
33  tcpCoMInFTSensorFrame = calibDefaults.tcpCoMInFTFrameRight;
34  }
35  else if (c.sensorName == "FT L")
36  {
37  tcpMass = calibDefaults.tcpMassLeft;
38  tcpCoMInFTSensorFrame = calibDefaults.tcpCoMInFTFrameLeft;
39  }
40 
41  rawForce.setZero();
42  rawTorque.setZero();
43  filteredForce.setZero();
44  filteredTorque.setZero();
45  filteredForceInRoot.setZero();
46  filteredTorqueInRoot.setZero();
47 
48  tcpGravityCompensation.setZero();
49  tcpGravForceVec.setZero();
50  tcpGravTorqueVec.setZero();
51 
52  sensorOriInRoot = Eigen::Matrix3f::Identity();
53  reset();
54  ARMARX_INFO << "Force torque sensor initialized.";
55  }
56 
57  //FTSensor::FTConfig FTSensor::reconfigure(const std::string &configFileName)
58  //{
59  // nlohmann::json userConfig;
60  // std::ifstream ifs{configFileName};
61  // ifs >> userConfig;
62  // auto c = userConfig["force_torque"];
63  // FTConfig config = FTConfig();
64  // std::string name = getValueWithDefault<std::string>(c, "", "sensor_name");
65  // if (name != sensorName)
66  // {
67  // ARMARX_ERROR << "the sensor name: " << name << " is not the same as initialized: " << sensorName << ", please consider to switch controllers instead of reuse";
68  // }
69  // config.ftFilter = getValueWithDefault<float>(c, s.ftFilter, "force_filter_coeff");
70  // config.deadZoneForce = getValueWithDefault<float>(c, s.deadZoneForce, "force_dead_zone");
71  // config.deadZoneTorque = getValueWithDefault<float>(c, s.deadZoneTorque, "torque_dead_zone");
72  // config.timeLimit = getValueWithDefault<float>(c, s.timeLimit, "wait_time_for_calibration");
73  // s.timeLimit = config.timeLimit;
74 
75  // config.enableTCPGravityCompensation = getValueWithDefault<bool>(c, s.enableTCPGravityCompensation, "enable_tcp_gravity_compensation");
76  // nlohmann::json compCfg;
77  // if (c.find(sensorName) != c.end())
78  // auto compCfg = c[sensorName];
79  // config.tcpMass = getValueWithDefault<float>(compCfg, s.tcpMass, "tcp_mass");
80  // config.tcpCoMInFTSensorFrame = getEigenVecWithDefault(compCfg, s.tcpCoMInFTSensorFrame, "tcp_CoM_in_FT_frame");
81  // config.forceBaseline.setZero();
82  // config.torqueBaseline.setZero();
83  // return config;
84  //}
85 
86  void
88  {
89  /// you have to call this method **only** in the first loop of rtRun
90  // s.tcpMass = 0.0f;
91  // s.tcpCoMInFTSensorFrame.setZero();
92 
93  forceOffset.setZero();
94  torqueOffset.setZero();
95  ft.setZero();
96 
97  calibrated.store(false);
98  timeForCalibration = 0.0f;
99 
100  safeGuardForceOffset.setZero();
101  safeGuardTorqueOffset.setZero();
102 
103  safeGuardEnabledForce.store(false);
104  safeGuardEnabledTorque.store(false);
105 
106  resetForceGuard.store(true);
107  resetTorqueGuard.store(true);
108 
109  // Eigen::Matrix4f forceFrameInRoot = sensorNode->getPoseInRootFrame();
110  // forceFrameInTCP.block<3, 3>(0, 0) = currentPose.block<3, 3>(0, 0).transpose() * forceFrameInRoot.block<3, 3>(0, 0);
111  // tcpCoMInTCPFrame = forceFrameInTCP.block<3, 3>(0, 0) * tcpCoMInFTSensorFrame;
112  }
113 
114  void
116  Eigen::Vector6f& currentFT,
117  double deltaT,
118  bool firstRun)
119  {
120  if (firstRun)
121  {
122  reset();
123  return;
124  }
125  sensorOriInRoot = sensorNode->getOrientationInRootFrame();
126  rawForce = forceSensor->force;
127  rawTorque = forceSensor->torque;
128 
129  if (c.reCalibrate)
130  {
131  calibrated.store(false);
132  /// TODO how to toggle recalibration?
133  }
135  if (!calibrated.load())
136  {
137  if (calibrate(c, deltaT))
138  {
139  calibrated.store(true);
140  }
141  }
142  else
143  {
144  currentFT = getFilteredForceTorque(c);
145  }
147  }
148 
149  void
151  {
152  if (c.enableSafeGuardForce and resetForceGuard.load())
153  {
154  safeGuardForceOffset = filteredForceInRoot;
155  safeGuardEnabledForce.store(true);
156  resetForceGuard.store(false);
157  }
158  if (c.enableSafeGuardTorque and resetTorqueGuard.load())
159  {
160  safeGuardTorqueOffset = filteredTorqueInRoot;
161  safeGuardEnabledTorque.store(true);
162  resetTorqueGuard.store(false);
163  }
164  }
165 
166  void
167  FTSensor::enableSafeGuard(bool enableForceGuard, bool enableTorqueGuard)
168  {
169  if (enableForceGuard)
170  {
171  resetForceGuard.store(true);
172  }
173  if (enableTorqueGuard)
174  {
175  resetTorqueGuard.store(true);
176  }
177  }
178 
179  bool
181  {
182  return safeGuardEnabledForce.load();
183  }
184 
185  bool
187  {
188  return safeGuardEnabledTorque.load();
189  }
190 
191  bool
193  {
194  auto unsafeFlag =
195  (c.enableSafeGuardForce and
196  (filteredForceInRoot - safeGuardForceOffset).norm() > c.safeGuardForceThreshold) or
197  (c.enableSafeGuardTorque and
198  (filteredTorqueInRoot - safeGuardTorqueOffset).norm() > c.safeGuardTorqueThreshold);
199  ftSafe.store(not unsafeFlag);
200 
201  return true;
202  }
203 
204  bool
205  FTSensor::calibrate(const FTConfig& c, double deltaT)
206  {
207  /// this will calibrate the force torque value in FTSensorFrame until timeLimit is reached
208  // sensorOriInRoot = sensorNode->getOrientationInRootFrame();
209  forceOffset = (1 - c.ftFilter) * forceOffset +
210  c.ftFilter * (forceSensor->force -
211  sensorOriInRoot.transpose() * tcpGravityCompensation.head(3));
212  torqueOffset = (1 - c.ftFilter) * torqueOffset +
213  c.ftFilter * (forceSensor->torque -
214  sensorOriInRoot.transpose() * tcpGravityCompensation.tail(3));
215 
216  timeForCalibration = timeForCalibration + deltaT;
217  if (timeForCalibration > c.timeLimit)
218  {
219  calibrated.store(true);
220  /// rt is ready only if the FT sensor is calibrated, and the rt2interface buffer is updated (see above)
222  "FT calibration done \n"
223  "-- force offset: [%.2f, %.2f, %.2f] \n"
224  "-- torque offset: [%.2f, %.2f, %.2f] \n"
225  "-- gravity compensation: [%.2f, %.2f, %.2f, %.2f, %.2f, %.2f]",
226  forceOffset(0),
227  forceOffset(1),
228  forceOffset(2),
229  torqueOffset(0),
230  torqueOffset(1),
231  torqueOffset(2),
232  tcpGravityCompensation(0),
233  tcpGravityCompensation(1),
234  tcpGravityCompensation(2),
235  tcpGravityCompensation(3),
236  tcpGravityCompensation(4),
237  tcpGravityCompensation(5));
238  }
239  return calibrated.load();
240  }
241 
242  //void FTSensor::enableGravityCompensation(const float mass, const Eigen::Vector3f& tcpCoMInFTFrame)
243  //{
244  // enableTCPGravityCompensation.store(true);
245  // tcpMass = mass;
246  // tcpCoMInFTSensorFrame = tcpCoMInFTFrame;
247  //}
248 
249  //void FTSensor::disableGravityCompensation()
250  //{
251  // enableTCPGravityCompensation.store(false);
252  // tcpMass = 0.0f;
253  // tcpCoMInFTSensorFrame.setZero();
254  // tcpGravityCompensation.setZero();
255  //}
256 
259  {
260  // /// update variables from rt buffer
261  // tcpMass = data.tcpMass;
262  // tcpCoMInTCPFrame = forceFrameInTCP.block<3, 3>(0, 0) * data.tcpCoMInFTSensorFrame;
263 
264  /// static compensation in root frame
265  if (c.enableTCPGravityCompensation)
266  {
267 
268  tcpGravForceVec = tcpMass * gravity.head(3);
269  tcpGravTorqueVec = (sensorOriInRoot * tcpCoMInFTSensorFrame).cross(tcpGravForceVec);
270  // tcpGravityCompensation << forceVec, torqueVec;
271  // Eigen::Vector3f localGravity = currentPose.block<3, 3>(0, 0).transpose() * gravity;
272  // Eigen::Vector3f localForceVec = tcpMass * localGravity;
273  // Eigen::Vector3f localTorqueVec = tcpCoMInTCPFrame.cross(localForceVec);
274 
275  // tcpGravityCompensation << localForceVec, localTorqueVec;
276  tcpGravityCompensation.head(3) = tcpGravForceVec;
277  tcpGravityCompensation.tail(3) = tcpGravTorqueVec;
278  }
279  else
280  {
281  tcpGravityCompensation.setZero();
282  }
283  return tcpGravityCompensation;
284  }
285 
288  {
289  filteredForce = (1 - c.ftFilter) * filteredForce + c.ftFilter * rawForce;
290  filteredTorque = (1 - c.ftFilter) * filteredTorque + c.ftFilter * rawTorque;
291 
292  filteredForceInRoot = sensorOriInRoot * (filteredForce - forceOffset) -
293  tcpGravityCompensation.head(3) - c.forceBaseline;
294  filteredTorqueInRoot = sensorOriInRoot * (filteredTorque - torqueOffset) -
295  tcpGravityCompensation.tail(3) - c.torqueBaseline;
296 
297  for (size_t i = 0; i < 3; ++i)
298  {
299  if (fabs(filteredForceInRoot(i)) > c.deadZoneForce)
300  {
301  filteredForceInRoot(i) -=
302  (filteredForceInRoot(i) / fabs(filteredForceInRoot(i))) * c.deadZoneForce;
303  }
304  else
305  {
306  filteredForceInRoot(i) = 0;
307  }
308 
309  if (fabs(filteredTorqueInRoot(i)) > c.deadZoneTorque)
310  {
311  filteredTorqueInRoot(i) -=
312  (filteredTorqueInRoot(i) / fabs(filteredTorqueInRoot(i))) * c.deadZoneTorque;
313  }
314  else
315  {
316  filteredTorqueInRoot(i) = 0;
317  }
318  }
319 
320  ft.head(3) = filteredForceInRoot;
321  ft.tail(3) = filteredTorqueInRoot;
322  return ft;
323  }
324 } // namespace armarx::control::common::ft
armarx::control::common::ft::FTSensor::initialize
void initialize(const VirtualRobot::RobotNodeSetPtr &rns, const armarx::RobotUnitPtr &robotUnit, const FTConfig &c)
Definition: FTSensor.cpp:19
armarx::control::common::ft::FTSensor::isSafe
bool isSafe(const FTConfig &c)
Definition: FTSensor.cpp:192
armarx::control::common::ft::FTSensor::resetSafeGuardOffset
void resetSafeGuardOffset(const FTConfig &c)
Definition: FTSensor.cpp:150
armarx::control::common::ft::FTCalibrateDefaultValue::tcpMassRight
float tcpMassRight
Definition: FTSensor.h:39
armarx::SensorValueBase::asA
const T * asA() const
Definition: SensorValueBase.h:82
armarx::SensorValueBase
The SensorValueBase class.
Definition: SensorValueBase.h:40
armarx::control::common::ft::FTSensor::FTConfig
arondto::FTConfig FTConfig
Definition: FTSensor.h:48
ARMARX_CHECK_NOT_NULL
#define ARMARX_CHECK_NOT_NULL(ptr)
This macro evaluates whether ptr is not null and if it turns out to be false it will throw an Express...
Definition: ExpressionException.h:206
armarx::control::common::ft::FTSensor::enableSafeGuard
void enableSafeGuard(bool enableForceGuard, bool enableTorqueGuard)
Definition: FTSensor.cpp:167
FTSensor.h
armarx::control::common::ft
This file is part of ArmarX.
Definition: aron_conversions.cpp:29
c
constexpr T c
Definition: UnscentedKalmanFilterTest.cpp:43
armarx::control::common::ft::FTSensor::isForceGuardEnabled
bool isForceGuardEnabled()
Definition: FTSensor.cpp:180
armarx::control::common::ft::FTCalibrateDefaultValue::tcpCoMInFTFrameRight
Eigen::Vector3f tcpCoMInFTFrameRight
Definition: FTSensor.h:40
armarx::SensorValueForceTorque::force
Eigen::Vector3f force
Definition: SensorValueForceTorque.h:35
GfxTL::Identity
void Identity(MatrixXX< N, N, T > *a)
Definition: MatrixXX.h:523
armarx::control::common::ft::FTSensor::ftSafe
std::atomic_bool ftSafe
Definition: FTSensor.h:71
armarx::control::common::ft::FTSensor::calibrated
std::atomic_bool calibrated
Definition: FTSensor.h:70
cross
Point cross(const Point &x, const Point &y)
Definition: point.hpp:33
armarx::control::common::ft::FTCalibrateDefaultValue::tcpCoMInFTFrameLeft
Eigen::Vector3f tcpCoMInFTFrameLeft
Definition: FTSensor.h:42
armarx::SensorValueForceTorque::torque
DETAIL_SensorValueBase_DEFAULT_METHOD_IMPLEMENTATION Eigen::Vector3f torque
Definition: SensorValueForceTorque.h:34
ARMARX_RT_LOGF_IMPORTANT
#define ARMARX_RT_LOGF_IMPORTANT(...)
Definition: ControlThreadOutputBuffer.h:341
armarx::control::common::ft::FTSensor::reset
void reset()
Definition: FTSensor.cpp:87
armarx::control::common::ft::FTSensor::updateStatus
void updateStatus(const FTConfig &c, Eigen::Vector6f &currentFT, double deltaT, bool firstRun)
Definition: FTSensor.cpp:115
armarx::control::common::ft::FTSensor::getFilteredForceTorque
Eigen::Vector6f & getFilteredForceTorque(const FTConfig &data)
Definition: FTSensor.cpp:287
ARMARX_INFO
#define ARMARX_INFO
Definition: Logging.h:174
armarx::control::common::ft::FTSensor::calibrate
bool calibrate(const FTConfig &c, double deltaT)
Definition: FTSensor.cpp:205
armarx::control::common::ft::FTCalibrateDefaultValue::tcpMassLeft
float tcpMassLeft
Definition: FTSensor.h:41
Eigen::Matrix< float, 6, 1 >
armarx::SensorValueForceTorque
Definition: SensorValueForceTorque.h:31
ArmarXDataPath.h
armarx::control::common::ft::FTSensor::isTorqueGuardEnabled
bool isTorqueGuardEnabled()
Definition: FTSensor.cpp:186
armarx::control::common::ft::FTSensor::compensateTCPGravity
Eigen::Vector6f & compensateTCPGravity(const FTConfig &data)
Definition: FTSensor.cpp:258