feet_force_torque_sensor_module.cpp
Go to the documentation of this file.
1 /*******************************************************************************
2 * Copyright 2018 ROBOTIS CO., LTD.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 *******************************************************************************/
16 
17 /*
18  * feet_force_torque_sensor_module.h
19  *
20  * Created on: 2016. 3. 22.
21  * Author: Jay Song
22  */
23 
25 
26 #define EXT_PORT_DATA_1 "external_port_data_1"
27 #define EXT_PORT_DATA_2 "external_port_data_2"
28 #define EXT_PORT_DATA_3 "external_port_data_3"
29 #define EXT_PORT_DATA_4 "external_port_data_4"
30 
31 using namespace thormang3;
32 
34 : control_cycle_msec_(8),
35  FT_NONE(0),
36  FT_AIR(1),
37  FT_GND(2),
38  FT_CALC(3)
39 {
40  module_name_ = "thormang3_foot_force_torque_sensor_module"; // set unique module name
41 
43 
44  r_foot_ft_air_.resize(6, 1); r_foot_ft_air_.fill(0.0);
45  l_foot_ft_air_.resize(6, 1); l_foot_ft_air_.fill(0.0);
46 
47  r_foot_ft_gnd_.resize(6, 1); r_foot_ft_gnd_.fill(0.0);
48  l_foot_ft_gnd_.resize(6, 1); l_foot_ft_gnd_.fill(0.0);
49 
52 
53  for(int _idx = 0; _idx < 6; _idx++) {
54  r_foot_ft_current_voltage_[_idx] = 3.3*0.5;
55  l_foot_ft_current_voltage_[_idx] = 3.3*0.5;
56  }
57 
62 
67 
68 
69  result_["r_foot_fx_raw_N"] = r_foot_fx_raw_N_;
70  result_["r_foot_fy_raw_N"] = r_foot_fy_raw_N_;
71  result_["r_foot_fz_raw_N"] = r_foot_fz_raw_N_;
72  result_["r_foot_tx_raw_Nm"] = r_foot_tx_raw_Nm_;
73  result_["r_foot_ty_raw_Nm"] = r_foot_ty_raw_Nm_;
74  result_["r_foot_tz_raw_Nm"] = r_foot_tz_raw_Nm_;
75 
76  result_["l_foot_fx_raw_N"] = l_foot_fx_raw_N_;
77  result_["l_foot_fy_raw_N"] = l_foot_fy_raw_N_;
78  result_["l_foot_fz_raw_N"] = l_foot_fz_raw_N_;
79  result_["l_foot_tx_raw_Nm"] = l_foot_tx_raw_Nm_;
80  result_["l_foot_ty_raw_Nm"] = l_foot_ty_raw_Nm_;
81  result_["l_foot_tz_raw_Nm"] = l_foot_tz_raw_Nm_;
82 
83 
84  result_["r_foot_fx_scaled_N"] = r_foot_fx_scaled_N_;
85  result_["r_foot_fy_scaled_N"] = r_foot_fy_scaled_N_;
86  result_["r_foot_fz_scaled_N"] = r_foot_fz_scaled_N_;
87  result_["r_foot_tx_scaled_Nm"] = r_foot_tx_scaled_Nm_;
88  result_["r_foot_ty_scaled_Nm"] = r_foot_ty_scaled_Nm_;
89  result_["r_foot_tz_scaled_Nm"] = r_foot_tz_scaled_Nm_;
90 
91  result_["l_foot_fx_scaled_N"] = l_foot_fx_scaled_N_;
92  result_["l_foot_fy_scaled_N"] = l_foot_fy_scaled_N_;
93  result_["l_foot_fz_scaled_N"] = l_foot_fz_scaled_N_;
94  result_["l_foot_tx_scaled_Nm"] = l_foot_tx_scaled_Nm_;
95  result_["l_foot_ty_scaled_Nm"] = l_foot_ty_scaled_Nm_;
96  result_["l_foot_tz_scaled_Nm"] = l_foot_tz_scaled_Nm_;
97 
98 
99  exist_r_leg_an_r_ = false;
100  exist_r_leg_an_p_ = false;
101  exist_l_leg_an_r_ = false;
102  exist_l_leg_an_p_ = false;
103 
104 
105  has_ft_air_ = false;
106  has_ft_gnd_ = false;
108  ft_period_ = 2 * 1000/ control_cycle_msec_;
109 
110  ft_get_count_ = 0;
111 }
112 
114 {
115  queue_thread_.join();
116 }
117 
118 void FeetForceTorqueSensor::initialize(const int control_cycle_msec, robotis_framework::Robot *robot)
119 {
120  control_cycle_msec_ = control_cycle_msec;
121 
122  ft_period_ = 2 * 1000/ control_cycle_msec_;
124 
125 
126  queue_thread_ = boost::thread(boost::bind(&FeetForceTorqueSensor::queueThread, this));
127 
129 }
130 
132 {
133  ros::NodeHandle ros_node;
134 
135  std::string foot_ft_data_path = ros_node.param<std::string>("ft_data_path", "");
136  std::string ft_calib_data_path = ros_node.param<std::string>("ft_calibration_data_path", "");
137 
138  r_foot_ft_sensor_.initialize(foot_ft_data_path, "ft_right_foot", "r_foot_ft_link" , "/robotis/sensor/ft_right_foot/raw", "/robotis/sensor/ft_right_foot/scaled");
139  l_foot_ft_sensor_.initialize(foot_ft_data_path, "ft_left_foot", "l_foot_ft_link", "/robotis/sensor/ft_left_foot/raw", "/robotis/sensor/ft_left_foot/scaled");
140 
141 
142  YAML::Node doc;
143 
144  doc = YAML::LoadFile(ft_calib_data_path.c_str());
145 
146  std::vector<double> ft;
147  ft = doc["ft_right_foot_air"].as<std::vector<double> >();
148  r_foot_ft_air_ = Eigen::Map<Eigen::MatrixXd>(ft.data(), 6, 1);
149 
150  ft.clear();
151  ft = doc["ft_right_foot_gnd"].as<std::vector<double> >();
152  r_foot_ft_gnd_ = Eigen::Map<Eigen::MatrixXd>(ft.data(), 6, 1);
153 
154  ft.clear();
155  ft = doc["ft_left_foot_air"].as<std::vector<double> >();
156  l_foot_ft_air_ = Eigen::Map<Eigen::MatrixXd>(ft.data(), 6, 1);
157 
158  ft.clear();
159  ft = doc["ft_left_foot_gnd"].as<std::vector<double> >();
160  l_foot_ft_gnd_ = Eigen::Map<Eigen::MatrixXd>(ft.data(), 6, 1);
161 
162  double scale = (total_mass_ * GRAVITY_ACCELERATION) / ( r_foot_ft_gnd_.coeff(2, 0) + l_foot_ft_gnd_.coeff(2, 0) - r_foot_ft_air_.coeff(2, 0) - l_foot_ft_air_.coeff(2, 0) );
164 
167 }
168 
169 void FeetForceTorqueSensor::saveFTCalibrationData(const std::string &path)
170 {
171  if(has_ft_air_ == false || has_ft_gnd_ == false) return;
172 
173  YAML::Emitter out;
174 
175  out << YAML::BeginMap;
176 
177  // air - right
178  std::vector<double> ft_calibration;
179  for(int ix = 0; ix < 6; ix++)
180  ft_calibration.push_back(r_foot_ft_air_.coeff(ix, 0));
181  out << YAML::Key << "ft_right_foot_air" << YAML::Value << ft_calibration;
182 
183  // ground - right
184  ft_calibration.clear();
185  for(int ix = 0; ix < 6; ix++)
186  ft_calibration.push_back(r_foot_ft_gnd_.coeff(ix, 0));
187  out << YAML::Key << "ft_right_foot_gnd" << YAML::Value << ft_calibration;
188 
189  // air - left
190  ft_calibration.clear();
191  for(int ix = 0; ix < 6; ix++)
192  ft_calibration.push_back(l_foot_ft_air_.coeff(ix, 0));
193  out << YAML::Key << "ft_left_foot_air" << YAML::Value << ft_calibration;
194 
195  // ground - left
196  ft_calibration.clear();
197  for(int ix = 0; ix < 6; ix++)
198  ft_calibration.push_back(l_foot_ft_gnd_.coeff(ix, 0));
199  out << YAML::Key << "ft_left_foot_gnd" << YAML::Value << ft_calibration;
200 
201  out << YAML::EndMap;
202 
203  // output to file
204  std::ofstream fout(path.c_str());
205  fout << out.c_str();
206 
207  ROS_INFO("Save FT foot calibration data");
208  publishStatusMsg(robotis_controller_msgs::StatusMsg::STATUS_INFO, "Saved FT Calibration Data");
209 }
210 
211 void FeetForceTorqueSensor::ftSensorCalibrationCommandCallback(const std_msgs::String::ConstPtr& msg)
212 {
213  if( (ft_command_ == FT_NONE) && (ft_period_ == ft_get_count_) )
214  {
215  std::string command = msg->data;
216 
217  if(command == "ft_air")
218  {
219  ft_get_count_ = 0;
221  publishStatusMsg(robotis_controller_msgs::StatusMsg::STATUS_INFO, "Start measuring FT_AIR");
222  has_ft_air_ = false;
223  r_foot_ft_air_.fill(0);
224  l_foot_ft_air_.fill(0);
225 
226  }
227  else if(command == "ft_gnd")
228  {
229  ft_get_count_ = 0;
231  publishStatusMsg(robotis_controller_msgs::StatusMsg::STATUS_INFO, "Start measuring FT_GND");
232  has_ft_gnd_ = false;
233  r_foot_ft_gnd_.fill(0);
234  l_foot_ft_gnd_.fill(0);
235  }
236  else if(command == "ft_send")
237  {
238  if(has_ft_air_ && has_ft_gnd_)
239  {
240  double scale = 1.0;
241  scale = (total_mass_ * GRAVITY_ACCELERATION) / ( r_foot_ft_gnd_.coeff(2, 0) + l_foot_ft_gnd_.coeff(2, 0) - r_foot_ft_air_.coeff(2, 0) - l_foot_ft_air_.coeff(2, 0) );
243 
244  ROS_INFO_STREAM("Total Mass : " << total_mass_);
245  ROS_INFO_STREAM("r_foot_ft_scale_factor_ : " << r_foot_ft_scale_factor_);
246  ROS_INFO_STREAM("l_foot_ft_scale_factor_ : " << l_foot_ft_scale_factor_);
247  ROS_INFO_STREAM("r_foot_ft_air_ : " << r_foot_ft_air_.transpose());
248  ROS_INFO_STREAM("l_foot_ft_air_ : " << l_foot_ft_air_.transpose());
249  ROS_INFO_STREAM("r_foot_ft_gnd_ : " << r_foot_ft_gnd_.transpose());
250  ROS_INFO_STREAM("l_foot_ft_gnd_ : " << l_foot_ft_gnd_.transpose());
253 
254  publishStatusMsg(robotis_controller_msgs::StatusMsg::STATUS_INFO, "Applied FT Calibration");
255  }
256  else
257  {
258  publishStatusMsg(robotis_controller_msgs::StatusMsg::STATUS_ERROR, "There is no value for calibration");
259  }
260  }
261  else if(command == "ft_save")
262  {
263  ros::NodeHandle ros_node;
264  std::string ft_calib_data_path = ros_node.param<std::string>("ft_calibration_data_path", "");
265  saveFTCalibrationData(ft_calib_data_path);
266  }
267  }
268  else
269  ROS_INFO("previous task is alive");
270 }
271 
272 void FeetForceTorqueSensor::publishStatusMsg(unsigned int type, std::string msg)
273 {
274  robotis_controller_msgs::StatusMsg status_msg;
275  status_msg.header.stamp = ros::Time::now();
276  status_msg.type = type;
277  status_msg.module_name = "FeetFT";
278  status_msg.status_msg = msg;
279 
281 }
282 
283 void FeetForceTorqueSensor::publishBothFTData(int type, Eigen::MatrixXd &ft_right, Eigen::MatrixXd &ft_left)
284 {
285  thormang3_feet_ft_module_msgs::BothWrench both_wrench_msg;
286 
287  if(type == FT_AIR)
288  both_wrench_msg.name = "ft_air";
289  else if(type == FT_GND)
290  both_wrench_msg.name = "ft_gnd";
291  else
292  return;
293 
294  both_wrench_msg.right.force.x = ft_right.coeff(0,0);
295  both_wrench_msg.right.force.y = ft_right.coeff(1,0);
296  both_wrench_msg.right.force.z = ft_right.coeff(2,0);
297  both_wrench_msg.right.torque.x = ft_right.coeff(3,0);
298  both_wrench_msg.right.torque.y = ft_right.coeff(4,0);
299  both_wrench_msg.right.torque.z = ft_right.coeff(5,0);
300 
301  both_wrench_msg.left.force.x = ft_left.coeff(0,0);
302  both_wrench_msg.left.force.y = ft_left.coeff(1,0);
303  both_wrench_msg.left.force.z = ft_left.coeff(2,0);
304  both_wrench_msg.left.torque.x = ft_left.coeff(3,0);
305  both_wrench_msg.left.torque.y = ft_left.coeff(4,0);
306  both_wrench_msg.left.torque.z = ft_left.coeff(5,0);
307 
308  thormang3_foot_ft_both_ft_pub_.publish(both_wrench_msg);
309 }
310 
312 {
313  ros::NodeHandle ros_node;
314  ros::CallbackQueue callback_queue;
315 
316  ros_node.setCallbackQueue(&callback_queue);
317 
318  /* subscriber */
319  ros::Subscriber ft_calib_command_sub = ros_node.subscribe("/robotis/feet_ft/ft_calib_command", 1, &FeetForceTorqueSensor::ftSensorCalibrationCommandCallback, this);
320 
321  /* publisher */
322  thormang3_foot_ft_status_pub_ = ros_node.advertise<robotis_controller_msgs::StatusMsg>("/robotis/status", 1);
323  thormang3_foot_ft_both_ft_pub_ = ros_node.advertise<thormang3_feet_ft_module_msgs::BothWrench>("/robotis/feet_ft/both_ft_value", 1);
324 
325  ros::WallDuration duration(control_cycle_msec_ / 1000.0);
326  while(ros_node.ok())
327  callback_queue.callAvailable(duration);
328 }
329 
330 void FeetForceTorqueSensor::process(std::map<std::string, robotis_framework::Dynamixel *> dxls, std::map<std::string, robotis_framework::Sensor *> sensors)
331 {
332  exist_r_leg_an_r_ = false;
333  exist_r_leg_an_p_ = false;
334  exist_l_leg_an_r_ = false;
335  exist_l_leg_an_p_ = false;
336 
337  std::map<std::string, robotis_framework::Dynamixel*>::iterator dxls_it = dxls.find("r_leg_an_r");
338 
339 
340  if(dxls_it != dxls.end())
341  {
342  r_foot_ft_current_voltage_[0] = (dxls_it->second->dxl_state_->bulk_read_table_[EXT_PORT_DATA_1])*3.3/4095.0;
343  r_foot_ft_current_voltage_[1] = (dxls_it->second->dxl_state_->bulk_read_table_[EXT_PORT_DATA_2])*3.3/4095.0;
344  r_foot_ft_current_voltage_[2] = (dxls_it->second->dxl_state_->bulk_read_table_[EXT_PORT_DATA_3])*3.3/4095.0;
345  r_foot_ft_current_voltage_[3] = (dxls_it->second->dxl_state_->bulk_read_table_[EXT_PORT_DATA_4])*3.3/4095.0;
346  exist_r_leg_an_r_ = true;
347  }
348  else
349  return;
350 
351  dxls_it = dxls.find("r_leg_an_p");
352  if(dxls_it != dxls.end())
353  {
354  r_foot_ft_current_voltage_[4] = (dxls_it->second->dxl_state_->bulk_read_table_[EXT_PORT_DATA_1])*3.3/4095.0;
355  r_foot_ft_current_voltage_[5] = (dxls_it->second->dxl_state_->bulk_read_table_[EXT_PORT_DATA_2])*3.3/4095.0;
356  exist_r_leg_an_p_ = true;
357  }
358  else
359  return;
360 
361  dxls_it = dxls.find("l_leg_an_r");
362  if(dxls_it != dxls.end())
363  {
364  l_foot_ft_current_voltage_[0] = (dxls_it->second->dxl_state_->bulk_read_table_[EXT_PORT_DATA_1])*3.3/4095.0;
365  l_foot_ft_current_voltage_[1] = (dxls_it->second->dxl_state_->bulk_read_table_[EXT_PORT_DATA_2])*3.3/4095.0;
366  l_foot_ft_current_voltage_[2] = (dxls_it->second->dxl_state_->bulk_read_table_[EXT_PORT_DATA_3])*3.3/4095.0;
367  l_foot_ft_current_voltage_[3] = (dxls_it->second->dxl_state_->bulk_read_table_[EXT_PORT_DATA_4])*3.3/4095.0;
368  exist_l_leg_an_r_ = true;
369  }
370  else
371  return;
372 
373  dxls_it = dxls.find("l_leg_an_p");
374  if(dxls_it != dxls.end())
375  {
376  l_foot_ft_current_voltage_[4] = (dxls_it->second->dxl_state_->bulk_read_table_[EXT_PORT_DATA_1])*3.3/4095.0;
377  l_foot_ft_current_voltage_[5] = (dxls_it->second->dxl_state_->bulk_read_table_[EXT_PORT_DATA_2])*3.3/4095.0;
378  exist_l_leg_an_p_ = true;
379  }
380  else
381  return;
382 
383 
384 
386 
393 
398 
399  result_["r_foot_fx_raw_N"] = r_foot_fx_raw_N_;
400  result_["r_foot_fy_raw_N"] = r_foot_fy_raw_N_;
401  result_["r_foot_fz_raw_N"] = r_foot_fz_raw_N_;
402  result_["r_foot_tx_raw_Nm"] = r_foot_tx_raw_Nm_;
403  result_["r_foot_ty_raw_Nm"] = r_foot_ty_raw_Nm_;
404  result_["r_foot_tz_raw_Nm"] = r_foot_tz_raw_Nm_;
405 
406 
407  result_["r_foot_fx_scaled_N"] = r_foot_fx_scaled_N_;
408  result_["r_foot_fy_scaled_N"] = r_foot_fy_scaled_N_;
409  result_["r_foot_fz_scaled_N"] = r_foot_fz_scaled_N_;
410  result_["r_foot_tx_scaled_Nm"] = r_foot_tx_scaled_Nm_;
411  result_["r_foot_ty_scaled_Nm"] = r_foot_ty_scaled_Nm_;
412  result_["r_foot_tz_scaled_Nm"] = r_foot_tz_scaled_Nm_;
413 
414  }
415 
423 
428 
429 
430  result_["l_foot_fx_raw_N"] = l_foot_fx_raw_N_;
431  result_["l_foot_fy_raw_N"] = l_foot_fy_raw_N_;
432  result_["l_foot_fz_raw_N"] = l_foot_fz_raw_N_;
433  result_["l_foot_tx_raw_Nm"] = l_foot_tx_raw_Nm_;
434  result_["l_foot_ty_raw_Nm"] = l_foot_ty_raw_Nm_;
435  result_["l_foot_tz_raw_Nm"] = l_foot_tz_raw_Nm_;
436 
437  result_["l_foot_fx_scaled_N"] = l_foot_fx_scaled_N_;
438  result_["l_foot_fy_scaled_N"] = l_foot_fy_scaled_N_;
439  result_["l_foot_fz_scaled_N"] = l_foot_fz_scaled_N_;
440  result_["l_foot_tx_scaled_Nm"] = l_foot_tx_scaled_Nm_;
441  result_["l_foot_ty_scaled_Nm"] = l_foot_ty_scaled_Nm_;
442  result_["l_foot_tz_scaled_Nm"] = l_foot_tz_scaled_Nm_;
443  }
444 
445 
446  if(ft_command_ == FT_NONE )
447  return;
448  else if(ft_command_ == FT_AIR)
449  {
450  ft_get_count_++;
451 
452  r_foot_ft_air_.coeffRef(0, 0) += r_foot_fx_raw_N_;
453  r_foot_ft_air_.coeffRef(1, 0) += r_foot_fy_raw_N_;
454  r_foot_ft_air_.coeffRef(2, 0) += r_foot_fz_raw_N_;
455  r_foot_ft_air_.coeffRef(3, 0) += r_foot_tx_raw_Nm_;
456  r_foot_ft_air_.coeffRef(4, 0) += r_foot_ty_raw_Nm_;
457  r_foot_ft_air_.coeffRef(5, 0) += r_foot_tz_raw_Nm_;
458 
459  l_foot_ft_air_.coeffRef(0, 0) += l_foot_fx_raw_N_;
460  l_foot_ft_air_.coeffRef(1, 0) += l_foot_fy_raw_N_;
461  l_foot_ft_air_.coeffRef(2, 0) += l_foot_fz_raw_N_;
462  l_foot_ft_air_.coeffRef(3, 0) += l_foot_tx_raw_Nm_;
463  l_foot_ft_air_.coeffRef(4, 0) += l_foot_ty_raw_Nm_;
464  l_foot_ft_air_.coeffRef(5, 0) += l_foot_tz_raw_Nm_;
465 
467  {
470 
471  has_ft_air_ = true;
472  publishStatusMsg(robotis_controller_msgs::StatusMsg::STATUS_INFO, "Finish measuring FT_AIR");
475  }
476  }
477  else if(ft_command_ == FT_GND)
478  {
479  ft_get_count_++;
480 
481  r_foot_ft_gnd_.coeffRef(0, 0) += r_foot_fx_raw_N_;
482  r_foot_ft_gnd_.coeffRef(1, 0) += r_foot_fy_raw_N_;
483  r_foot_ft_gnd_.coeffRef(2, 0) += r_foot_fz_raw_N_;
484  r_foot_ft_gnd_.coeffRef(3, 0) += r_foot_tx_raw_Nm_;
485  r_foot_ft_gnd_.coeffRef(4, 0) += r_foot_ty_raw_Nm_;
486  r_foot_ft_gnd_.coeffRef(5, 0) += r_foot_tz_raw_Nm_;
487 
488  l_foot_ft_gnd_.coeffRef(0, 0) += l_foot_fx_raw_N_;
489  l_foot_ft_gnd_.coeffRef(1, 0) += l_foot_fy_raw_N_;
490  l_foot_ft_gnd_.coeffRef(2, 0) += l_foot_fz_raw_N_;
491  l_foot_ft_gnd_.coeffRef(3, 0) += l_foot_tx_raw_Nm_;
492  l_foot_ft_gnd_.coeffRef(4, 0) += l_foot_ty_raw_Nm_;
493  l_foot_ft_gnd_.coeffRef(5, 0) += l_foot_tz_raw_Nm_;
494 
496  {
499 
500  has_ft_gnd_ = true;
501  publishStatusMsg(robotis_controller_msgs::StatusMsg::STATUS_INFO, "Finish measuring FT_GND");
503 
505  }
506  }
507  else
508  {
509  return;
510  }
511 
512 }
Eigen::MatrixXd getCurrentForceTorqueRaw()
void publish(const boost::shared_ptr< M > &message) const
Subscriber subscribe(const std::string &topic, uint32_t queue_size, void(T::*fp)(M), T *obj, const TransportHints &transport_hints=TransportHints())
void initialize(const int control_cycle_msec, robotis_framework::Robot *robot)
#define GRAVITY_ACCELERATION
std::map< std::string, double > result_
void setScaleParam(double ft_scale_factor, Eigen::MatrixXd ft_null)
ROSLIB_DECL std::string command(const std::string &cmd)
void setCurrentVoltageOutputPublish(double voltage0, double voltage1, double voltage2, double voltage3, double voltage4, double voltage5)
#define ROS_INFO(...)
void process(std::map< std::string, robotis_framework::Dynamixel * > dxls, std::map< std::string, robotis_framework::Sensor * > sensors)
bool param(const std::string &param_name, T &param_val, const T &default_val) const
void setCallbackQueue(CallbackQueueInterface *queue)
Publisher advertise(const std::string &topic, uint32_t queue_size, bool latch=false)
bool initialize(const std::string &ft_data_path, const std::string &ft_data_key, const std::string &ft_frame_id, const std::string &ft_raw_publish_name, const std::string &ft_scaled_publish_name)
void publishBothFTData(int type, Eigen::MatrixXd &ft_right, Eigen::MatrixXd &ft_left)
void ftSensorCalibrationCommandCallback(const std_msgs::String::ConstPtr &msg)
#define ROS_INFO_STREAM(args)
double calcTotalMass(int joint_id)
static Time now()
void publishStatusMsg(unsigned int type, std::string msg)
bool ok() const
Eigen::MatrixXd getCurrentForceTorqueScaled()
void saveFTCalibrationData(const std::string &path)


thormang3_feet_ft_module
Author(s): Zerom , SCH , Kayman , Jay Song
autogenerated on Mon Jun 10 2019 15:37:52