27 #include <type_traits>
29 #include <SimoxUtility/json/json.hpp>
36 #include <RobotAPI/interface/units/RobotUnit/RobotUnitInterface.h>
42 #include <armarx/control/core/Controller.h>
43 #include <armarx/control/interface/ConfigurableNJointControllerInterface.h>
44 #include <armarx/control/memory/config/Reader.h>
45 #include <armarx/control/memory/config/Writer.h>
62 detail::ctrl_class_name::CtrlConfigClassName_v<ControllerDescriptionType>;
65 using AronDTO =
typename ControllerDescriptionType::AronDTO;
68 static_assert(::armarx::aron::cpp::isAronGeneratedClass<AronDTO>,
69 "The AronConfigT must be an AronGeneratedClass!");
72 const memory::config::Reader& configProvider,
73 const memory::config::Writer& configWriter,
74 const std::string& controllerNamePrefix) :
75 controllerCreator(controllerCreator),
76 configReader(configProvider),
77 configWriter(configWriter),
78 controllerNamePrefix(controllerNamePrefix)
81 <<
"By convention, the controller name prefix must exist. This ensures that "
82 "in between components, no naming clashes occur.";
88 if (
auto cfg = configReader.getDefaultConfig(ControllerDescriptionType::name, name))
90 dto = AronDTO::FromAron(cfg);
102 const std::string& robotNameSuffix =
"",
103 const std::string& appendix =
"")
108 "controller_config/" + configClassName +
"/" +
109 name + robotNameSuffix + appendix +
".json");
117 auto cfg = configReader.getConfig(memoryId);
118 dto = AronDTO::FromAron(cfg);
126 dto = AronDTO::FromAron(configDict);
138 nlohmann::json jsonConfig;
142 if (not this->dto.has_value())
152 this->dto->read(reader, jsonConfig);
175 this->nodeSetName = nodeSetName;
182 if (namePrefix.empty())
186 this->controllerNamePrefix = this->controllerNamePrefix +
"_" + namePrefix;
193 this->daemonized =
true;
202 std::unique_ptr<ControllerWrapper<T>>
205 const std::string controllerClassName = ControllerDescriptionType::name;
206 return create(controllerClassName);
209 std::unique_ptr<ControllerWrapper<T>>
212 if (not ensureInitialized())
217 ::armarx::control::ConfigurableNJointControllerConfigPtr
config =
218 new ::armarx::control::ConfigurableNJointControllerConfig;
219 config->config = dto.value().toAronDTO();
229 controllerName = controllerNamePrefix +
"_" + name;
230 const std::string controllerClassName = ControllerDescriptionType::name;
234 armarx::NJointControllerInterfacePrx
controller =
235 controllerCreator->getNJointController(controllerName);
238 this->reusing_ = [&]() ->
bool
253 if (
controller->getClassName() != controllerClassName)
292 ARMARX_INFO <<
"--- Deleting existing controller `" << controllerName <<
"`";
296 ARMARX_INFO <<
"--- Wait until controller is in-active";
305 ARMARX_INFO <<
"--- Controller is not active anymore, deleting controller";
323 if (not this->reusing_)
327 ARMARX_INFO <<
"Creating controller `" << controllerName <<
"`";
329 controller = controllerCreator->createNJointController(
330 controllerClassName, controllerName,
config);
332 ARMARX_INFO << controllerName <<
" is now created.";
341 ARMARX_WARNING <<
"Failed to create controller of type `" << controllerClassName
347 armarx::control::ConfigurableNJointControllerInterfacePrx::checkedCast(
controller);
349 std::unique_ptr<ControllerWrapper<T>> ctrlWrapper =
350 std::make_unique<ControllerWrapper<T>>(
351 ctrl, controllerName, configWriter, dto.value());
352 ctrlWrapper->daemonize(daemonized);
356 ctrlWrapper->updateConfig();
360 std::unique_ptr<ControllerWrapper<T>>
363 const std::string& configFilename =
"",
364 bool flagActivate =
true,
365 bool flagAllowReuse =
true,
366 bool flagFromMemory =
false)
368 ARMARX_CHECK(not(configDict.get() ==
nullptr and configFilename.empty()));
376 if (configFilename.empty())
386 <<
"configuration file does not exist\n"
389 "1) if you need to configure a controller by passing configuration "
392 "controllerBuilder (me), you need to make sure the "
394 "component is running "
395 "on the same PC as your application, otherwise\n"
396 "2) use the createControllerFromConfig() interface, which does not "
399 "creator is running";
409 std::ostringstream oss;
410 for (
const auto& pair :
config().limbs)
413 if (&pair != &(*
config().limbs.rbegin()))
418 std::string robotNodeSets = oss.str();
420 if (namePrefix.empty())
433 auto ctrlWrapper =
create();
437 ARMARX_INFO <<
"using controller name " << controllerName;
443 <<
"setting nullspace target: if the default is null use the cfg from the "
444 "existing controller";
447 auto ctrlConfig = ctrlWrapper->getConfig().limbs;
448 for (
const auto& pair :
config().limbs)
450 if (not pair.second.desiredNullspaceJointAngles.has_value())
452 ctrlWrapper->config.limbs.at(pair.first).desiredNullspaceJointAngles =
453 ctrlConfig.at(pair.first).desiredNullspaceJointAngles;
467 ctrlWrapper->activate();
469 while (not ctrlWrapper->isActive())
473 ARMARX_INFO <<
"Controller " << controllerName <<
" is active";
477 ARMARX_INFO <<
"User have to activate " << controllerName
478 <<
" controller in your application";
483 std::unique_ptr<ControllerWrapper<T>>
487 const std::string& configFilename =
"",
488 bool flagActivate =
true,
489 bool flagAllowReuse =
true,
490 bool flagFromMemory =
false,
491 bool flagStart =
true)
499 auto ctrl = CtrlProxy::checkedCast(ctrlWrapper->ctrl());
500 ctrl->updateMPConfig(mpConfigDict);
516 const std::string& configFilename =
"",
517 bool flagActivate =
true,
518 bool flagAllowReuse =
true,
519 bool flagFromMemory =
false,
520 bool flagStart =
true)
528 auto ctrl = CtrlProxy::checkedCast(ctrlWrapper->ctrl());
530 ctrl->updateMPConfig(mpConfigDict);
552 return this->reusing_;
558 return controllerName;
565 if (
auto cfg = configReader.getDefaultConfig(ControllerDescriptionType::name))
567 dto = AronDTO::FromAron(cfg);
578 if (not dto.has_value())
580 return initDefaultConfig();
588 const memory::config::Reader configReader;
589 const memory::config::Writer configWriter;
591 std::optional<AronDTO> dto;
593 std::optional<std::string> nodeSetName;
595 std::string controllerNamePrefix;
596 std::string controllerName;
598 bool daemonized =
false;
599 bool allowReuse_ =
false;
600 bool reusing_ =
false;