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