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>
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);
124 withConfig(const ::armarx::aron::data::dto::DictPtr& configDict)
126 dto = AronDTO::FromAron(configDict);
133 ARMARX_CHECK(std::filesystem::is_regular_file(filename)) << filename;
137 ARMARX_INFO <<
"Loading config from file `" << filename <<
"`.";
138 std::ifstream ifs{filename};
140 nlohmann::json jsonConfig;
144 if (not this->dto.has_value())
154 this->dto->read(reader, jsonConfig);
177 this->nodeSetName = nodeSetName;
184 if (namePrefix.empty())
188 this->controllerNamePrefix = this->controllerNamePrefix +
"_" + namePrefix;
195 this->daemonized =
true;
204 std::unique_ptr<ControllerWrapper<T>>
207 const std::string controllerClassName = ControllerDescriptionType::name;
208 return create(controllerClassName);
211 std::unique_ptr<ControllerWrapper<T>>
214 if (not ensureInitialized())
219 ::armarx::control::ConfigurableNJointControllerConfigPtr
config =
220 new ::armarx::control::ConfigurableNJointControllerConfig;
223 config->config = dto.value().toAronDTO();
235 controllerName = controllerNamePrefix +
"_" + name;
236 const std::string controllerClassName = ControllerDescriptionType::name;
241 armarx::NJointControllerInterfacePrx
controller =
242 controllerCreator->getNJointController(controllerName);
243 ARMARX_DEBUG <<
"--> get controller by name from robot unit took "
246 this->reusing_ = [&]() ->
bool
261 if (
controller->getClassName() != controllerClassName)
300 ARMARX_INFO <<
"--- Deleting existing controller `" << controllerName <<
"`";
304 ARMARX_INFO <<
"--- Wait until controller is in-active";
313 ARMARX_INFO <<
"--- Controller is not active anymore, deleting controller";
327 ARMARX_INFO <<
"Reuse of controller would be possible.";
331 if (not this->reusing_)
335 ARMARX_INFO <<
"Creating controller `" << controllerName <<
"`";
337 controller = controllerCreator->createNJointController(
338 controllerClassName, controllerName,
config);
342 ARMARX_INFO <<
"Controller `" << controllerName <<
"` created.";
351 ARMARX_WARNING <<
"Failed to create controller of type `" << controllerClassName
357 armarx::control::ConfigurableNJointControllerInterfacePrx::checkedCast(
controller);
359 std::unique_ptr<ControllerWrapper<T>> ctrlWrapper =
360 std::make_unique<ControllerWrapper<T>>(
361 ctrl, controllerName, configWriter, dto.value());
362 ctrlWrapper->daemonize(daemonized);
367 ctrlWrapper->updateConfig();
373 std::unique_ptr<ControllerWrapper<T>>
375 const ::armarx::aron::data::dto::DictPtr& configDict =
nullptr,
376 const std::string& configFilename =
"",
377 bool flagActivate =
true,
378 bool flagAllowReuse =
true,
379 bool flagFromMemory =
false)
381 ARMARX_CHECK(not(configDict.get() ==
nullptr and configFilename.empty()));
390 if (configFilename.empty())
400 <<
"configuration file does not exist\n"
403 "1) if you need to configure a controller by passing configuration "
406 "controllerBuilder (me), you need to make sure the "
408 "component is running "
409 "on the same PC as your application, otherwise\n"
410 "2) use the createControllerFromConfig() interface, which does not "
413 "creator is running";
425 std::ostringstream oss;
426 for (
const auto& pair :
config().limbs)
429 if (&pair != &(*
config().limbs.rbegin()))
434 std::string robotNodeSets = oss.str();
436 if (namePrefix.empty())
449 auto ctrlWrapper =
create();
453 ARMARX_INFO <<
"using controller name " << controllerName;
459 <<
"setting nullspace target: if the default is null use the cfg from the "
460 "existing controller";
463 auto ctrlConfig = ctrlWrapper->getConfig().limbs;
464 for (
const auto& pair :
config().limbs)
466 if (not pair.second.desiredNullspaceJointAngles.has_value())
468 ctrlWrapper->config.limbs.at(pair.first).desiredNullspaceJointAngles =
469 ctrlConfig.at(pair.first).desiredNullspaceJointAngles;
483 if (not ctrlWrapper->isActive())
485 ctrlWrapper->activate();
487 while (not ctrlWrapper->isActive())
492 ARMARX_INFO <<
"Controller " << controllerName <<
" is active";
496 ARMARX_INFO <<
"User have to activate " << controllerName
497 <<
" controller in your application";
504 const ::armarx::aron::data::dto::DictPtr& configDict =
nullptr,
505 const std::string& configFilename =
"",
506 bool flagActivate =
true,
507 bool flagAllowReuse =
true,
508 bool flagFromMemory =
false)
516 auto ctrl = CtrlProxy::checkedCast(ctrlWrapper->ctrl());
520 std::unique_ptr<ControllerWrapper<T>>
522 const ::armarx::aron::data::dto::DictPtr& mpConfigDict,
523 const ::armarx::aron::data::dto::DictPtr& configDict =
nullptr,
524 const std::string& configFilename =
"",
525 bool flagActivate =
true,
526 bool flagAllowReuse =
true,
527 bool flagFromMemory =
false,
528 bool flagStart =
true)
536 auto ctrl = CtrlProxy::checkedCast(ctrlWrapper->ctrl());
537 ctrl->updateMPConfig(mpConfigDict);
551 const ::armarx::aron::data::dto::DictPtr& mpConfigDict,
552 const ::armarx::aron::data::dto::DictPtr& configDict =
nullptr,
553 const std::string& configFilename =
"",
554 bool flagActivate =
true,
555 bool flagAllowReuse =
true,
556 bool flagFromMemory =
false,
557 bool flagStart =
true)
565 auto ctrl = CtrlProxy::checkedCast(ctrlWrapper->ctrl());
568 ctrl->updateMPConfig(mpConfigDict);
569 ARMARX_DEBUG <<
"--> ctrl->updateMPConfig(mpConfigDict: DictPtr) took "
597 return this->reusing_;
603 return controllerName;
610 if (
auto cfg = configReader.getDefaultConfig(ControllerDescriptionType::name))
612 dto = AronDTO::FromAron(cfg);
623 if (not dto.has_value())
625 return initDefaultConfig();
633 const memory::config::Reader configReader;
634 const memory::config::Writer configWriter;
636 std::optional<AronDTO> dto;
638 std::optional<std::string> nodeSetName;
640 std::string controllerNamePrefix;
641 std::string controllerName;
643 bool daemonized =
false;
644 bool allowReuse_ =
false;
645 bool reusing_ =
false;
#define ARMARX_CHECK_NOT_EMPTY(c)
static void WaitFor(const Duration &duration)
Wait for a certain duration on the virtual clock.
static Duration SecondsDouble(double seconds)
Constructs a duration in seconds.
static Duration MilliSeconds(std::int64_t milliSeconds)
Constructs a duration in milliseconds.
static std::filesystem::path toSystemPath(const data::PackagePath &pp)
ControllerBuilder & withNodeSet(const std::string &nodeSetName)
ControllerBuilder & allowReuse(const bool allowReuse)
typename ControllerDescriptionType::AronDTO AronDTO
ControllerBuilder & daemonize()
ControllerBuilder & withConfig(const ::armarx::aron::data::dto::DictPtr &configDict)
std::string getControllerName()
ControllerBuilder(const armarx::RobotUnitInterfacePrx &controllerCreator, const memory::config::Reader &configProvider, const memory::config::Writer &configWriter, const std::string &controllerNamePrefix)
ControllerBuilder & withDefaultConfig(const std::string &name="default")
ControllerBuilder & withConfig(const AronDTO &dto)
std::unique_ptr< ControllerWrapper< T > > create()
Creates the controller with the default name.
CtrlProxy createGetTSComplianceCtrl(const std::string &namePrefix="", const ::armarx::aron::data::dto::DictPtr &configDict=nullptr, const std::string &configFilename="", bool flagActivate=true, bool flagAllowReuse=true, bool flagFromMemory=false)
std::unique_ptr< ControllerWrapper< T > > createTSComplianceCtrl(const std::string &namePrefix="", const ::armarx::aron::data::dto::DictPtr &configDict=nullptr, const std::string &configFilename="", bool flagActivate=true, bool flagAllowReuse=true, bool flagFromMemory=false)
ControllerBuilder & withConfig(const std::filesystem::path &filename)
ControllerBuilder & withNamePrefix(const std::string &namePrefix)
detail::proxy::ProxyType_t< ControllerDescriptionType > CtrlProxy
ControllerBuilder & withConfig(const armarx::armem::MemoryID &memoryId)
CtrlProxy createGetTSComplianceMPCtrl(const std::string &namePrefix, const ::armarx::aron::data::dto::DictPtr &mpConfigDict, const ::armarx::aron::data::dto::DictPtr &configDict=nullptr, const std::string &configFilename="", bool flagActivate=true, bool flagAllowReuse=true, bool flagFromMemory=false, bool flagStart=true)
static constexpr const char * ctrlConfigClassName
std::unique_ptr< ControllerWrapper< T > > create(const std::string &name)
ControllerBuilder & withDefaultConfigFile(const std::string &name="default", const std::string &robotNameSuffix="", const std::string &appendix="")
ControllerDescription< T > ControllerDescriptionType
std::unique_ptr< ControllerWrapper< T > > createTSComplianceMPCtrl(const std::string &namePrefix, const ::armarx::aron::data::dto::DictPtr &mpConfigDict, const ::armarx::aron::data::dto::DictPtr &configDict=nullptr, const std::string &configFilename="", bool flagActivate=true, bool flagAllowReuse=true, bool flagFromMemory=false, bool flagStart=true)
#define ARMARX_CHECK(expression)
Shortcut for ARMARX_CHECK_EXPRESSION.
#define ARMARX_CHECK_NOT_NULL(ptr)
This macro evaluates whether ptr is not null and if it turns out to be false it will throw an Express...
#define ARMARX_INFO
The normal logging level.
#define ARMARX_IMPORTANT
The logging level for always important information, but expected behaviour (in contrast to ARMARX_WAR...
#define ARMARX_DEBUG
The logging level for output that is only interesting while debugging.
#define ARMARX_WARNING
The logging level for unexpected behaviour, but not a serious problem.
#define ARMARX_VERBOSE
The logging level for verbose information.
constexpr const char * CtrlConfigClassName_v
typename ProxyType< T >::type ProxyType_t
This file is part of ArmarX.
::IceInternal::ProxyHandle<::IceProxy::armarx::RobotUnitInterface > RobotUnitInterfacePrx
std::string GetHandledExceptionString()