37 std::lock_guard g{_all_mutex};
46 std::lock_guard g{_all_mutex};
55 std::lock_guard g{_all_mutex};
61 _dialog->addLineEdit(
"dbgo",
"DebugObserver Topic",
"DebugObserver");
63 return qobject_cast<SimpleConfigDialog*>(_dialog);
69 std::lock_guard g{_all_mutex};
82 _widget.pushButtonLoadCalibFromFile->setVisible(
false);
83 connect(_widget.pushButtonLoadCalibFromFile, &QPushButton::clicked,
84 this, &FTSensorCalibrationGuiWidgetController::loadCalibFromFile);
85 connect(_widget.pushButtonStart, &QPushButton::clicked,
86 this, &FTSensorCalibrationGuiWidgetController::startRecording);
87 connect(_widget.pushButtonStop, &QPushButton::clicked,
88 this, &FTSensorCalibrationGuiWidgetController::stopRecording);
89 connect(_widget.pushButtonLoadDefaultArmar6FTL, &QPushButton::clicked,
90 this, &FTSensorCalibrationGuiWidgetController::loadDefaultArmar6FTL);
91 connect(_widget.pushButtonLoadDefaultArmar6FTR, &QPushButton::clicked,
92 this, &FTSensorCalibrationGuiWidgetController::loadDefaultArmar6FTR);
94 connect(_widget.tableWidgetOffset, &QTableWidget::itemChanged,
95 this, &FTSensorCalibrationGuiWidgetController::updateCalibration);
96 connect(_widget.tableWidgetOffset, &QTableWidget::itemChanged,
97 this, &FTSensorCalibrationGuiWidgetController::updateCalibration);
98 connect(_widget.tableWidgetChannelOrder, &QTableWidget::itemChanged,
99 this, &FTSensorCalibrationGuiWidgetController::updateCalibration);
100 connect(_widget.doubleSpinBoxTickToVolt, qOverload<double>(&QDoubleSpinBox::valueChanged),
101 this, &FTSensorCalibrationGuiWidgetController::updateCalibration);
102 connect(_widget.doubleSpinBoxTickToVoltE, qOverload<int>(&QSpinBox::valueChanged),
103 this, &FTSensorCalibrationGuiWidgetController::updateCalibration);
105 connect(_widget.tableWidgetCompensate, &QTableWidget::itemChanged,
106 this, &FTSensorCalibrationGuiWidgetController::updateCompensation);
108 loadDefaultArmar6FTR();
119 std::lock_guard g{_all_mutex};
120 _robot =
addOrGetRobot(
"r", VirtualRobot::RobotIO::RobotDescription::eStructure);
126 std::lock_guard g{_all_mutex};
128 _comboboxes_are_set_up =
false;
135 std::lock_guard g{_all_mutex};
138 _widget.widgetFields->setEnabled(
false);
141 const auto to_list = [](
const auto & container)
144 for (
const auto& name : container)
146 qnames << QString::fromStdString(name);
150 if (!_comboboxes_are_set_up)
154 _all_logging_names = std::set<std::string>(vec.begin(), vec.end());
156 const auto qnames = to_list(_all_logging_names);
157 const auto setup = [&](
auto box,
const auto & lst,
auto regex)
161 const auto idx = lst.indexOf(QRegExp{regex});
164 box->setCurrentIndex(idx);
167 setup(_widget.comboBoxADC1Value, qnames, R
"(^sens\.FT R\.adc_raw_1_to_3\.x$)");
168 setup(_widget.comboBoxADC2Value, qnames, R"(^sens\.FT R\.adc_raw_1_to_3\.y$)");
169 setup(_widget.comboBoxADC3Value, qnames, R"(^sens\.FT R\.adc_raw_1_to_3\.z$)");
170 setup(_widget.comboBoxADC4Value, qnames, R"(^sens\.FT R\.adc_raw_4_to_6\.x$)");
171 setup(_widget.comboBoxADC5Value, qnames, R"(^sens\.FT R\.adc_raw_4_to_6\.y$)");
172 setup(_widget.comboBoxADC6Value, qnames, R"(^sens\.FT R\.adc_raw_4_to_6\.z$)");
174 setup(_widget.comboBoxADC1Temp, qnames, R"(^sens\.FT R\.adc_1_to_3_temperature$)");
175 setup(_widget.comboBoxADC2Temp, qnames, R"(^sens\.FT R\.adc_1_to_3_temperature$)");
176 setup(_widget.comboBoxADC3Temp, qnames, R"(^sens\.FT R\.adc_1_to_3_temperature$)");
177 setup(_widget.comboBoxADC4Temp, qnames, R"(^sens\.FT R\.adc_4_to_6_temperature$)");
178 setup(_widget.comboBoxADC5Temp, qnames, R"(^sens\.FT R\.adc_4_to_6_temperature$)");
179 setup(_widget.comboBoxADC6Temp, qnames, R"(^sens\.FT R\.adc_4_to_6_temperature$)");
181 setup(_widget.comboBoxKinematicChain,
182 to_list(_robot->getRobotNodeSetNames()),
185 _widget.pushButtonStart->setEnabled(
true);
186 _widget.widgetFields->setEnabled(
true);
187 _comboboxes_are_set_up =
true;
191 _widget.comboBoxADC1Value->setEnabled(!_recording);
192 _widget.comboBoxADC2Value->setEnabled(!_recording);
193 _widget.comboBoxADC3Value->setEnabled(!_recording);
194 _widget.comboBoxADC4Value->setEnabled(!_recording);
195 _widget.comboBoxADC5Value->setEnabled(!_recording);
196 _widget.comboBoxADC6Value->setEnabled(!_recording);
198 _widget.comboBoxADC1Temp ->setEnabled(!_recording);
199 _widget.comboBoxADC2Temp ->setEnabled(!_recording);
200 _widget.comboBoxADC3Temp ->setEnabled(!_recording);
201 _widget.comboBoxADC4Temp ->setEnabled(!_recording);
202 _widget.comboBoxADC5Temp ->setEnabled(!_recording);
203 _widget.comboBoxADC6Temp ->setEnabled(!_recording);
212 auto&
data = _streaming_handler->getDataBuffer();
214 long time_compensation_us = 0;
217 const auto log = [&](
auto n)
219 _logfile <<
';' << n;
221 for (
const auto&
s :
data)
223 _logfile <<
s.iterationId <<
';' <<
s.timestampUSec;
230 std::vector<float> vals;
232 const auto& last =
data.back();
233 const auto pback = [&](
auto n)
235 vals.emplace_back(n);
243 raw_ft_unordered[0] = vals.at(0);
244 raw_ft_unordered[1] = vals.at(1);
245 raw_ft_unordered[2] = vals.at(2);
246 raw_ft_unordered[3] = vals.at(3);
247 raw_ft_unordered[4] = vals.at(4);
248 raw_ft_unordered[5] = vals.at(5);
251 temp_unordered[0] = vals.at(6 + 0);
252 temp_unordered[1] = vals.at(6 + 1);
253 temp_unordered[2] = vals.at(6 + 2);
254 temp_unordered[3] = vals.at(6 + 3);
255 temp_unordered[4] = vals.at(6 + 4);
256 temp_unordered[5] = vals.at(6 + 5);
258 _widget.labelADC1Value->setText(QString::number(raw_ft_unordered(0)));
259 _widget.labelADC2Value->setText(QString::number(raw_ft_unordered(1)));
260 _widget.labelADC3Value->setText(QString::number(raw_ft_unordered(2)));
261 _widget.labelADC4Value->setText(QString::number(raw_ft_unordered(3)));
262 _widget.labelADC5Value->setText(QString::number(raw_ft_unordered(4)));
263 _widget.labelADC6Value->setText(QString::number(raw_ft_unordered(5)));
265 _widget.labelADC1Temp ->setText(QString::number(temp_unordered(0)));
266 _widget.labelADC2Temp ->setText(QString::number(temp_unordered(1)));
267 _widget.labelADC3Temp ->setText(QString::number(temp_unordered(2)));
268 _widget.labelADC4Temp ->setText(QString::number(temp_unordered(3)));
269 _widget.labelADC5Temp ->setText(QString::number(temp_unordered(4)));
270 _widget.labelADC6Temp ->setText(QString::number(temp_unordered(5)));
272 const auto do_compensation = [&]
274 const auto st = std::chrono::high_resolution_clock::now();
275 for (
int i = 0; i < 6; ++i)
277 raw_ft_unordered(i) =
278 _comp_table.
compensate(temp_unordered(i), raw_ft_unordered(i));
280 const auto dt = std::chrono::high_resolution_clock::now() - st;
281 time_compensation_us = std::chrono::duration_cast<std::chrono::microseconds>(
dt).count();
284 if (_widget.radioButtonCompBeforeOffset->isChecked())
288 raw_ft_unordered -= _offset;
289 if (_widget.radioButtonCompAfterOffset->isChecked())
296 raw_ft[0] = raw_ft_unordered(_channel_order(0));
297 raw_ft[1] = raw_ft_unordered(_channel_order(1));
298 raw_ft[2] = raw_ft_unordered(_channel_order(2));
299 raw_ft[3] = raw_ft_unordered(_channel_order(3));
300 raw_ft[4] = raw_ft_unordered(_channel_order(4));
301 raw_ft[5] = raw_ft_unordered(_channel_order(5));
303 const Eigen::Vector6f ft = _conversion_matrix * (raw_ft * _ticks_to_volt_factor);
319 void FTSensorCalibrationGuiWidgetController::startRecording()
322 std::lock_guard g{_all_mutex};
323 _widget.pushButtonStart->setEnabled(
false);
324 _widget.pushButtonStop->setEnabled(
true);
326 const std::array field_adc_value =
328 _widget.comboBoxADC1Value->currentText().toStdString(),
329 _widget.comboBoxADC2Value->currentText().toStdString(),
330 _widget.comboBoxADC3Value->currentText().toStdString(),
331 _widget.comboBoxADC4Value->currentText().toStdString(),
332 _widget.comboBoxADC5Value->currentText().toStdString(),
333 _widget.comboBoxADC6Value->currentText().toStdString()
336 const std::array field_adc_temp =
338 _widget.comboBoxADC1Temp ->currentText().toStdString(),
339 _widget.comboBoxADC2Temp ->currentText().toStdString(),
340 _widget.comboBoxADC3Temp ->currentText().toStdString(),
341 _widget.comboBoxADC4Temp ->currentText().toStdString(),
342 _widget.comboBoxADC5Temp ->currentText().toStdString(),
343 _widget.comboBoxADC6Temp ->currentText().toStdString()
349 RobotUnitDataStreaming::Config cfg;
351 std::set<std::string> to_log;
353 to_log.emplace(field_adc_value.at(0));
354 to_log.emplace(field_adc_value.at(1));
355 to_log.emplace(field_adc_value.at(2));
356 to_log.emplace(field_adc_value.at(3));
357 to_log.emplace(field_adc_value.at(4));
358 to_log.emplace(field_adc_value.at(5));
360 to_log.emplace(field_adc_temp.at(0));
361 to_log.emplace(field_adc_temp.at(1));
362 to_log.emplace(field_adc_temp.at(2));
363 to_log.emplace(field_adc_temp.at(3));
364 to_log.emplace(field_adc_temp.at(4));
365 to_log.emplace(field_adc_temp.at(5));
370 const auto rns_name = _widget.comboBoxKinematicChain ->currentText().toStdString();
372 for (
const auto& name : _robot->getRobotNodeSet(rns_name)->getNodeNames())
374 auto dataf =
"sens." + name +
".position";
375 if (_all_logging_names.count(dataf))
377 to_log.emplace(std::move(dataf));
380 cfg.loggingNames.insert(cfg.loggingNames.end(), to_log.begin(), to_log.end());
382 make_shared<RobotUnitDataStreamingReceiver>(
this,
getRobotUnit(), cfg);
386 auto entries = _streaming_handler->getDataDescription().entries;
387 for (std::size_t i = 0; i < 6; ++i)
391 _adc.at(i) = entries.at(field_adc_value.at(i));
392 _adc_temp.at(i) = entries.at(field_adc_temp.at(i));
394 for (std::size_t i = 0; i < 6; ++i)
396 entries.erase(field_adc_value.at(i));
397 entries.erase(field_adc_temp.at(i));
401 if (path.has_parent_path())
403 std::filesystem::create_directories(path.parent_path());
406 _logfile.open(path.string());
407 _logfile <<
"iteration;timestamp;adc1;adc2;adc3;adc4;adc5;acd1_temp;acd2_temp;acd3_temp;acd4_temp;acd5_temp";
409 for (
const auto& [name, entry] : entries)
411 _joints.emplace_back(entry);
412 _logfile <<
';' << name;
414 _logfile << std::endl;
419 void FTSensorCalibrationGuiWidgetController::stopRecording()
422 std::lock_guard g{_all_mutex};
423 _widget.pushButtonStart->setEnabled(
true);
424 _widget.pushButtonStop->setEnabled(
false);
426 _streaming_handler =
nullptr;
427 _logfile = std::ofstream{};
433 #define option(type, fn) if constexpr(std::is_same_v<T, type>) { return str.fn() ; } else
438 option(qlonglong, toLongLong)
442 option(qulonglong, toULongLong)
445 static_assert(!std::is_same_v<float_t, float_t>,
"this function can't handle the given type");
453 val = str_to_val<T>(
str);
459 return str.isEmpty() ? opt : str_to_val<T>(
str);;
462 void read(
auto& eigen,
auto* table)
464 for (
int c = 0;
c < eigen.cols(); ++
c)
466 for (
int r = 0; r < eigen.rows(); ++r)
468 auto it = table->item(r,
c);
470 QString
str = it->text();
480 void FTSensorCalibrationGuiWidgetController::updateCalibration()
484 read(_conversion_matrix, _widget.tableWidgetMatrix);
485 read(_offset, _widget.tableWidgetOffset);
486 read(_channel_order, _widget.tableWidgetChannelOrder);
487 _ticks_to_volt_factor = _widget.doubleSpinBoxTickToVolt->value() *
488 std::pow(10.0, 1.0 * _widget.doubleSpinBoxTickToVoltE->value());
491 void FTSensorCalibrationGuiWidgetController::updateCompensation()
494 _comp_table.
table.clear();
495 const auto maxRows = _widget.tableWidgetCompensate->rowCount();
497 for (
int r = 0; r < maxRows; ++r)
499 const auto read_cell = [&](
int col)
501 auto it = _widget.tableWidgetCompensate->item(r, col);
505 const auto c0 = read_cell(0);
511 _comp_table.
table.emplace_back(std::array
513 str_to_val<float>(c0),
514 str_to_val_with_opt_on_empty<float>(read_cell(1), 0),
515 str_to_val_with_opt_on_empty<float>(read_cell(2), 0)
517 std::sort(_comp_table.
table.begin(), _comp_table.
table.end());
521 void FTSensorCalibrationGuiWidgetController::loadCalibFromFile()
527 void FTSensorCalibrationGuiWidgetController::loadDefaultArmar6FTR()
530 const auto set = [&](
auto tab,
auto row,
auto col,
auto str)
532 auto it = tab->item(row, col);
537 set(_widget.tableWidgetMatrix, 0, 0,
"-467.643251792");
538 set(_widget.tableWidgetMatrix, 0, 1,
"91.3750529228");
539 set(_widget.tableWidgetMatrix, 0, 2,
"2494.4447796887");
540 set(_widget.tableWidgetMatrix, 0, 3,
"-21630.9316531438");
541 set(_widget.tableWidgetMatrix, 0, 4,
"-2015.8633957692");
542 set(_widget.tableWidgetMatrix, 0, 5,
"21220.5317464812");
544 set(_widget.tableWidgetMatrix, 1, 0,
"-632.4535042867");
545 set(_widget.tableWidgetMatrix, 1, 1,
"26666.445463403");
546 set(_widget.tableWidgetMatrix, 1, 2,
"888.174687977");
547 set(_widget.tableWidgetMatrix, 1, 3,
"-12567.7138845759");
548 set(_widget.tableWidgetMatrix, 1, 4,
"2056.9631948303");
549 set(_widget.tableWidgetMatrix, 1, 5,
"-12362.9602817359");
551 set(_widget.tableWidgetMatrix, 2, 0,
"32117.1345018829");
552 set(_widget.tableWidgetMatrix, 2, 1,
"1042.3739547082");
553 set(_widget.tableWidgetMatrix, 2, 2,
"32619.3235489089");
554 set(_widget.tableWidgetMatrix, 2, 3,
"401.9862056573");
555 set(_widget.tableWidgetMatrix, 2, 4,
"32571.279999299");
556 set(_widget.tableWidgetMatrix, 2, 5,
"1238.1723510684");
558 set(_widget.tableWidgetMatrix, 3, 0,
"-7.9924072503");
559 set(_widget.tableWidgetMatrix, 3, 1,
"183.6989072793");
560 set(_widget.tableWidgetMatrix, 3, 2,
"-528.3700035934");
561 set(_widget.tableWidgetMatrix, 3, 3,
"-95.0326724598");
562 set(_widget.tableWidgetMatrix, 3, 4,
"529.7112223958");
563 set(_widget.tableWidgetMatrix, 3, 5,
"-67.4388404574");
565 set(_widget.tableWidgetMatrix, 4, 0,
"601.7174062086");
566 set(_widget.tableWidgetMatrix, 4, 1,
"19.2614267838");
567 set(_widget.tableWidgetMatrix, 4, 2,
"-343.4582260308");
568 set(_widget.tableWidgetMatrix, 4, 3,
"144.3830278106");
569 set(_widget.tableWidgetMatrix, 4, 4,
"-284.5086278763");
570 set(_widget.tableWidgetMatrix, 4, 5,
"-156.6756177634");
572 set(_widget.tableWidgetMatrix, 5, 0,
"6.7801800162");
573 set(_widget.tableWidgetMatrix, 5, 1,
"-339.2302595085");
574 set(_widget.tableWidgetMatrix, 5, 2,
"35.4255085497");
575 set(_widget.tableWidgetMatrix, 5, 3,
"-320.187165265");
576 set(_widget.tableWidgetMatrix, 5, 4,
"40.6862246688");
577 set(_widget.tableWidgetMatrix, 5, 5,
"-314.5800995414");
579 set(_widget.tableWidgetOffset, 0, 0,
"0");
580 set(_widget.tableWidgetOffset, 1, 0,
"0");
581 set(_widget.tableWidgetOffset, 2, 0,
"0");
582 set(_widget.tableWidgetOffset, 3, 0,
"0");
583 set(_widget.tableWidgetOffset, 4, 0,
"0");
584 set(_widget.tableWidgetOffset, 5, 0,
"0");
586 set(_widget.tableWidgetChannelOrder, 0, 0,
"0");
587 set(_widget.tableWidgetChannelOrder, 1, 0,
"1");
588 set(_widget.tableWidgetChannelOrder, 2, 0,
"2");
589 set(_widget.tableWidgetChannelOrder, 3, 0,
"3");
590 set(_widget.tableWidgetChannelOrder, 4, 0,
"4");
591 set(_widget.tableWidgetChannelOrder, 5, 0,
"5");
593 _widget.doubleSpinBoxTickToVolt->setValue(-7.275957614183426);
594 _widget.doubleSpinBoxTickToVoltE->setValue(-12);
597 void FTSensorCalibrationGuiWidgetController::loadDefaultArmar6FTL()
600 const auto set = [&](
auto tab,
auto row,
auto col,
auto str)
602 auto it = tab->item(row, col);
607 set(_widget.tableWidgetMatrix, 0, 0,
"243.0341527991");
608 set(_widget.tableWidgetMatrix, 0, 1,
"101.5053757216");
609 set(_widget.tableWidgetMatrix, 0, 2,
"3363.1141700153");
610 set(_widget.tableWidgetMatrix, 0, 3,
"-22042.8003987865");
611 set(_widget.tableWidgetMatrix, 0, 4,
"-1473.1343892481");
612 set(_widget.tableWidgetMatrix, 0, 5,
"22371.6116908654");
614 set(_widget.tableWidgetMatrix, 1, 0,
"-2855.7194248476");
615 set(_widget.tableWidgetMatrix, 1, 1,
"26276.7522410658");
616 set(_widget.tableWidgetMatrix, 1, 2,
"1998.8250953037");
617 set(_widget.tableWidgetMatrix, 1, 3,
"-12713.8569146837");
618 set(_widget.tableWidgetMatrix, 1, 4,
"298.7344647758");
619 set(_widget.tableWidgetMatrix, 1, 5,
"-12925.3451059361");
621 set(_widget.tableWidgetMatrix, 2, 0,
"32124.3594508476");
622 set(_widget.tableWidgetMatrix, 2, 1,
"1084.8849712208");
623 set(_widget.tableWidgetMatrix, 2, 2,
"32074.9427983169");
624 set(_widget.tableWidgetMatrix, 2, 3,
"1590.5268672115");
625 set(_widget.tableWidgetMatrix, 2, 4,
"31332.9720074452");
626 set(_widget.tableWidgetMatrix, 2, 5,
"1975.0541066964");
628 set(_widget.tableWidgetMatrix, 3, 0,
"-16.374713716");
629 set(_widget.tableWidgetMatrix, 3, 1,
"180.8318075047");
630 set(_widget.tableWidgetMatrix, 3, 2,
"-507.7906728024");
631 set(_widget.tableWidgetMatrix, 3, 3,
"-111.2589978068");
632 set(_widget.tableWidgetMatrix, 3, 4,
"503.7542430159");
633 set(_widget.tableWidgetMatrix, 3, 5,
"-59.7462546316");
635 set(_widget.tableWidgetMatrix, 4, 0,
"598.6997045889");
636 set(_widget.tableWidgetMatrix, 4, 1,
"15.4552761047");
637 set(_widget.tableWidgetMatrix, 4, 2,
"-323.6960410703");
638 set(_widget.tableWidgetMatrix, 4, 3,
"137.7987236203");
639 set(_widget.tableWidgetMatrix, 4, 4,
"-296.3155623038");
640 set(_widget.tableWidgetMatrix, 4, 5,
"-171.7206902305");
642 set(_widget.tableWidgetMatrix, 5, 0,
"49.6982738536");
643 set(_widget.tableWidgetMatrix, 5, 1,
"-335.3035629766");
644 set(_widget.tableWidgetMatrix, 5, 2,
"43.0493257519");
645 set(_widget.tableWidgetMatrix, 5, 3,
"-323.8948308006");
646 set(_widget.tableWidgetMatrix, 5, 4,
"15.3044378249");
647 set(_widget.tableWidgetMatrix, 5, 5,
"-329.7565028853");
649 set(_widget.tableWidgetOffset, 0, 0,
"0");
650 set(_widget.tableWidgetOffset, 1, 0,
"0");
651 set(_widget.tableWidgetOffset, 2, 0,
"0");
652 set(_widget.tableWidgetOffset, 3, 0,
"0");
653 set(_widget.tableWidgetOffset, 4, 0,
"0");
654 set(_widget.tableWidgetOffset, 5, 0,
"0");
656 set(_widget.tableWidgetChannelOrder, 0, 0,
"0");
657 set(_widget.tableWidgetChannelOrder, 1, 0,
"1");
658 set(_widget.tableWidgetChannelOrder, 2, 0,
"2");
659 set(_widget.tableWidgetChannelOrder, 3, 0,
"3");
660 set(_widget.tableWidgetChannelOrder, 4, 0,
"4");
661 set(_widget.tableWidgetChannelOrder, 5, 0,
"5");
663 _widget.doubleSpinBoxTickToVolt->setValue(-7.275957614183426);
664 _widget.doubleSpinBoxTickToVoltE->setValue(-12);