51 GetStatusReportedActive(
const NJointControllerBasePtr& nJointCtrl)
53 return nJointCtrl->statusReportedActive;
57 GetStatusReportedRequested(
const NJointControllerBasePtr& nJointCtrl)
59 return nJointCtrl->statusReportedRequested;
63 UpdateStatusReported(
const NJointControllerBasePtr& nJointCtrl)
65 nJointCtrl->statusReportedActive = nJointCtrl->isActive.load();
66 nJointCtrl->statusReportedRequested = nJointCtrl->isRequested.load();
70 Publish(
const NJointControllerBasePtr& nJointCtrl,
75 nJointCtrl->publish(sac, draw, observer);
79 DeactivatePublishing(
const NJointControllerBasePtr& nJointCtrl,
83 nJointCtrl->deactivatePublish(draw, observer);
95 static const std::string&
96 GetSensorDeviceName(
Publisher* p, std::size_t idx)
98 return p->
_module<
Devices>().sensorDevices.at(idx)->getDeviceName();
110 static const std::vector<RobotUnitSubUnitPtr>&
125 static const std::map<std::string, NJointControllerBasePtr>&
132 RemoveNJointControllersToBeDeleted(
Publisher* p,
bool blocking, RobotUnitListenerPrx l)
147 ProcessEmergencyStopRequest(
Publisher* p)
157 Publisher::publishNJointClassNames()
164 if (lastReportedClasses.size() != classNames.size())
166 for (
const auto& name : classNames)
168 if (!lastReportedClasses.count(name))
170 robotUnitListenerBatchPrx->nJointControllerClassAdded(name);
171 lastReportedClasses.emplace(name);
177 return new TimedVariant{TimestampVariant{end - beg}, lastControlThreadTimestamp};
189 auto debugDrawerBatchPrx = debugDrawerPrx->ice_batchOneway();
190 auto debugObserverBatchPrx = debugObserverPrx->ice_batchOneway();
191 NJointControllerStatusSeq allStatus;
192 for (
const auto& pair :
193 ControllerManagementAttorneyForPublisher::GetNJointControllers(
this))
196 const NJointControllerBasePtr& nJointCtrl = pair.second;
199 NJointControllerAttorneyForPublisher::Publish(
200 nJointCtrl, controlThreadOutputBuffer, debugDrawerBatchPrx, debugObserverBatchPrx);
201 if (NJointControllerAttorneyForPublisher::GetStatusReportedActive(nJointCtrl) !=
202 nJointCtrl->isControllerActive() ||
203 NJointControllerAttorneyForPublisher::GetStatusReportedRequested(nJointCtrl) !=
204 nJointCtrl->isControllerRequested())
206 NJointControllerAttorneyForPublisher::UpdateStatusReported(nJointCtrl);
207 allStatus.emplace_back(nJointCtrl->getControllerStatus());
211 timingMap[
"NJointControllerUpdates_" + nJointCtrl->getInstanceName()] =
212 new TimedVariant{TimestampVariant{endInner - begInner}, lastControlThreadTimestamp};
215 robotUnitListenerBatchPrx->nJointControllerStatusChanged(allStatus);
216 debugObserverBatchPrx->ice_flushBatchRequests();
217 debugDrawerBatchPrx->ice_flushBatchRequests();
220 return new TimedVariant{TimestampVariant{end - beg}, lastControlThreadTimestamp};
226 const JointAndNJointControllers& activatedControllers)
234 for (
const RobotUnitSubUnitPtr& rsu : UnitsAttorneyForPublisher::GetSubUnits(
this))
236 if (rsu && rsu->getObjectScheduler() && rsu->getProxy())
239 rsu->update(controlThreadOutputBuffer, activatedControllers);
241 timingMap[
"UnitUpdate_" + rsu->getName()] =
new TimedVariant{
242 TimestampVariant{endInner - begInner}, lastControlThreadTimestamp};
247 return new TimedVariant{TimestampVariant{end - beg}, lastControlThreadTimestamp};
251 Publisher::publishControlUpdates(
const SensorAndControl& controlThreadOutputBuffer,
252 bool haveSensorAndControlValsChanged,
253 bool publishToObserver,
254 const JointAndNJointControllers& activatedControllers,
255 const std::vector<JointController*>& requestedJointControllers)
263 ControlDeviceStatusSeq allStatus;
264 for (std::size_t ctrlidx = 0; ctrlidx < _module<Devices>().getNumberOfControlDevices();
267 const ControlDevice& ctrlDev = *(
_module<Devices>().getControlDevices().at(ctrlidx));
269 StringToStringVariantBaseMapMap variants;
270 ControlDeviceStatus
status;
271 const auto activeJointCtrl = activatedControllers.jointControllers.at(ctrlidx);
272 status.activeControlMode = activeJointCtrl
273 ? activeJointCtrl->getControlMode()
274 : std::string{
"!!JointController is nullptr!!"};
275 status.deviceName = ctrlDev.getDeviceName();
278 auto additionalDatafields =
279 activeJointCtrl->publish(debugDrawerPrx, debugObserverPrx);
280 for (
auto& pair : additionalDatafields)
282 ctrlDevMap[ctrlDev.getDeviceName() +
"_" + activeJointCtrl->getControlMode() +
283 "_" + pair.first] = pair.second;
287 for (
const auto& ctrlVal : controlThreadOutputBuffer.control.at(ctrlidx))
289 const auto& controlMode = ctrlVal->getControlMode();
290 variants[controlMode] = ctrlVal->toVariants(lastControlThreadTimestamp);
291 if (haveSensorAndControlValsChanged && !variants[controlMode].
empty() &&
292 observerPublishControlTargets && publishToObserver)
294 for (
const auto& pair : variants[controlMode])
296 ctrlDevMap[
status.deviceName +
"_" + pair.first] = pair.second;
302 status.requestedControlMode = requestedJointControllers.at(ctrlidx)->getControlMode();
303 status.controlTargetValues = std::move(variants);
304 status.timestampUSec = lastControlThreadTimestamp.toMicroSeconds();
305 allStatus.emplace_back(
status);
308 robotUnitListenerBatchPrx->controlDeviceStatusChanged(allStatus);
309 if (observerPublishControlTargets)
311 if (robotUnitObserver->getState() >= eManagedIceObjectStarted)
313 robotUnitObserver->offerOrUpdateDataFieldsFlatCopy_async(
314 robotUnitObserver->controlDevicesChannel, std::move(ctrlDevMap));
319 return new TimedVariant{TimestampVariant{end - beg}, lastControlThreadTimestamp};
323 Publisher::publishSensorUpdates(
bool publishToObserver,
334 SensorDeviceStatusSeq allStatus;
335 for (std::size_t sensidx = 0; sensidx < numSensorDev; ++sensidx)
338 const SensorValueBase& sensVal = *(controlThreadOutputBuffer.sensors.at(sensidx));
339 auto variants = sensVal.toVariants(lastControlThreadTimestamp);
341 if (!variants.empty())
343 SensorDeviceStatus
status;
344 status.deviceName = DevicesAttorneyForPublisher::GetSensorDeviceName(
this, sensidx);
347 if (observerPublishSensorValues && publishToObserver)
349 for (
const auto& pair : variants)
351 sensorDevMap[
status.deviceName +
"_" + pair.first] = pair.second;
355 status.sensorValue = std::move(variants);
356 status.timestampUSec = lastControlThreadTimestamp.toMicroSeconds();
357 allStatus.emplace_back(
status);
362 robotUnitListenerBatchPrx->sensorDeviceStatusChanged(allStatus);
363 if (observerPublishSensorValues)
366 if (robotUnitObserver->getState() >= eManagedIceObjectStarted)
369 for (
auto& pair : sensorDevMap)
371 s << pair.first <<
": \t"
372 << (pair.second ? pair.second->ice_id() +
"\t with datatype \t" +
380 for (
auto& pair : sensorDevMap)
382 out << pair.first <<
": "
383 << (pair.second ? pair.second->ice_id() +
389 robotUnitObserver->offerOrUpdateDataFieldsFlatCopy_async(
390 robotUnitObserver->sensorDevicesChannel, std::move(sensorDevMap));
396 return new TimedVariant{TimestampVariant{end - beg}, lastControlThreadTimestamp};
404 return robotUnitListenerTopicName;
412 return debugDrawerUpdatesTopicName;
420 return debugObserverTopicName;
429 return robotUnitListenerPrx;
438 return debugObserverPrx;
447 return debugDrawerPrx;
451 Publisher::_preOnConnectRobotUnit()
455 ARMARX_DEBUG <<
"retrieving RobotUnitListenerPrx for topic "
458 robotUnitListenerBatchPrx = robotUnitListenerPrx->ice_batchOneway();
460 ARMARX_DEBUG <<
"retrieving DebugDrawerInterfacePrx for topic "
464 ARMARX_DEBUG <<
"retrieving DebugObserverInterfacePrx for topic "
470 Publisher::_preOnInitRobotUnit()
474 robotUnitListenerTopicName =
476 debugDrawerUpdatesTopicName =
480 observerEnablePublishing =
getProperty<bool>(
"ObserverEnablePublishing").getValue();
481 observerPublishSensorValues =
getProperty<bool>(
"ObserverPublishSensorValues").getValue();
482 observerPublishControlTargets =
484 observerPublishTimingInformation =
486 observerPublishAdditionalInformation =
488 debugObserverSkipIterations =
500 Publisher::_icePropertiesInitialized()
510 Publisher::_componentPropertiesUpdated(
const std::set<std::string>& changedProperties)
514 if (changedProperties.count(
"ObserverPublishSensorValues"))
516 observerPublishSensorValues =
519 if (changedProperties.count(
"ObserverPublishControlTargets"))
521 observerPublishControlTargets =
524 if (changedProperties.count(
"ObserverPublishTimingInformation"))
526 observerPublishTimingInformation =
529 if (changedProperties.count(
"ObserverPublishAdditionalInformation"))
531 observerPublishAdditionalInformation =
534 if (changedProperties.count(
"ObserverPrintEveryNthIterations"))
536 debugObserverSkipIterations =
542 Publisher::_preFinishRunning()
549 publisherTask->stop();
550 std::this_thread::sleep_for(std::chrono::milliseconds{10});
551 while (publisherTask->isFunctionExecuting() || publisherTask->isRunning())
554 <<
"PUBLISHER TASK IS RUNNING AFTER IT WAS STOPPED!";
556 publisherTask =
nullptr;
558 std::this_thread::sleep_for(std::chrono::milliseconds{100});
561 for (
const auto& pair :
562 ControllerManagementAttorneyForPublisher::GetNJointControllers(
this))
564 ARMARX_DEBUG <<
"forcing deactivation of publishing for " << pair.first;
565 NJointControllerAttorneyForPublisher::DeactivatePublishing(
566 pair.second, debugDrawerPrx, debugObserverPrx);
571 Publisher::_postFinishControlThreadInitialization()
576 publisherTask =
new PublisherTaskT(
577 [&] {
publish({}); }, publishPeriodMs,
false,
getName() +
"_PublisherTask");
578 ARMARX_INFO <<
"starting publisher with timestep " << publishPeriodMs;
579 publisherTask->setDelayWarningTolerance(10 * publishPeriodMs);
580 if (observerEnablePublishing)
582 publisherTask->start();
616 ControlThreadAttorneyForPublisher::ProcessEmergencyStopRequest(
this);
620 ControllerManagementAttorneyForPublisher::RemoveNJointControllersToBeDeleted(
621 this,
false, robotUnitListenerBatchPrx);
623 const bool haveActivatedControllersChanged =
625 const bool haveSensorAndControlValsChanged =
628 const auto& controlThreadOutputBuffer =
631 const auto activatedControllers =
633 const auto requestedJointControllers =
638 lastControlThreadTimestamp =
641 const bool publishToObserver = !(publishIterationCount % debugObserverSkipIterations);
643 additionalMap[
"haveActivatedControllersChanged"] =
644 new TimedVariant{haveActivatedControllersChanged, lastControlThreadTimestamp};
645 additionalMap[
"haveSensorAndControlValsChanged"] =
646 new TimedVariant{haveSensorAndControlValsChanged, lastControlThreadTimestamp};
647 additionalMap[
"publishToObserver"] =
648 new TimedVariant{publishToObserver, lastControlThreadTimestamp};
649 additionalMap[
"SoftwareEmergencyStopState"] =
651 EmergencyStopState::eEmergencyStopActive
652 ?
"EmergencyStopActive"
653 :
"EmergencyStopInactive",
654 lastControlThreadTimestamp};
658 if (haveSensorAndControlValsChanged)
660 timingMap[
"UnitUpdate"] =
661 publishUnitUpdates(timingMap, controlThreadOutputBuffer, activatedControllers);
662 timingMap[
"SensorUpdates"] =
663 publishSensorUpdates(publishToObserver, controlThreadOutputBuffer);
667 const double sensSecondsAgo =
669 if (sensSecondsAgo > 1)
672 <<
"armarx::RobotUnit::publish: Last sensor value update is "
673 << sensSecondsAgo <<
" seconds ago!";
676 if (haveSensorAndControlValsChanged || haveActivatedControllersChanged)
678 timingMap[
"ControlUpdates"] = publishControlUpdates(controlThreadOutputBuffer,
679 haveSensorAndControlValsChanged,
681 activatedControllers,
682 requestedJointControllers);
685 timingMap[
"NJointControllerUpdates"] =
686 publishNJointControllerUpdates(timingMap, controlThreadOutputBuffer);
689 timingMap[
"ClassNameUpdates"] = publishNJointClassNames();
694 , lastControlThreadTimestamp
697if (publishToObserver)
699 timingMap[
"LastPublishLoop"] =
701 if (robotUnitObserver->getState() >= eManagedIceObjectStarted)
703 if (observerPublishTimingInformation)
705 robotUnitObserver->offerOrUpdateDataFieldsFlatCopy_async(
706 robotUnitObserver->additionalChannel, std::move(additionalMap));
708 if (observerPublishAdditionalInformation)
710 robotUnitObserver->offerOrUpdateDataFieldsFlatCopy_async(
711 robotUnitObserver->timingChannel, std::move(timingMap));
719 if (std::any_of(jointCtrls.begin(),
724 <<
"armarx::RobotUnit::publish: Some activated JointControllers are "
725 "reported to be nullptr! "
726 <<
"(did you forget to call rtSwitchControllerSetup()?)";
729++publishIterationCount;
#define ARMARX_STREAM_PRINTER
use this macro to write output code that is executed when printed and thus not executed if the debug ...
static TPtr create(Ice::PropertiesPtr properties=Ice::createProperties(), const std::string &configName="", const std::string &configDomain="ArmarX")
Factory method for a component.
std::string getConfigDomain()
Retrieve config domain for this component as set in constructor.
void addPropertyUser(const PropertyUserPtr &subPropertyUser)
Add additional property users here that should show up in the application help text.
Property< PropertyType > getProperty(const std::string &name)
The JointController class represents one joint in one control mode.
SpamFilterDataPtr deactivateSpam(float deactivationDurationSec=10.0f, const std::string &identifier="", bool deactivate=true) const
disables the logging for the current line for the given amount of seconds.
void offeringTopic(const std::string &name)
Registers a topic for retrival after initialization.
TopicProxyType getTopic(const std::string &name)
Returns a proxy of the specified topic.
std::string getName() const
Retrieve name of object.
ArmarXManagerPtr getArmarXManager() const
Returns the ArmarX manager used to add and remove components.
Ice::PropertiesPtr getIceProperties() const
Returns the set of Ice properties.
static std::vector< std::string > getKeys()
This class allows minimal access to private members of ControlThread in a sane fashion for Publisher.
This Module manages the ControlThread.
This class allows minimal access to private members of ControllerManagement in a sane fashion for Pub...
This Module manages NJointControllers.
This class allows minimal access to private members of Devices in a sane fashion for Publisher.
This Module manages sensor and control devices for a RobotUnit and only allows save and sane access.
RobotUnitState getRobotUnitState() const
Returns the RobotUnit's State.
T & _module()
Returns this as ref to the given type.
GuardType getGuard() const
Returns a guard to the RobotUnits mutex.
void throwIfInControlThread(const std::string &fnc) const
Throws if the current thread is the ControlThread.
void throwIfStateIsNot(const std::set< RobotUnitState > &stateSet, const std::string &fnc, bool onlyWarn=false) const
Throws an exception if the current state is not in.
bool isShuttingDown() const
Returns whether the RobotUnit is shutting down.
std::unique_lock< MutexType > GuardType
This class allows minimal access to private members of NJointControllerBase in a sane fashion for Pub...
This Module manages publishing of all data to Topics, updating of all units managed by the Units modu...
std::string getDebugObserverTopicName(const Ice::Current &=Ice::emptyCurrent) const override
Returns the name of the used DebugObserverTopic.
DebugDrawerInterfacePrx getDebugDrawerProxy(const Ice::Current &=Ice::emptyCurrent) const override
Returns the used DebugDrawerProxy.
RobotUnitListenerPrx getRobotUnitListenerProxy(const Ice::Current &=Ice::emptyCurrent) const override
Returns the used RobotUnitListenerProxy.
DebugObserverInterfacePrx getDebugObserverProxy(const Ice::Current &=Ice::emptyCurrent) const override
Returns the used DebugObserverProxy.
std::string getDebugDrawerTopicName(const Ice::Current &=Ice::emptyCurrent) const override
Returns the name of the used DebugDrawerTopic.
virtual void publish(StringVariantBaseMap additionalMap={}, StringVariantBaseMap timingMap={})
Publishes data.
std::string getRobotUnitListenerTopicName(const Ice::Current &=Ice::emptyCurrent) const override
Returns the name of the used RobotUnitListenerTopic.
This class allows minimal access to private members of Units in a sane fashion for Publisher.
This Module manages all Units of a RobotUnit.
static IceUtil::Time GetTime(TimeMode timeMode=TimeMode::VirtualTime)
Get the current time.
Implements a Variant type for timestamps.
static std::string typeToString(VariantTypeId typeId)
Return the name of the registered type typeId.
#define ARMARX_STOPWATCH(...)
#define ARMARX_CHECK_EXPRESSION(expression)
This macro evaluates the expression and if it turns out to be false it will throw an ExpressionExcept...
#define ARMARX_CHECK_EQUAL(lhs, rhs)
This macro evaluates whether lhs is equal (==) rhs and if it turns out to be false it will throw an E...
#define ARMARX_INFO
The normal logging level.
#define ARMARX_FATAL
The logging level for unexpected behaviour, that will lead to a seriously malfunctioning program and ...
#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.
double s(double t, double s0, double v0, double a0, double j)
::IceInternal::ProxyHandle<::IceProxy::armarx::DebugObserverInterface > DebugObserverInterfacePrx
std::map< std::string, VariantBasePtr > StringVariantBaseMap
IceUtil::Time mapRtTimestampToNonRtTimestamp(const IceUtil::Time &time_monotic_raw)
IceInternal::Handle< TimedVariant > TimedVariantPtr
::IceInternal::ProxyHandle<::IceProxy::armarx::DebugDrawerInterface > DebugDrawerInterfacePrx
detail::ControlThreadOutputBufferEntry SensorAndControl
bool empty(const std::string &s)