28 #include <VirtualRobot/RobotNodeSet.h>
40 std::lock_guard g{_all_mutex};
42 settings->value(
"rsc",
"Armar6StateComponent").toString().toStdString());
44 settings->value(
"ru",
"Armar6Unit").toString().toStdString());
46 settings->value(
"dbgo",
"DebugObserver").toString().toStdString());
53 std::lock_guard g{_all_mutex};
68 std::lock_guard g{_all_mutex};
74 "rsc",
"Robot State Component",
"*Component");
75 _dialog->addLineEdit(
"dbgo",
"DebugObserver Topic",
"DebugObserver");
77 return qobject_cast<SimpleConfigDialog*>(_dialog);
84 std::lock_guard g{_all_mutex};
98 _widget.pushButtonLoadCalibFromFile->setVisible(
false);
99 connect(_widget.pushButtonLoadCalibFromFile,
100 &QPushButton::clicked,
102 &FTSensorCalibrationGuiWidgetController::loadCalibFromFile);
103 connect(_widget.pushButtonStart,
104 &QPushButton::clicked,
106 &FTSensorCalibrationGuiWidgetController::startRecording);
107 connect(_widget.pushButtonStop,
108 &QPushButton::clicked,
110 &FTSensorCalibrationGuiWidgetController::stopRecording);
111 connect(_widget.pushButtonLoadDefaultArmar6FTL,
112 &QPushButton::clicked,
114 &FTSensorCalibrationGuiWidgetController::loadDefaultArmar6FTL);
115 connect(_widget.pushButtonLoadDefaultArmar6FTR,
116 &QPushButton::clicked,
118 &FTSensorCalibrationGuiWidgetController::loadDefaultArmar6FTR);
120 connect(_widget.tableWidgetOffset,
121 &QTableWidget::itemChanged,
123 &FTSensorCalibrationGuiWidgetController::updateCalibration);
124 connect(_widget.tableWidgetOffset,
125 &QTableWidget::itemChanged,
127 &FTSensorCalibrationGuiWidgetController::updateCalibration);
128 connect(_widget.tableWidgetChannelOrder,
129 &QTableWidget::itemChanged,
131 &FTSensorCalibrationGuiWidgetController::updateCalibration);
132 connect(_widget.doubleSpinBoxTickToVolt,
133 qOverload<double>(&QDoubleSpinBox::valueChanged),
135 &FTSensorCalibrationGuiWidgetController::updateCalibration);
136 connect(_widget.doubleSpinBoxTickToVoltE,
137 qOverload<int>(&QSpinBox::valueChanged),
139 &FTSensorCalibrationGuiWidgetController::updateCalibration);
141 connect(_widget.tableWidgetCompensate,
142 &QTableWidget::itemChanged,
144 &FTSensorCalibrationGuiWidgetController::updateCompensation);
146 loadDefaultArmar6FTR();
158 std::lock_guard g{_all_mutex};
159 _robot =
addOrGetRobot(
"r", VirtualRobot::RobotIO::RobotDescription::eStructure);
166 std::lock_guard g{_all_mutex};
168 _comboboxes_are_set_up =
false;
176 std::lock_guard g{_all_mutex};
179 _widget.widgetFields->setEnabled(
false);
182 const auto to_list = [](
const auto& container)
185 for (
const auto& name : container)
187 qnames << QString::fromStdString(name);
191 if (!_comboboxes_are_set_up)
195 _all_logging_names = std::set<std::string>(vec.begin(), vec.end());
197 const auto qnames = to_list(_all_logging_names);
198 const auto setup = [&](
auto box,
const auto& lst,
auto regex)
202 const auto idx = lst.indexOf(QRegExp{regex});
205 box->setCurrentIndex(idx);
208 setup(_widget.comboBoxADC1Value, qnames, R
"(^sens\.FT R\.adc_raw_1_to_3\.x$)");
209 setup(_widget.comboBoxADC2Value, qnames, R"(^sens\.FT R\.adc_raw_1_to_3\.y$)");
210 setup(_widget.comboBoxADC3Value, qnames, R"(^sens\.FT R\.adc_raw_1_to_3\.z$)");
211 setup(_widget.comboBoxADC4Value, qnames, R"(^sens\.FT R\.adc_raw_4_to_6\.x$)");
212 setup(_widget.comboBoxADC5Value, qnames, R"(^sens\.FT R\.adc_raw_4_to_6\.y$)");
213 setup(_widget.comboBoxADC6Value, qnames, R"(^sens\.FT R\.adc_raw_4_to_6\.z$)");
215 setup(_widget.comboBoxADC1Temp, qnames, R"(^sens\.FT R\.adc_1_to_3_temperature$)");
216 setup(_widget.comboBoxADC2Temp, qnames, R"(^sens\.FT R\.adc_1_to_3_temperature$)");
217 setup(_widget.comboBoxADC3Temp, qnames, R"(^sens\.FT R\.adc_1_to_3_temperature$)");
218 setup(_widget.comboBoxADC4Temp, qnames, R"(^sens\.FT R\.adc_4_to_6_temperature$)");
219 setup(_widget.comboBoxADC5Temp, qnames, R"(^sens\.FT R\.adc_4_to_6_temperature$)");
220 setup(_widget.comboBoxADC6Temp, qnames, R"(^sens\.FT R\.adc_4_to_6_temperature$)");
223 _widget.comboBoxKinematicChain, to_list(_robot->getRobotNodeSetNames()), "^Robot$");
225 _widget.pushButtonStart->setEnabled(
true);
226 _widget.widgetFields->setEnabled(
true);
227 _comboboxes_are_set_up =
true;
231 _widget.comboBoxADC1Value->setEnabled(!_recording);
232 _widget.comboBoxADC2Value->setEnabled(!_recording);
233 _widget.comboBoxADC3Value->setEnabled(!_recording);
234 _widget.comboBoxADC4Value->setEnabled(!_recording);
235 _widget.comboBoxADC5Value->setEnabled(!_recording);
236 _widget.comboBoxADC6Value->setEnabled(!_recording);
238 _widget.comboBoxADC1Temp->setEnabled(!_recording);
239 _widget.comboBoxADC2Temp->setEnabled(!_recording);
240 _widget.comboBoxADC3Temp->setEnabled(!_recording);
241 _widget.comboBoxADC4Temp->setEnabled(!_recording);
242 _widget.comboBoxADC5Temp->setEnabled(!_recording);
243 _widget.comboBoxADC6Temp->setEnabled(!_recording);
252 auto&
data = _streaming_handler->getDataBuffer();
254 long time_compensation_us = 0;
257 const auto log = [&](
auto n) { _logfile <<
';' << n; };
258 for (
const auto&
s :
data)
260 _logfile <<
s.iterationId <<
';' <<
s.timestampUSec;
267 std::vector<float> vals;
269 const auto& last =
data.back();
270 const auto pback = [&](
auto n) { vals.emplace_back(n); };
277 raw_ft_unordered[0] = vals.at(0);
278 raw_ft_unordered[1] = vals.at(1);
279 raw_ft_unordered[2] = vals.at(2);
280 raw_ft_unordered[3] = vals.at(3);
281 raw_ft_unordered[4] = vals.at(4);
282 raw_ft_unordered[5] = vals.at(5);
285 temp_unordered[0] = vals.at(6 + 0);
286 temp_unordered[1] = vals.at(6 + 1);
287 temp_unordered[2] = vals.at(6 + 2);
288 temp_unordered[3] = vals.at(6 + 3);
289 temp_unordered[4] = vals.at(6 + 4);
290 temp_unordered[5] = vals.at(6 + 5);
292 _widget.labelADC1Value->setText(QString::number(raw_ft_unordered(0)));
293 _widget.labelADC2Value->setText(QString::number(raw_ft_unordered(1)));
294 _widget.labelADC3Value->setText(QString::number(raw_ft_unordered(2)));
295 _widget.labelADC4Value->setText(QString::number(raw_ft_unordered(3)));
296 _widget.labelADC5Value->setText(QString::number(raw_ft_unordered(4)));
297 _widget.labelADC6Value->setText(QString::number(raw_ft_unordered(5)));
299 _widget.labelADC1Temp->setText(QString::number(temp_unordered(0)));
300 _widget.labelADC2Temp->setText(QString::number(temp_unordered(1)));
301 _widget.labelADC3Temp->setText(QString::number(temp_unordered(2)));
302 _widget.labelADC4Temp->setText(QString::number(temp_unordered(3)));
303 _widget.labelADC5Temp->setText(QString::number(temp_unordered(4)));
304 _widget.labelADC6Temp->setText(QString::number(temp_unordered(5)));
306 const auto do_compensation = [&]
308 const auto st = std::chrono::high_resolution_clock::now();
309 for (
int i = 0; i < 6; ++i)
311 raw_ft_unordered(i) =
312 _comp_table.
compensate(temp_unordered(i), raw_ft_unordered(i));
314 const auto dt = std::chrono::high_resolution_clock::now() - st;
315 time_compensation_us =
316 std::chrono::duration_cast<std::chrono::microseconds>(
dt).count();
319 if (_widget.radioButtonCompBeforeOffset->isChecked())
323 raw_ft_unordered -= _offset;
324 if (_widget.radioButtonCompAfterOffset->isChecked())
331 raw_ft[0] = raw_ft_unordered(_channel_order(0));
332 raw_ft[1] = raw_ft_unordered(_channel_order(1));
333 raw_ft[2] = raw_ft_unordered(_channel_order(2));
334 raw_ft[3] = raw_ft_unordered(_channel_order(3));
335 raw_ft[4] = raw_ft_unordered(_channel_order(4));
336 raw_ft[5] = raw_ft_unordered(_channel_order(5));
338 const Eigen::Vector6f ft = _conversion_matrix * (raw_ft * _ticks_to_volt_factor);
355 FTSensorCalibrationGuiWidgetController::startRecording()
358 std::lock_guard g{_all_mutex};
359 _widget.pushButtonStart->setEnabled(
false);
360 _widget.pushButtonStop->setEnabled(
true);
362 const std::array field_adc_value = {_widget.comboBoxADC1Value->currentText().toStdString(),
363 _widget.comboBoxADC2Value->currentText().toStdString(),
364 _widget.comboBoxADC3Value->currentText().toStdString(),
365 _widget.comboBoxADC4Value->currentText().toStdString(),
366 _widget.comboBoxADC5Value->currentText().toStdString(),
367 _widget.comboBoxADC6Value->currentText().toStdString()};
369 const std::array field_adc_temp = {_widget.comboBoxADC1Temp->currentText().toStdString(),
370 _widget.comboBoxADC2Temp->currentText().toStdString(),
371 _widget.comboBoxADC3Temp->currentText().toStdString(),
372 _widget.comboBoxADC4Temp->currentText().toStdString(),
373 _widget.comboBoxADC5Temp->currentText().toStdString(),
374 _widget.comboBoxADC6Temp->currentText().toStdString()};
379 RobotUnitDataStreaming::Config cfg;
381 std::set<std::string> to_log;
383 to_log.emplace(field_adc_value.at(0));
384 to_log.emplace(field_adc_value.at(1));
385 to_log.emplace(field_adc_value.at(2));
386 to_log.emplace(field_adc_value.at(3));
387 to_log.emplace(field_adc_value.at(4));
388 to_log.emplace(field_adc_value.at(5));
390 to_log.emplace(field_adc_temp.at(0));
391 to_log.emplace(field_adc_temp.at(1));
392 to_log.emplace(field_adc_temp.at(2));
393 to_log.emplace(field_adc_temp.at(3));
394 to_log.emplace(field_adc_temp.at(4));
395 to_log.emplace(field_adc_temp.at(5));
400 const auto rns_name = _widget.comboBoxKinematicChain->currentText().toStdString();
402 for (
const auto& name : _robot->getRobotNodeSet(rns_name)->getNodeNames())
404 auto dataf =
"sens." + name +
".position";
405 if (_all_logging_names.count(dataf))
407 to_log.emplace(std::move(dataf));
410 cfg.loggingNames.insert(cfg.loggingNames.end(), to_log.begin(), to_log.end());
412 make_shared<RobotUnitDataStreamingReceiver>(
this,
getRobotUnit(), cfg);
416 auto entries = _streaming_handler->getDataDescription().entries;
417 for (std::size_t i = 0; i < 6; ++i)
420 <<
VAROUT(field_adc_value.at(i));
422 <<
VAROUT(field_adc_temp.at(i));
423 _adc.at(i) = entries.at(field_adc_value.at(i));
424 _adc_temp.at(i) = entries.at(field_adc_temp.at(i));
426 for (std::size_t i = 0; i < 6; ++i)
428 entries.erase(field_adc_value.at(i));
429 entries.erase(field_adc_temp.at(i));
432 const std::filesystem::path path =
434 _widget.lineEditLogFile->text().toStdString());
435 if (path.has_parent_path())
437 std::filesystem::create_directories(path.parent_path());
440 _logfile.open(path.string());
441 _logfile <<
"iteration;timestamp;adc1;adc2;adc3;adc4;adc5;acd1_temp;acd2_temp;acd3_"
442 "temp;acd4_temp;acd5_temp";
444 for (
const auto& [name, entry] : entries)
446 _joints.emplace_back(entry);
447 _logfile <<
';' << name;
449 _logfile << std::endl;
456 FTSensorCalibrationGuiWidgetController::stopRecording()
459 std::lock_guard g{_all_mutex};
460 _widget.pushButtonStart->setEnabled(
true);
461 _widget.pushButtonStop->setEnabled(
false);
463 _streaming_handler =
nullptr;
464 _logfile = std::ofstream{};
471 #define option(type, fn) \
472 if constexpr (std::is_same_v<T, type>) \
481 static_assert(!std::is_same_v<float_t, float_t>,
482 "this function can't handle the given type");
491 val = str_to_val<T>(
str);
498 return str.isEmpty() ? opt : str_to_val<T>(
str);
505 for (
int c = 0;
c < eigen.cols(); ++
c)
507 for (
int r = 0; r < eigen.rows(); ++r)
509 auto it = table->item(r,
c);
511 QString
str = it->text();
522 FTSensorCalibrationGuiWidgetController::updateCalibration()
526 read(_conversion_matrix, _widget.tableWidgetMatrix);
527 read(_offset, _widget.tableWidgetOffset);
528 read(_channel_order, _widget.tableWidgetChannelOrder);
529 _ticks_to_volt_factor = _widget.doubleSpinBoxTickToVolt->value() *
530 std::pow(10.0, 1.0 * _widget.doubleSpinBoxTickToVoltE->value());
534 FTSensorCalibrationGuiWidgetController::updateCompensation()
537 _comp_table.
table.clear();
538 const auto maxRows = _widget.tableWidgetCompensate->rowCount();
540 for (
int r = 0; r < maxRows; ++r)
542 const auto read_cell = [&](
int col)
544 auto it = _widget.tableWidgetCompensate->item(r, col);
548 const auto c0 = read_cell(0);
554 _comp_table.
table.emplace_back(
555 std::array{str_to_val<float>(c0),
556 str_to_val_with_opt_on_empty<float>(read_cell(1), 0),
557 str_to_val_with_opt_on_empty<float>(read_cell(2), 0)});
558 std::sort(_comp_table.
table.begin(), _comp_table.
table.end());
563 FTSensorCalibrationGuiWidgetController::loadCalibFromFile()
569 FTSensorCalibrationGuiWidgetController::loadDefaultArmar6FTR()
572 const auto set = [&](
auto tab,
auto row,
auto col,
auto str)
574 auto it = tab->item(row, col);
579 set(_widget.tableWidgetMatrix, 0, 0,
"-467.643251792");
580 set(_widget.tableWidgetMatrix, 0, 1,
"91.3750529228");
581 set(_widget.tableWidgetMatrix, 0, 2,
"2494.4447796887");
582 set(_widget.tableWidgetMatrix, 0, 3,
"-21630.9316531438");
583 set(_widget.tableWidgetMatrix, 0, 4,
"-2015.8633957692");
584 set(_widget.tableWidgetMatrix, 0, 5,
"21220.5317464812");
586 set(_widget.tableWidgetMatrix, 1, 0,
"-632.4535042867");
587 set(_widget.tableWidgetMatrix, 1, 1,
"26666.445463403");
588 set(_widget.tableWidgetMatrix, 1, 2,
"888.174687977");
589 set(_widget.tableWidgetMatrix, 1, 3,
"-12567.7138845759");
590 set(_widget.tableWidgetMatrix, 1, 4,
"2056.9631948303");
591 set(_widget.tableWidgetMatrix, 1, 5,
"-12362.9602817359");
593 set(_widget.tableWidgetMatrix, 2, 0,
"32117.1345018829");
594 set(_widget.tableWidgetMatrix, 2, 1,
"1042.3739547082");
595 set(_widget.tableWidgetMatrix, 2, 2,
"32619.3235489089");
596 set(_widget.tableWidgetMatrix, 2, 3,
"401.9862056573");
597 set(_widget.tableWidgetMatrix, 2, 4,
"32571.279999299");
598 set(_widget.tableWidgetMatrix, 2, 5,
"1238.1723510684");
600 set(_widget.tableWidgetMatrix, 3, 0,
"-7.9924072503");
601 set(_widget.tableWidgetMatrix, 3, 1,
"183.6989072793");
602 set(_widget.tableWidgetMatrix, 3, 2,
"-528.3700035934");
603 set(_widget.tableWidgetMatrix, 3, 3,
"-95.0326724598");
604 set(_widget.tableWidgetMatrix, 3, 4,
"529.7112223958");
605 set(_widget.tableWidgetMatrix, 3, 5,
"-67.4388404574");
607 set(_widget.tableWidgetMatrix, 4, 0,
"601.7174062086");
608 set(_widget.tableWidgetMatrix, 4, 1,
"19.2614267838");
609 set(_widget.tableWidgetMatrix, 4, 2,
"-343.4582260308");
610 set(_widget.tableWidgetMatrix, 4, 3,
"144.3830278106");
611 set(_widget.tableWidgetMatrix, 4, 4,
"-284.5086278763");
612 set(_widget.tableWidgetMatrix, 4, 5,
"-156.6756177634");
614 set(_widget.tableWidgetMatrix, 5, 0,
"6.7801800162");
615 set(_widget.tableWidgetMatrix, 5, 1,
"-339.2302595085");
616 set(_widget.tableWidgetMatrix, 5, 2,
"35.4255085497");
617 set(_widget.tableWidgetMatrix, 5, 3,
"-320.187165265");
618 set(_widget.tableWidgetMatrix, 5, 4,
"40.6862246688");
619 set(_widget.tableWidgetMatrix, 5, 5,
"-314.5800995414");
621 set(_widget.tableWidgetOffset, 0, 0,
"0");
622 set(_widget.tableWidgetOffset, 1, 0,
"0");
623 set(_widget.tableWidgetOffset, 2, 0,
"0");
624 set(_widget.tableWidgetOffset, 3, 0,
"0");
625 set(_widget.tableWidgetOffset, 4, 0,
"0");
626 set(_widget.tableWidgetOffset, 5, 0,
"0");
628 set(_widget.tableWidgetChannelOrder, 0, 0,
"0");
629 set(_widget.tableWidgetChannelOrder, 1, 0,
"1");
630 set(_widget.tableWidgetChannelOrder, 2, 0,
"2");
631 set(_widget.tableWidgetChannelOrder, 3, 0,
"3");
632 set(_widget.tableWidgetChannelOrder, 4, 0,
"4");
633 set(_widget.tableWidgetChannelOrder, 5, 0,
"5");
635 _widget.doubleSpinBoxTickToVolt->setValue(-7.275957614183426);
636 _widget.doubleSpinBoxTickToVoltE->setValue(-12);
640 FTSensorCalibrationGuiWidgetController::loadDefaultArmar6FTL()
643 const auto set = [&](
auto tab,
auto row,
auto col,
auto str)
645 auto it = tab->item(row, col);
650 set(_widget.tableWidgetMatrix, 0, 0,
"243.0341527991");
651 set(_widget.tableWidgetMatrix, 0, 1,
"101.5053757216");
652 set(_widget.tableWidgetMatrix, 0, 2,
"3363.1141700153");
653 set(_widget.tableWidgetMatrix, 0, 3,
"-22042.8003987865");
654 set(_widget.tableWidgetMatrix, 0, 4,
"-1473.1343892481");
655 set(_widget.tableWidgetMatrix, 0, 5,
"22371.6116908654");
657 set(_widget.tableWidgetMatrix, 1, 0,
"-2855.7194248476");
658 set(_widget.tableWidgetMatrix, 1, 1,
"26276.7522410658");
659 set(_widget.tableWidgetMatrix, 1, 2,
"1998.8250953037");
660 set(_widget.tableWidgetMatrix, 1, 3,
"-12713.8569146837");
661 set(_widget.tableWidgetMatrix, 1, 4,
"298.7344647758");
662 set(_widget.tableWidgetMatrix, 1, 5,
"-12925.3451059361");
664 set(_widget.tableWidgetMatrix, 2, 0,
"32124.3594508476");
665 set(_widget.tableWidgetMatrix, 2, 1,
"1084.8849712208");
666 set(_widget.tableWidgetMatrix, 2, 2,
"32074.9427983169");
667 set(_widget.tableWidgetMatrix, 2, 3,
"1590.5268672115");
668 set(_widget.tableWidgetMatrix, 2, 4,
"31332.9720074452");
669 set(_widget.tableWidgetMatrix, 2, 5,
"1975.0541066964");
671 set(_widget.tableWidgetMatrix, 3, 0,
"-16.374713716");
672 set(_widget.tableWidgetMatrix, 3, 1,
"180.8318075047");
673 set(_widget.tableWidgetMatrix, 3, 2,
"-507.7906728024");
674 set(_widget.tableWidgetMatrix, 3, 3,
"-111.2589978068");
675 set(_widget.tableWidgetMatrix, 3, 4,
"503.7542430159");
676 set(_widget.tableWidgetMatrix, 3, 5,
"-59.7462546316");
678 set(_widget.tableWidgetMatrix, 4, 0,
"598.6997045889");
679 set(_widget.tableWidgetMatrix, 4, 1,
"15.4552761047");
680 set(_widget.tableWidgetMatrix, 4, 2,
"-323.6960410703");
681 set(_widget.tableWidgetMatrix, 4, 3,
"137.7987236203");
682 set(_widget.tableWidgetMatrix, 4, 4,
"-296.3155623038");
683 set(_widget.tableWidgetMatrix, 4, 5,
"-171.7206902305");
685 set(_widget.tableWidgetMatrix, 5, 0,
"49.6982738536");
686 set(_widget.tableWidgetMatrix, 5, 1,
"-335.3035629766");
687 set(_widget.tableWidgetMatrix, 5, 2,
"43.0493257519");
688 set(_widget.tableWidgetMatrix, 5, 3,
"-323.8948308006");
689 set(_widget.tableWidgetMatrix, 5, 4,
"15.3044378249");
690 set(_widget.tableWidgetMatrix, 5, 5,
"-329.7565028853");
692 set(_widget.tableWidgetOffset, 0, 0,
"0");
693 set(_widget.tableWidgetOffset, 1, 0,
"0");
694 set(_widget.tableWidgetOffset, 2, 0,
"0");
695 set(_widget.tableWidgetOffset, 3, 0,
"0");
696 set(_widget.tableWidgetOffset, 4, 0,
"0");
697 set(_widget.tableWidgetOffset, 5, 0,
"0");
699 set(_widget.tableWidgetChannelOrder, 0, 0,
"0");
700 set(_widget.tableWidgetChannelOrder, 1, 0,
"1");
701 set(_widget.tableWidgetChannelOrder, 2, 0,
"2");
702 set(_widget.tableWidgetChannelOrder, 3, 0,
"3");
703 set(_widget.tableWidgetChannelOrder, 4, 0,
"4");
704 set(_widget.tableWidgetChannelOrder, 5, 0,
"5");
706 _widget.doubleSpinBoxTickToVolt->setValue(-7.275957614183426);
707 _widget.doubleSpinBoxTickToVoltE->setValue(-12);