28 #include <IceUtil/Time.h>
30 #include <VirtualRobot/MathTools.h>
31 #include <VirtualRobot/Nodes/RobotNode.h>
32 #include <VirtualRobot/RobotNodeSet.h>
44 #include <ArmarXGui/interface/StaticPlotterInterface.h>
46 #include <RobotAPI/interface/units/RobotUnit/NjointZeroTorqueController.h>
59 #include <armarx/control/common/control_law/aron/CollisionAvoidanceControllerConfig.aron.generated.h>
64 const std::string Component::defaultName =
"controller_creator";
79 def->optional(properties.robotName,
"robotName");
81 def->optional(properties.defaultRobotNodeSetLeft,
82 "default_robotNodeSet_left",
83 "default kinematic chain name of left arm.");
84 def->optional(properties.defaultRobotNodeSetRight,
85 "default_robotNodeSet_right",
86 "default kinematic chain name of right arm.");
88 const std::string defaultName =
"";
89 def->component(m_robot_unit, defaultName);
156 m_robot =
addRobot(
"controller_creator_robot", VirtualRobot::RobotIO::eStructure);
161 m_rns_l = m_robot->getRobotNodeSet(properties.defaultRobotNodeSetLeft);
162 m_rns_r = m_robot->getRobotNodeSet(properties.defaultRobotNodeSetRight);
455 template <control::common::ControllerType T>
459 const std::string& configFilename,
464 auto builder = controllerBuilder<T>();
465 auto ctrlWrapper = builder.createTSComplianceCtrl(namePrefix, configDict);
466 const std::string controllerName = builder.getControllerName();
467 return controllerName;
472 const std::string& controllerType,
474 const std::string& configFilename,
480 ARMARX_INFO <<
"creating controller of type " << controllerType;
482 std::string controllerName;
492 controllerName = createComplianceController<T::TSAdm>(
493 namePrefix, configDict, configFilename, activate, allowReuse, cfgFromMemory);
496 controllerName = createComplianceController<T::TSImp>(
497 namePrefix, configDict, configFilename, activate, allowReuse, cfgFromMemory);
500 controllerName = createComplianceController<T::TSImpCol>(
501 namePrefix, configDict, configFilename, activate, allowReuse, cfgFromMemory);
503 case T::TSMixImpVelCol:
504 controllerName = createComplianceController<T::TSMixImpVelCol>(
505 namePrefix, configDict, configFilename, activate, allowReuse, cfgFromMemory);
508 controllerName = createComplianceController<T::TSMixImpVel>(
509 namePrefix, configDict, configFilename, activate, allowReuse, cfgFromMemory);
512 controllerName = createComplianceController<T::TSVel>(
513 namePrefix, configDict, configFilename, activate, allowReuse, cfgFromMemory);
517 controllerName = createComplianceController<T::TSMPAdm>(
518 namePrefix, configDict, configFilename, activate, allowReuse, cfgFromMemory);
521 controllerName = createComplianceController<T::TSMPImp>(
522 namePrefix, configDict, configFilename, activate, allowReuse, cfgFromMemory);
525 controllerName = createComplianceController<T::TSMPImpCol>(
526 namePrefix, configDict, configFilename, activate, allowReuse, cfgFromMemory);
528 case T::TSMPMixImpVel:
529 controllerName = createComplianceController<T::TSMPMixImpVel>(
530 namePrefix, configDict, configFilename, activate, allowReuse, cfgFromMemory);
533 controllerName = createComplianceController<T::TSMPVel>(
534 namePrefix, configDict, configFilename, activate, allowReuse, cfgFromMemory);
536 case T::TSMPMixImpVelCol:
537 controllerName = createComplianceController<T::TSMPMixImpVelCol>(
538 namePrefix, configDict, configFilename, activate, allowReuse, cfgFromMemory);
540 case T::TSMPMixImpVelColWiping:
541 controllerName = createComplianceController<T::TSMPMixImpVelColWiping>(
542 namePrefix, configDict, configFilename, activate, allowReuse, cfgFromMemory);
544 case T::TSMPVelWiping:
545 controllerName = createComplianceController<T::TSMPVelWiping>(
546 namePrefix, configDict, configFilename, activate, allowReuse, cfgFromMemory);
553 ARMARX_INFO <<
"controller type: " << controllerType <<
" is not supported yet";
555 return controllerName;
714 const std::string& side,
715 const std::string& fileName,
716 const std::string& nameSuffix,
720 ARMARX_INFO <<
"Kinesthetic teaching: Initialize zero torque controllers for "
721 <<
VAROUT(kinematicChainName);
722 const std::string ctrl_class_name =
"NJointZeroTorqueController";
723 const std::string ctrl_name =
"kinesthetic_teaching_" + ctrl_class_name +
"_" + nameSuffix;
727 if (kinematicChainName ==
"RightArm" || kinematicChainName ==
"RightArmWithoutWrist")
732 auto& robotReader = virtualRobotReader_->get();
736 robotReader, properties.robotName, hand);
742 NJointZeroTorqueControllerConfigPtr config(
new NJointZeroTorqueControllerConfig());
743 config->maxTorque = 0;
745 auto nodeSet = m_robot->getRobotNodeSet(kinematicChainName);
746 for (
auto& name : nodeSet->getNodeNames())
748 config->jointNames.push_back(name);
750 NJointZeroTorqueControllerInterfacePrx zeroTorqueController =
751 NJointZeroTorqueControllerInterfacePrx::checkedCast(
752 m_robot_unit->createNJointController(ctrl_class_name, ctrl_name, config));
756 float motionThresholdRadian = 0.1f;
757 float noMotionTimeoutMs = 2000.0f;
759 VirtualRobot::RobotNodeSetPtr rns = m_robot->getRobotNodeSet(kinematicChainName);
760 std::vector<std::string> jointNames = rns->getNodeNames();
763 bool initialMotionDetected =
false;
767 std::vector<std::vector<float>> jointData;
768 std::vector<std::vector<float>> cartData;
769 std::vector<float> timestamps;
772 Eigen::VectorXf jve = rns->getJointValuesEigen();
775 VirtualRobot::MathTools::eigen4f2quat(initPose);
779 for (
size_t i = 0; i < jointNames.size(); i++)
781 std::vector<float> cjoint{};
783 jointData.push_back(cjoint);
788 for (
size_t i = 0; i < 7; ++i)
790 std::vector<float> cpos{};
792 cartData.push_back(cpos);
796 int motionStartIndex = 0;
797 int motionEndIndex = 0;
832 zeroTorqueController->activateController();
839 Eigen::VectorXf jve2 = rns->getJointValuesEigen();
840 if ((jve2 - jve).
norm() > motionThresholdRadian)
842 if (!initialMotionDetected)
845 motionStartIndex = 0;
849 initialMotionDetected =
true;
850 lastMotionTime = now;
853 double t = (now - start).toSecondsDouble();
855 std::vector<float> jvs = rns->getJointValues();
856 for (
size_t i = 0; i < jvs.size(); i++)
858 jointData.at(i).push_back(jvs.at(i));
862 cartData.at(0).push_back(tcpPose(0, 3));
863 cartData.at(1).push_back(tcpPose(1, 3));
864 cartData.at(2).push_back(tcpPose(2, 3));
866 VirtualRobot::MathTools::eigen4f2quat(tcpPose);
869 double dotProduct = quat.w * oldquatE.w + quat.x * oldquatE.x + quat.y * oldquatE.y +
873 cartData.at(3).push_back(-quat.w);
874 cartData.at(4).push_back(-quat.x);
875 cartData.at(5).push_back(-quat.y);
876 cartData.at(6).push_back(-quat.z);
877 oldquatE.w = -quat.w;
878 oldquatE.x = -quat.x;
879 oldquatE.y = -quat.y;
880 oldquatE.z = -quat.z;
884 cartData.at(3).push_back(quat.w);
885 cartData.at(4).push_back(quat.x);
886 cartData.at(5).push_back(quat.y);
887 cartData.at(6).push_back(quat.z);
895 timestamps.push_back(t);
897 if (initialMotionDetected &&
898 (now - lastMotionTime).toMilliSeconds() > noMotionTimeoutMs)
901 motionEndIndex = timestamps.size();
909 zeroTorqueController->deactivateController();
910 while (zeroTorqueController->isControllerActive())
914 zeroTorqueController->deleteController();
915 ARMARX_INFO <<
"zerotorque controller for kinesthetic teaching is deleteded";
918 motionStartIndex -= sigmaMs / sampleMs * 2;
919 if (motionStartIndex < 0)
921 motionStartIndex = 0;
932 timestamps = std::vector<float>(timestamps.begin() + motionStartIndex,
933 timestamps.begin() + motionEndIndex);
934 for (
size_t n = 1; n < timestamps.size(); n++)
936 timestamps.at(n) = timestamps.at(n) - timestamps.at(0);
938 timestamps.at(0) = 0;
942 timestamps.at(0), timestamps.at(timestamps.size() - 1), timestamps.size());
946 StringFloatSeqDict plotFiltered;
947 StringFloatSeqDict plotOrig;
948 StringFloatSeqDict plotResampled;
949 for (
size_t i = 0; i < jointData.size(); i++)
951 jointData.at(i) = std::vector<float>(jointData.at(i).begin() + motionStartIndex,
952 jointData.at(i).begin() + motionEndIndex);
953 if (rns->getNode(i)->isLimitless())
957 plotOrig[jointNames.at(i)] = jointData.at(i);
960 plotResampled[jointNames.at(i)] = jointData.at(i);
966 plotFiltered[jointNames.at(i)] = jointData.at(i);
973 std::vector<std::string> cartName = {
"x",
"y",
"z",
"qw",
"qx",
"qy",
"qz"};
977 std::string trajName;
980 time_t timer = now.toSeconds();
983 ts = localtime(&timer);
984 strftime(buffer, 80,
"%Y-%m-%d-%H-%M-%S", ts);
985 std::string
str(buffer);
986 trajName = fileName +
"-" +
str;
990 double cutoutTime = (noMotionTimeoutMs / 1000.0f) * 0.8;
992 std::string packageName =
"armarx_control";
995 std::string dataDir = finder.
getDataDir() +
"/" + packageName +
"/kinesthetic_teaching/";
996 std::string returnFileNamePattern = dataDir + trajName;
1000 std::string dmpForwardFile;
1001 std::string dmpBackwardFile;
1003 std::vector<std::string> header;
1004 header.push_back(
"timestamp");
1005 for (
size_t i = 0; i < cartName.size(); ++i)
1007 header.push_back(cartName.at(i));
1010 std::string ffname = trajName +
"-ts-forward.csv";
1011 std::string bfname = trajName +
"-ts-backward.csv";
1012 dmpForwardFile = dataDir + ffname;
1013 dmpBackwardFile = dataDir + bfname;
1014 std::vector<std::string> fflist;
1015 fflist.push_back(ffname);
1017 std::vector<std::string> bflist;
1018 bflist.push_back(bfname);
1020 CsvWriter fwriter(dmpForwardFile, header,
false);
1021 CsvWriter bwriter(dmpBackwardFile, header,
false);
1023 ARMARX_IMPORTANT <<
"writing taskspace trajectory as " << ffname <<
" and " << bfname;
1025 double endTime = timestamps.at(timestamps.size() - 1);
1026 for (
size_t n = 0; n < timestamps.size(); n++)
1029 std::vector<float> row;
1030 row.push_back(timestamps.at(n));
1031 for (
size_t i = 0; i < cartData.size(); i++)
1033 row.push_back(cartData.at(i).at(n));
1037 if (endTime - timestamps.at(n) < cutoutTime)
1040 row.at(5), row.at(6), row.at(7), row.at(4));
1041 endPose(0, 3) = row.at(1);
1042 endPose(1, 3) = row.at(2);
1043 endPose(2, 3) = row.at(3);
1049 for (
int n = timestamps.size() - 1; n >= 0 && nt <
static_cast<int>(timestamps.size());
1052 std::vector<float> row;
1053 row.push_back(timestamps.at(nt));
1054 for (
size_t i = 0; i < cartData.size(); i++)
1056 row.push_back(cartData.at(i).at(n));
1063 row.at(5), row.at(6), row.at(7), row.at(4));
1064 endPose(0, 3) = row.at(1);
1065 endPose(1, 3) = row.at(2);
1066 endPose(2, 3) = row.at(3);
1075 std::string dmpJSForwardFile;
1076 std::string dmpJSBackwardFile;
1078 std::vector<std::string> header;
1079 header.push_back(
"timestamp");
1080 for (
size_t i = 0; i < jointNames.size(); ++i)
1082 header.push_back(jointNames.at(i));
1085 std::string ffname = trajName +
"-js-forward.csv";
1086 std::string bfname = trajName +
"-js-backward.csv";
1087 dmpJSForwardFile = dataDir + ffname;
1088 dmpJSBackwardFile = dataDir + bfname;
1089 std::vector<std::string> fflist;
1090 fflist.push_back(ffname);
1092 std::vector<std::string> bflist;
1093 bflist.push_back(bfname);
1095 CsvWriter fwriter(dmpJSForwardFile, header,
false);
1096 CsvWriter bwriter(dmpJSBackwardFile, header,
false);
1098 ARMARX_IMPORTANT <<
"writing jointspace trajectory as " << ffname <<
" and " << bfname;
1100 double endTime = timestamps.at(timestamps.size() - 1);
1101 for (
size_t n = 0; n < timestamps.size(); n++)
1104 std::vector<float> row;
1105 row.push_back(timestamps.at(n));
1106 for (
size_t i = 0; i < jointNames.size(); i++)
1108 row.push_back(jointData.at(i).at(n));
1112 if (endTime - timestamps.at(n) < cutoutTime)
1114 std::vector<float> endJointValue;
1115 for (
size_t i = 0; i < jointNames.size(); i++)
1117 endJointValue.push_back(jointData.at(i).at(n));
1123 ARMARX_INFO <<
"forward joint space data written to fine!";
1125 for (
int n = timestamps.size() - 1; n >= 0 && nt <
static_cast<int>(timestamps.size());
1128 std::vector<float> row;
1129 row.push_back(timestamps.at(nt));
1130 for (
size_t i = 0; i < jointNames.size(); i++)
1132 row.push_back(jointData.at(i).at(n));
1138 std::vector<float> endJointValue;
1139 for (
size_t i = 0; i < jointNames.size(); i++)
1141 endJointValue.push_back(jointData.at(i).at(n));
1148 return returnFileNamePattern;
1158 std::vector<std::string> joint_names = m_rns_l->getNodeNames();
1160 NameControlModeMap control_modes;
1161 for (
const std::string& joint_name : joint_names)
1163 control_modes[joint_name] = eVelocityControl;
1164 target_vels[joint_name] = 0;
1169 std::vector<std::string> joint_names = m_rns_r->getNodeNames();
1171 NameControlModeMap control_modes;
1172 for (
const std::string& joint_name : joint_names)
1174 control_modes[joint_name] = eVelocityControl;
1175 target_vels[joint_name] = 0;
1188 Eigen::Matrix4f pose = m_robot->getRobotNode(nodeName)->getPoseInRootFrame();
1190 std::vector<Ice::Float> pose_seq;
1191 for (
int i = 0; i < pose.rows(); i++)
1193 for (
int j = 0; j < pose.cols(); j++)
1195 pose_seq.push_back(pose(i, j));
1205 Eigen::Matrix4f pose = m_robot->getRobotNode(nodeName)->getGlobalPose();
1207 std::vector<Ice::Float> pose_seq;
1208 for (
int i = 0; i < pose.rows(); i++)
1210 for (
int j = 0; j < pose.cols(); j++)
1212 pose_seq.push_back(pose(i, j));
1221 return Component::defaultName;
1227 return Component::defaultName;