35 #include <ArmarXGui/interface/StaticPlotterInterface.h>
37 #include <RobotAPI/interface/units/RobotUnit/NjointZeroTorqueController.h>
50 #include <armarx/control/common/control_law/aron/CollisionAvoidanceControllerConfig.aron.generated.h>
55 const std::string Component::defaultName =
"controller_creator";
73 def->optional(properties.defaultRobotNodeSetLeft,
74 "default_robotNodeSet_left",
75 "default kinematic chain name of left arm.");
76 def->optional(properties.defaultRobotNodeSetRight,
77 "default_robotNodeSet_right",
78 "default kinematic chain name of right arm.");
80 def->component(m_robot_unit, properties.robotUnitName);
147 m_robot =
addRobot(
"controller_creator_robot", VirtualRobot::RobotIO::eStructure);
152 m_rns_l = m_robot->getRobotNodeSet(properties.defaultRobotNodeSetLeft);
153 m_rns_r = m_robot->getRobotNodeSet(properties.defaultRobotNodeSetRight);
446 template <control::common::ControllerType T>
450 const std::string& configFilename,
455 auto builder = controllerBuilder<T>();
456 auto ctrlWrapper = builder.createTSComplianceCtrl(namePrefix, configDict);
457 const std::string controllerName = builder.getControllerName();
458 return controllerName;
463 const std::string& controllerType,
465 const std::string& configFilename,
471 ARMARX_INFO <<
"creating controller of type " << controllerType;
473 std::string controllerName;
483 controllerName = createComplianceController<T::TSAdm>(
484 namePrefix, configDict, configFilename, activate, allowReuse, cfgFromMemory);
487 controllerName = createComplianceController<T::TSImp>(
488 namePrefix, configDict, configFilename, activate, allowReuse, cfgFromMemory);
491 controllerName = createComplianceController<T::TSImpSafe>(
492 namePrefix, configDict, configFilename, activate, allowReuse, cfgFromMemory);
495 controllerName = createComplianceController<T::TSImpCol>(
496 namePrefix, configDict, configFilename, activate, allowReuse, cfgFromMemory);
498 case T::TSMixImpVelCol:
499 controllerName = createComplianceController<T::TSMixImpVelCol>(
500 namePrefix, configDict, configFilename, activate, allowReuse, cfgFromMemory);
503 controllerName = createComplianceController<T::TSMixImpVel>(
504 namePrefix, configDict, configFilename, activate, allowReuse, cfgFromMemory);
507 controllerName = createComplianceController<T::TSVel>(
508 namePrefix, configDict, configFilename, activate, allowReuse, cfgFromMemory);
512 controllerName = createComplianceController<T::TSMPAdm>(
513 namePrefix, configDict, configFilename, activate, allowReuse, cfgFromMemory);
516 controllerName = createComplianceController<T::TSMPImp>(
517 namePrefix, configDict, configFilename, activate, allowReuse, cfgFromMemory);
520 controllerName = createComplianceController<T::TSMPImpSafe>(
521 namePrefix, configDict, configFilename, activate, allowReuse, cfgFromMemory);
524 controllerName = createComplianceController<T::TSMPImpCol>(
525 namePrefix, configDict, configFilename, activate, allowReuse, cfgFromMemory);
527 case T::TSMPMixImpVel:
528 controllerName = createComplianceController<T::TSMPMixImpVel>(
529 namePrefix, configDict, configFilename, activate, allowReuse, cfgFromMemory);
532 controllerName = createComplianceController<T::TSMPVel>(
533 namePrefix, configDict, configFilename, activate, allowReuse, cfgFromMemory);
535 case T::TSMPMixImpVelCol:
536 controllerName = createComplianceController<T::TSMPMixImpVelCol>(
537 namePrefix, configDict, configFilename, activate, allowReuse, cfgFromMemory);
544 ARMARX_INFO <<
"controller type: " << controllerType <<
" is not supported yet";
546 return controllerName;
705 const std::string& side,
706 const std::string& fileName,
710 ARMARX_INFO <<
"Kinesthetic teaching: Initialize zero torque controllers for "
711 <<
VAROUT(kinematicChainName);
712 const std::string ctrl_class_name =
"NJointZeroTorqueController";
713 const std::string ctrl_name =
getDefaultName() +
"_kinesthetic_teaching_" + ctrl_class_name;
717 if (kinematicChainName ==
"RightArm" || kinematicChainName ==
"RightArmWithoutWrist")
722 auto& robotReader = virtualRobotReader_->get();
726 robotReader, properties.robotName, hand);
732 NJointZeroTorqueControllerConfigPtr config(
new NJointZeroTorqueControllerConfig());
733 config->maxTorque = 0;
735 auto nodeSet = m_robot->getRobotNodeSet(kinematicChainName);
736 for (
auto& name : nodeSet->getNodeNames())
738 config->jointNames.push_back(name);
740 NJointZeroTorqueControllerInterfacePrx zeroTorqueController =
741 NJointZeroTorqueControllerInterfacePrx::checkedCast(
742 m_robot_unit->createNJointController(ctrl_class_name, ctrl_name, config));
746 float motionThresholdRadian = 0.1f;
747 float noMotionTimeoutMs = 2000.0f;
749 VirtualRobot::RobotNodeSetPtr rns = m_robot->getRobotNodeSet(kinematicChainName);
750 std::vector<std::string> jointNames = rns->getNodeNames();
753 bool initialMotionDetected =
false;
757 std::vector<std::vector<float>> jointData;
758 std::vector<std::vector<float>> cartData;
759 std::vector<float> timestamps;
762 Eigen::VectorXf jve = rns->getJointValuesEigen();
765 VirtualRobot::MathTools::eigen4f2quat(initPose);
769 for (
size_t i = 0; i < jointNames.size(); i++)
771 std::vector<float> cjoint{};
773 jointData.push_back(cjoint);
778 for (
size_t i = 0; i < 7; ++i)
780 std::vector<float> cpos{};
782 cartData.push_back(cpos);
786 int motionStartIndex = 0;
787 int motionEndIndex = 0;
822 zeroTorqueController->activateController();
829 Eigen::VectorXf jve2 = rns->getJointValuesEigen();
830 if ((jve2 - jve).
norm() > motionThresholdRadian)
832 if (!initialMotionDetected)
835 motionStartIndex = 0;
839 initialMotionDetected =
true;
840 lastMotionTime = now;
843 double t = (now - start).toSecondsDouble();
845 std::vector<float> jvs = rns->getJointValues();
846 for (
size_t i = 0; i < jvs.size(); i++)
848 jointData.at(i).push_back(jvs.at(i));
852 cartData.at(0).push_back(tcpPose(0, 3));
853 cartData.at(1).push_back(tcpPose(1, 3));
854 cartData.at(2).push_back(tcpPose(2, 3));
856 VirtualRobot::MathTools::eigen4f2quat(tcpPose);
859 double dotProduct = quat.w * oldquatE.w + quat.x * oldquatE.x + quat.y * oldquatE.y +
863 cartData.at(3).push_back(-quat.w);
864 cartData.at(4).push_back(-quat.x);
865 cartData.at(5).push_back(-quat.y);
866 cartData.at(6).push_back(-quat.z);
867 oldquatE.w = -quat.w;
868 oldquatE.x = -quat.x;
869 oldquatE.y = -quat.y;
870 oldquatE.z = -quat.z;
874 cartData.at(3).push_back(quat.w);
875 cartData.at(4).push_back(quat.x);
876 cartData.at(5).push_back(quat.y);
877 cartData.at(6).push_back(quat.z);
885 timestamps.push_back(t);
887 if (initialMotionDetected &&
888 (now - lastMotionTime).toMilliSeconds() > noMotionTimeoutMs)
891 motionEndIndex = timestamps.size();
899 zeroTorqueController->deactivateController();
900 while (zeroTorqueController->isControllerActive())
904 zeroTorqueController->deleteController();
907 motionStartIndex -= sigmaMs / sampleMs * 2;
908 if (motionStartIndex < 0)
910 motionStartIndex = 0;
921 timestamps = std::vector<float>(timestamps.begin() + motionStartIndex,
922 timestamps.begin() + motionEndIndex);
923 for (
size_t n = 1; n < timestamps.size(); n++)
925 timestamps.at(n) = timestamps.at(n) - timestamps.at(0);
927 timestamps.at(0) = 0;
931 timestamps.at(0), timestamps.at(timestamps.size() - 1), timestamps.size());
935 StringFloatSeqDict plotFiltered;
936 StringFloatSeqDict plotOrig;
937 StringFloatSeqDict plotResampled;
938 for (
size_t i = 0; i < jointData.size(); i++)
940 jointData.at(i) = std::vector<float>(jointData.at(i).begin() + motionStartIndex,
941 jointData.at(i).begin() + motionEndIndex);
942 if (rns->getNode(i)->isLimitless())
946 plotOrig[jointNames.at(i)] = jointData.at(i);
949 plotResampled[jointNames.at(i)] = jointData.at(i);
955 plotFiltered[jointNames.at(i)] = jointData.at(i);
962 std::vector<std::string> cartName = {
"x",
"y",
"z",
"qw",
"qx",
"qy",
"qz"};
966 std::string trajName;
969 time_t timer = now.toSeconds();
972 ts = localtime(&timer);
973 strftime(buffer, 80,
"%Y-%m-%d-%H-%M-%S", ts);
974 std::string
str(buffer);
975 trajName = fileName +
"-" +
str;
979 double cutoutTime = (noMotionTimeoutMs / 1000.0f) * 0.8;
981 std::string packageName =
"armarx_control";
984 std::string dataDir = finder.
getDataDir() +
"/" + packageName +
"/kinesthetic_teaching/";
985 std::string returnFileNamePattern = dataDir + trajName;
989 std::string dmpForwardFile;
990 std::string dmpBackwardFile;
992 std::vector<std::string> header;
993 header.push_back(
"timestamp");
994 for (
size_t i = 0; i < cartName.size(); ++i)
996 header.push_back(cartName.at(i));
999 std::string ffname = trajName +
"-ts-forward.csv";
1000 std::string bfname = trajName +
"-ts-backward.csv";
1001 dmpForwardFile = dataDir + ffname;
1002 dmpBackwardFile = dataDir + bfname;
1003 std::vector<std::string> fflist;
1004 fflist.push_back(ffname);
1006 std::vector<std::string> bflist;
1007 bflist.push_back(bfname);
1009 CsvWriter fwriter(dmpForwardFile, header,
false);
1010 CsvWriter bwriter(dmpBackwardFile, header,
false);
1012 ARMARX_IMPORTANT <<
"writing taskspace trajectory as " << ffname <<
" and " << bfname;
1014 double endTime = timestamps.at(timestamps.size() - 1);
1015 for (
size_t n = 0; n < timestamps.size(); n++)
1018 std::vector<float> row;
1019 row.push_back(timestamps.at(n));
1020 for (
size_t i = 0; i < cartData.size(); i++)
1022 row.push_back(cartData.at(i).at(n));
1026 if (endTime - timestamps.at(n) < cutoutTime)
1029 row.at(5), row.at(6), row.at(7), row.at(4));
1030 endPose(0, 3) = row.at(1);
1031 endPose(1, 3) = row.at(2);
1032 endPose(2, 3) = row.at(3);
1038 for (
int n = timestamps.size() - 1; n >= 0 && nt <
static_cast<int>(timestamps.size());
1041 std::vector<float> row;
1042 row.push_back(timestamps.at(nt));
1043 for (
size_t i = 0; i < cartData.size(); i++)
1045 row.push_back(cartData.at(i).at(n));
1052 row.at(5), row.at(6), row.at(7), row.at(4));
1053 endPose(0, 3) = row.at(1);
1054 endPose(1, 3) = row.at(2);
1055 endPose(2, 3) = row.at(3);
1064 std::string dmpJSForwardFile;
1065 std::string dmpJSBackwardFile;
1067 std::vector<std::string> header;
1068 header.push_back(
"timestamp");
1069 for (
size_t i = 0; i < jointNames.size(); ++i)
1071 header.push_back(jointNames.at(i));
1074 std::string ffname = trajName +
"-js-forward.csv";
1075 std::string bfname = trajName +
"-js-backward.csv";
1076 dmpJSForwardFile = dataDir + ffname;
1077 dmpJSBackwardFile = dataDir + bfname;
1078 std::vector<std::string> fflist;
1079 fflist.push_back(ffname);
1081 std::vector<std::string> bflist;
1082 bflist.push_back(bfname);
1084 CsvWriter fwriter(dmpJSForwardFile, header,
false);
1085 CsvWriter bwriter(dmpJSBackwardFile, header,
false);
1087 ARMARX_IMPORTANT <<
"writing jointspace trajectory as " << ffname <<
" and " << bfname;
1089 double endTime = timestamps.at(timestamps.size() - 1);
1090 for (
size_t n = 0; n < timestamps.size(); n++)
1093 std::vector<float> row;
1094 row.push_back(timestamps.at(n));
1095 for (
size_t i = 0; i < jointNames.size(); i++)
1097 row.push_back(jointData.at(i).at(n));
1101 if (endTime - timestamps.at(n) < cutoutTime)
1103 std::vector<float> endJointValue;
1104 for (
size_t i = 0; i < jointNames.size(); i++)
1106 endJointValue.push_back(jointData.at(i).at(n));
1112 ARMARX_INFO <<
"forward joint space data written to fine!";
1114 for (
int n = timestamps.size() - 1; n >= 0 && nt <
static_cast<int>(timestamps.size());
1117 std::vector<float> row;
1118 row.push_back(timestamps.at(nt));
1119 for (
size_t i = 0; i < jointNames.size(); i++)
1121 row.push_back(jointData.at(i).at(n));
1127 std::vector<float> endJointValue;
1128 for (
size_t i = 0; i < jointNames.size(); i++)
1130 endJointValue.push_back(jointData.at(i).at(n));
1137 return returnFileNamePattern;
1147 std::vector<std::string> joint_names = m_rns_l->getNodeNames();
1149 NameControlModeMap control_modes;
1150 for (
const std::string& joint_name : joint_names)
1152 control_modes[joint_name] = eVelocityControl;
1153 target_vels[joint_name] = 0;
1158 std::vector<std::string> joint_names = m_rns_r->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;
1177 Eigen::Matrix4f pose = m_robot->getRobotNode(nodeName)->getPoseInRootFrame();
1179 std::vector<Ice::Float> pose_seq;
1180 for (
int i = 0; i < pose.rows(); i++)
1182 for (
int j = 0; j < pose.cols(); j++)
1184 pose_seq.push_back(pose(i, j));
1194 Eigen::Matrix4f pose = m_robot->getRobotNode(nodeName)->getGlobalPose();
1196 std::vector<Ice::Float> pose_seq;
1197 for (
int i = 0; i < pose.rows(); i++)
1199 for (
int j = 0; j < pose.cols(); j++)
1201 pose_seq.push_back(pose(i, j));
1210 return Component::defaultName;
1216 return Component::defaultName;