472 const std::string& controllerType,
473 const ::armarx::aron::data::dto::DictPtr& configDict,
474 const std::string& configFilename,
480 ARMARX_INFO <<
"creating controller of type " << controllerType;
482 std::string controllerName;
493 namePrefix, configDict, configFilename, activate, allowReuse, cfgFromMemory);
497 namePrefix, configDict, configFilename, activate, allowReuse, cfgFromMemory);
501 namePrefix, configDict, configFilename, activate, allowReuse, cfgFromMemory);
507 case T::TSMixImpVelCol:
509 namePrefix, configDict, configFilename, activate, allowReuse, cfgFromMemory);
513 namePrefix, configDict, configFilename, activate, allowReuse, cfgFromMemory);
517 namePrefix, configDict, configFilename, activate, allowReuse, cfgFromMemory);
521 namePrefix, configDict, configFilename, activate, allowReuse, cfgFromMemory);
525 namePrefix, configDict, configFilename, activate, allowReuse, cfgFromMemory);
530 namePrefix, configDict, configFilename, activate, allowReuse, cfgFromMemory);
534 namePrefix, configDict, configFilename, activate, allowReuse, cfgFromMemory);
538 namePrefix, configDict, configFilename, activate, allowReuse, cfgFromMemory);
544 case T::TSMPMixImpVel:
546 namePrefix, configDict, configFilename, activate, allowReuse, cfgFromMemory);
550 namePrefix, configDict, configFilename, activate, allowReuse, cfgFromMemory);
554 namePrefix, configDict, configFilename, activate, allowReuse, cfgFromMemory);
558 namePrefix, configDict, configFilename, activate, allowReuse, cfgFromMemory);
560 case T::TSMPMixImpVelCol:
562 namePrefix, configDict, configFilename, activate, allowReuse, cfgFromMemory);
564 case T::TSMPMixImpVelColWiping:
566 namePrefix, configDict, configFilename, activate, allowReuse, cfgFromMemory);
568 case T::TSMPVelWiping:
570 namePrefix, configDict, configFilename, activate, allowReuse, cfgFromMemory);
576 case T::TSMPImpWiping:
578 namePrefix, configDict, configFilename, activate, allowReuse, cfgFromMemory);
585 namePrefix, configDict, configFilename, activate, allowReuse, cfgFromMemory);
589 namePrefix, configDict, configFilename, activate, allowReuse, cfgFromMemory);
591 case T::ZMQTSMixImpVelCol:
593 namePrefix, configDict, configFilename, activate, allowReuse, cfgFromMemory);
595 case T::ZMQTSMixImpVel:
597 namePrefix, configDict, configFilename, activate, allowReuse, cfgFromMemory);
601 namePrefix, configDict, configFilename, activate, allowReuse, cfgFromMemory);
607 namePrefix, configDict, configFilename, activate, allowReuse, cfgFromMemory);
609 case T::ZenohTSImpCol:
611 namePrefix, configDict, configFilename, activate, allowReuse, cfgFromMemory);
613 case T::ZenohTSMixImpVelCol:
615 namePrefix, configDict, configFilename, activate, allowReuse, cfgFromMemory);
617 case T::ZenohTSMixImpVel:
619 namePrefix, configDict, configFilename, activate, allowReuse, cfgFromMemory);
623 namePrefix, configDict, configFilename, activate, allowReuse, cfgFromMemory);
626 ARMARX_ERROR <<
"controller type: " << controllerType <<
" is not supported yet";
628 return controllerName;
730 const std::string& side,
731 const std::string& fileName,
732 const std::string& nameSuffix,
736 ARMARX_INFO <<
"Kinesthetic teaching: Initialize zero torque controllers for "
737 <<
VAROUT(kinematicChainName);
738 const std::string ctrl_class_name =
"NJointZeroTorqueController";
739 const std::string ctrl_name =
"kinesthetic_teaching_" + ctrl_class_name +
"_" + nameSuffix;
743 if (kinematicChainName ==
"RightArm" || kinematicChainName ==
"RightArmWithoutWrist")
748 auto& robotReader = virtualRobotReader_->get();
752 robotReader, properties.robotName, hand);
758 NJointZeroTorqueControllerConfigPtr config(
new NJointZeroTorqueControllerConfig());
759 config->maxTorque = 0;
761 auto nodeSet = m_robot->getRobotNodeSet(kinematicChainName);
762 for (
auto& name : nodeSet->getNodeNames())
764 config->jointNames.push_back(name);
766 NJointZeroTorqueControllerInterfacePrx zeroTorqueController =
767 NJointZeroTorqueControllerInterfacePrx::checkedCast(
768 m_robot_unit->createNJointController(ctrl_class_name, ctrl_name, config));
772 float motionThresholdRadian = 0.1f;
773 float noMotionTimeoutMs = 2000.0f;
775 VirtualRobot::RobotNodeSetPtr rns = m_robot->getRobotNodeSet(kinematicChainName);
776 std::vector<std::string> jointNames = rns->getNodeNames();
778 IceUtil::Time lastMotionTime = start;
779 bool initialMotionDetected =
false;
783 std::vector<std::vector<float>> jointData;
784 std::vector<std::vector<float>> cartData;
785 std::vector<float> timestamps;
788 Eigen::VectorXf jve = rns->getJointValuesEigen();
789 Eigen::Matrix4f initPose = rns->getTCP()->getPoseInRootFrame();
790 VirtualRobot::MathTools::Quaternion initQuat =
791 VirtualRobot::MathTools::eigen4f2quat(initPose);
792 VirtualRobot::MathTools::Quaternion oldquatE = initQuat;
795 for (
size_t i = 0; i < jointNames.size(); i++)
797 std::vector<float> cjoint{};
799 jointData.push_back(cjoint);
804 for (
size_t i = 0; i < 7; ++i)
806 std::vector<float> cpos{};
808 cartData.push_back(cpos);
812 int motionStartIndex = 0;
813 int motionEndIndex = 0;
848 zeroTorqueController->activateController();
855 Eigen::VectorXf jve2 = rns->getJointValuesEigen();
856 if ((jve2 - jve).
norm() > motionThresholdRadian)
858 if (!initialMotionDetected)
861 motionStartIndex = 0;
865 initialMotionDetected =
true;
866 lastMotionTime = now;
869 double t = (now - start).toSecondsDouble();
871 std::vector<float> jvs = rns->getJointValues();
872 for (
size_t i = 0; i < jvs.size(); i++)
874 jointData.at(i).push_back(jvs.at(i));
877 Eigen::Matrix4f tcpPose = rns->getTCP()->getPoseInRootFrame();
878 cartData.at(0).push_back(tcpPose(0, 3));
879 cartData.at(1).push_back(tcpPose(1, 3));
880 cartData.at(2).push_back(tcpPose(2, 3));
881 VirtualRobot::MathTools::Quaternion quat =
882 VirtualRobot::MathTools::eigen4f2quat(tcpPose);
885 double dotProduct = quat.w * oldquatE.w + quat.x * oldquatE.x + quat.y * oldquatE.y +
889 cartData.at(3).push_back(-quat.w);
890 cartData.at(4).push_back(-quat.x);
891 cartData.at(5).push_back(-quat.y);
892 cartData.at(6).push_back(-quat.z);
893 oldquatE.w = -quat.w;
894 oldquatE.x = -quat.x;
895 oldquatE.y = -quat.y;
896 oldquatE.z = -quat.z;
900 cartData.at(3).push_back(quat.w);
901 cartData.at(4).push_back(quat.x);
902 cartData.at(5).push_back(quat.y);
903 cartData.at(6).push_back(quat.z);
911 timestamps.push_back(t);
913 if (initialMotionDetected &&
914 (now - lastMotionTime).toMilliSeconds() > noMotionTimeoutMs)
917 motionEndIndex = timestamps.size();
925 zeroTorqueController->deactivateController();
926 while (zeroTorqueController->isControllerActive())
930 zeroTorqueController->deleteController();
931 ARMARX_INFO <<
"zerotorque controller for kinesthetic teaching is deleteded";
934 motionStartIndex -= sigmaMs / sampleMs * 2;
935 if (motionStartIndex < 0)
937 motionStartIndex = 0;
948 timestamps = std::vector<float>(timestamps.begin() + motionStartIndex,
949 timestamps.begin() + motionEndIndex);
950 for (
size_t n = 1; n < timestamps.size(); n++)
952 timestamps.at(n) = timestamps.at(n) - timestamps.at(0);
954 timestamps.at(0) = 0;
958 timestamps.at(0), timestamps.at(timestamps.size() - 1), timestamps.size());
962 StringFloatSeqDict plotFiltered;
963 StringFloatSeqDict plotOrig;
964 StringFloatSeqDict plotResampled;
965 for (
size_t i = 0; i < jointData.size(); i++)
967 jointData.at(i) = std::vector<float>(jointData.at(i).begin() + motionStartIndex,
968 jointData.at(i).begin() + motionEndIndex);
969 if (rns->getNode(i)->isLimitless())
973 plotOrig[jointNames.at(i)] = jointData.at(i);
976 plotResampled[jointNames.at(i)] = jointData.at(i);
982 plotFiltered[jointNames.at(i)] = jointData.at(i);
989 std::vector<std::string> cartName = {
"x",
"y",
"z",
"qw",
"qx",
"qy",
"qz"};
993 std::string trajName;
995 IceUtil::Time now = IceUtil::Time::now();
996 time_t timer = now.toSeconds();
999 ts = localtime(&timer);
1000 strftime(buffer, 80,
"%Y-%m-%d-%H-%M-%S", ts);
1001 std::string
str(buffer);
1002 trajName = fileName +
"-" +
str;
1006 double cutoutTime = (noMotionTimeoutMs / 1000.0f) * 0.8;
1008 std::string packageName =
"armarx_control";
1011 std::string dataDir = finder.
getDataDir() +
"/" + packageName +
"/kinesthetic_teaching/";
1012 std::string returnFileNamePattern = dataDir + trajName;
1016 std::string dmpForwardFile;
1017 std::string dmpBackwardFile;
1019 std::vector<std::string> header;
1020 header.push_back(
"timestamp");
1021 for (
size_t i = 0; i < cartName.size(); ++i)
1023 header.push_back(cartName.at(i));
1026 std::string ffname = trajName +
"-ts-forward.csv";
1027 std::string bfname = trajName +
"-ts-backward.csv";
1028 dmpForwardFile = dataDir + ffname;
1029 dmpBackwardFile = dataDir + bfname;
1030 std::vector<std::string> fflist;
1031 fflist.push_back(ffname);
1033 std::vector<std::string> bflist;
1034 bflist.push_back(bfname);
1036 CsvWriter fwriter(dmpForwardFile, header,
false);
1037 CsvWriter bwriter(dmpBackwardFile, header,
false);
1039 ARMARX_IMPORTANT <<
"writing taskspace trajectory as " << ffname <<
" and " << bfname;
1041 double endTime = timestamps.at(timestamps.size() - 1);
1042 for (
size_t n = 0; n < timestamps.size(); n++)
1045 std::vector<float> row;
1046 row.push_back(timestamps.at(n));
1047 for (
size_t i = 0; i < cartData.size(); i++)
1049 row.push_back(cartData.at(i).at(n));
1053 if (endTime - timestamps.at(n) < cutoutTime)
1055 Eigen::Matrix4f endPose = VirtualRobot::MathTools::quat2eigen4f(
1056 row.at(5), row.at(6), row.at(7), row.at(4));
1057 endPose(0, 3) = row.at(1);
1058 endPose(1, 3) = row.at(2);
1059 endPose(2, 3) = row.at(3);
1065 for (
int n = timestamps.size() - 1; n >= 0 && nt <
static_cast<int>(timestamps.size());
1068 std::vector<float> row;
1069 row.push_back(timestamps.at(nt));
1070 for (
size_t i = 0; i < cartData.size(); i++)
1072 row.push_back(cartData.at(i).at(n));
1078 Eigen::Matrix4f endPose = VirtualRobot::MathTools::quat2eigen4f(
1079 row.at(5), row.at(6), row.at(7), row.at(4));
1080 endPose(0, 3) = row.at(1);
1081 endPose(1, 3) = row.at(2);
1082 endPose(2, 3) = row.at(3);
1091 std::string dmpJSForwardFile;
1092 std::string dmpJSBackwardFile;
1094 std::vector<std::string> header;
1095 header.push_back(
"timestamp");
1096 for (
size_t i = 0; i < jointNames.size(); ++i)
1098 header.push_back(jointNames.at(i));
1101 std::string ffname = trajName +
"-js-forward.csv";
1102 std::string bfname = trajName +
"-js-backward.csv";
1103 dmpJSForwardFile = dataDir + ffname;
1104 dmpJSBackwardFile = dataDir + bfname;
1105 std::vector<std::string> fflist;
1106 fflist.push_back(ffname);
1108 std::vector<std::string> bflist;
1109 bflist.push_back(bfname);
1111 CsvWriter fwriter(dmpJSForwardFile, header,
false);
1112 CsvWriter bwriter(dmpJSBackwardFile, header,
false);
1114 ARMARX_IMPORTANT <<
"writing jointspace trajectory as " << ffname <<
" and " << bfname;
1116 double endTime = timestamps.at(timestamps.size() - 1);
1117 for (
size_t n = 0; n < timestamps.size(); n++)
1120 std::vector<float> row;
1121 row.push_back(timestamps.at(n));
1122 for (
size_t i = 0; i < jointNames.size(); i++)
1124 row.push_back(jointData.at(i).at(n));
1128 if (endTime - timestamps.at(n) < cutoutTime)
1130 std::vector<float> endJointValue;
1131 for (
size_t i = 0; i < jointNames.size(); i++)
1133 endJointValue.push_back(jointData.at(i).at(n));
1139 ARMARX_INFO <<
"forward joint space data written to fine!";
1141 for (
int n = timestamps.size() - 1; n >= 0 && nt <
static_cast<int>(timestamps.size());
1144 std::vector<float> row;
1145 row.push_back(timestamps.at(nt));
1146 for (
size_t i = 0; i < jointNames.size(); i++)
1148 row.push_back(jointData.at(i).at(n));
1154 std::vector<float> endJointValue;
1155 for (
size_t i = 0; i < jointNames.size(); i++)
1157 endJointValue.push_back(jointData.at(i).at(n));
1164 return returnFileNamePattern;