25#include <SimoxUtility/algorithm/string/string_tools.h>
41#define RAWFORCE "_rawforcevectors"
42#define OFFSETFORCE "_forceswithoffsetvectors"
43#define FILTEREDFORCE "_filteredforcesvectors"
44#define RAWTORQUE "_rawtorquevectors"
45#define OFFSETTORQUE "_torqueswithoffsetvectors"
46#define FORCETORQUEVECTORS "_forceTorqueVectors"
47#define POD_SUFFIX "_pod"
58 this->topicName = topicName;
64 if (topicName.empty())
86 auto sensorRobotNodeSplit =
88 for (
auto& elem : sensorRobotNodeSplit)
90 simox::alg::trim(elem);
92 if (
split.size() >= 2)
94 sensorRobotNodeMapping.emplace(
95 simox::alg::trim_copy(
split.at(0)),
96 std::make_pair(simox::alg::trim_copy(
split.at(1)),
97 split.size() >= 3 ? simox::alg::trim_copy(
split.at(2)) :
""));
117 "visualizerFunction");
118 visualizerTask->start();
122 &ForceTorqueObserver::updateRobot,
127 updateRobotTask->start();
142 auto batchPrx = debugDrawer->ice_batchOneway();
144 std::unique_lock lock(dataMutex);
146 std::set<std::string> frameAlreadyReported;
157 if (frameAlreadyReported.count(value->frame) > 0 ||
158 (value->frame !=
GlobalFrame && !value->frame.empty() &&
159 !localRobot->hasRobotNode(value->frame)))
163 frameAlreadyReported.insert(value->frame);
164 auto force = value->toGlobal(localRobot);
166 << channel.first <<
" : " << force->toEigen()
167 <<
" original frame: " << value->frame;
169 float forceMag = force->toEigen().norm() * forceFactor;
171 new Vector3(localRobot->getRobotNode(value->frame)->getGlobalPose());
172 forceMag = std::min(1.0f, forceMag);
173 batchPrx->setArrowVisu(
"Forces",
174 "Force" + channel.first,
177 DrawColor{forceMag, 1.0f - forceMag, 0.0f, 0.5f},
178 std::max(arrowLength * forceMag, 10.f),
181 field = DatafieldRefPtr::dynamicCast(
187 Eigen::Vector3f dirXglobal =
188 FramedDirection(Eigen::Vector3f::UnitX(), torque->frame, torque->agent)
190 Eigen::Vector3f dirYglobal =
191 FramedDirection(Eigen::Vector3f::UnitY(), torque->frame, torque->agent)
193 Eigen::Vector3f dirZglobal =
194 FramedDirection(Eigen::Vector3f::UnitZ(), torque->frame, torque->agent)
197 if (fabs(torque->x) > torqueVisuDeadZone)
199 batchPrx->setCircleArrowVisu(
"Torques",
200 "TorqueX" + channel.first,
204 torque->x / maxTorque,
205 3 * std::max(1.0f, torque->x / maxTorque),
206 DrawColor{1.0f, 0.0f, 0.0f, 0.5f});
210 batchPrx->removeCircleVisu(
"Torques",
"TorqueX" + channel.first);
212 if (fabs(torque->y) > torqueVisuDeadZone)
214 batchPrx->setCircleArrowVisu(
"Torques",
215 "TorqueY" + channel.first,
219 torque->y / maxTorque,
220 3 * std::max(1.0f, torque->y / maxTorque),
221 DrawColor{0.0f, 1.0f, 0.0f, 0.5f});
225 batchPrx->removeCircleVisu(
"Torques",
"TorqueY" + channel.first);
227 if (fabs(torque->z) > torqueVisuDeadZone)
229 batchPrx->setCircleArrowVisu(
"Torques",
230 "TorqueZ" + channel.first,
234 torque->z / maxTorque,
235 3 * std::max(1.0f, torque->z / maxTorque),
236 DrawColor{0.0f, 0.0f, 1.0f, 0.5f});
240 batchPrx->removeCircleVisu(
"Torques",
"TorqueZ" + channel.first);
254 batchPrx->ice_flushBatchRequests();
265 ForceTorqueObserver::updateRobot()
267 std::unique_lock lock(dataMutex);
272 ForceTorqueObserver::offerValue(
const std::string& nodeName,
273 const std::string& type,
274 const FramedDirectionBasePtr& value,
286 ARMARX_INFO <<
"Creating force/torque fields for node " << nodeName <<
" with id "
287 <<
id->getIdentifierStr();
293 type +
" vectors on specific parts of the robot.");
298 "3D vector for " + type +
" of " + nodeName);
304 std::string pod_channelName =
id->channelName +
POD_SUFFIX;
309 values[
id->datafieldName +
"_x"] =
new Variant(vec->x);
310 values[
id->datafieldName +
"_y"] =
new Variant(vec->y);
311 values[
id->datafieldName +
"_z"] =
new Variant(vec->z);
312 values[
id->datafieldName +
"_frame"] =
new Variant(vec->frame);
321 id->datafieldName +
" on " + nodeName +
" as plain old data (pod)");
324 pod_channelName, id->datafieldName +
"_x", Variant(vec->x), type +
" on X axis");
326 pod_channelName, id->datafieldName +
"_y", Variant(vec->y), type +
" on Y axis");
328 pod_channelName, id->datafieldName +
"_z", Variant(vec->z), type +
" on Z axis");
330 id->datafieldName +
"_frame",
332 "Frame of " +
value->frame);
338 const FramedDirectionBasePtr& forces,
339 const FramedDirectionBasePtr& torques,
340 const Ice::Current&
c)
342 std::unique_lock lock(dataMutex);
344 auto offerForceAndTorqueValue = [=,
this](std::string
const& sensorNodeName,
345 std::string
const& frame,
346 std::string channelName,
347 const FramedDirectionBasePtr& forces,
348 const FramedDirectionBasePtr& torques)
356 if (channelName.empty())
365 offerValue(sensorNodeName, id->datafieldName, forces,
id);
370 if (channelName.empty())
379 offerValue(sensorNodeName, id->datafieldName, torques,
id);
385 catch (std::exception&)
387 ARMARX_ERROR <<
"Reporting force torque for " << sensorNodeName <<
" failed! ";
399 realTorques->changeFrame(localRobot, forces->frame);
402 offerForceAndTorqueValue(sensorNodeName, forces->frame,
"", realForces, realTorques);
404 auto sensorMappingRange = sensorRobotNodeMapping.equal_range(sensorNodeName);
405 for (
auto iter = sensorMappingRange.first; iter != sensorMappingRange.second; ++iter)
407 auto& sensorName = iter->first;
408 auto& robotNodeName = iter->second.first;
409 auto& channelName = iter->second.second;
411 FramedDirectionPtr torquesCopy = FramedDirectionPtr::dynamicCast(realTorques->clone());
412 forcesCopy->changeFrame(localRobot, robotNodeName);
413 torquesCopy->changeFrame(localRobot, robotNodeName);
415 offerForceAndTorqueValue(
416 sensorName, robotNodeName, channelName, forcesCopy, torquesCopy);
422 const DatafieldRefBasePtr& forceTorqueDatafieldRef,
435 throw UserException(
"No sensor for node '" + nodeName +
"'available: channel " +
441 throw UserException(
"No sensor for node '" + nodeName +
"'available: datafield " +
445 return new DatafieldRef(
this, id->channelName, id->datafieldName);
455 throw UserException(
"No sensor for node '" + nodeName +
"'available: channel " +
461 throw UserException(
"No sensor for node '" + nodeName +
"'available: datafield " +
465 return new DatafieldRef(
this, id->channelName, id->datafieldName);
471 std::string channelName;
473 if (frame == nodeName)
475 channelName = nodeName;
479 channelName = nodeName +
"_" + frame;
482 std::string datafieldName =
"forces";
490 std::string channelName;
492 if (frame == nodeName)
494 channelName = nodeName;
498 channelName = nodeName +
"_" + frame;
501 std::string datafieldName =
"torques";
511 visualizerTask->stop();
515 updateRobotTask->stop();
SpamFilterDataPtr deactivateSpam(SpamFilterDataPtr const &spamFilter, float deactivationDurationSec, const std::string &identifier, bool deactivate)
std::string getConfigIdentifier()
Retrieve config identifier for this component as set in constructor.
Property< PropertyType > getProperty(const std::string &name)
Checks if the numbers published in the relevant data fields equal reference value with respect to a t...
Checks if the numbers published in the relevant data fields equal a reference value.
Checks if the numbers published in the relevant data fields are larger than a reference value.
Checks if the numbers published in the relevant data fields are smaller than a reference value.
Checks if the relevant data fields have been updated since the installation of this condition.
DataFieldIdentifier provide the basis to identify data field within a distributed ArmarX scenario.
The DatafieldRef class is similar to the ChannelRef, but points to a specific Datafield instead of to...
void reportSensorValues(const std::string &sensorNodeName, const FramedDirectionBasePtr &forces, const FramedDirectionBasePtr &torques, const Ice::Current &) override
void onConnectObserver() override
Framework hook.
void setTopicName(std::string topicName)
void onExitObserver() override
Framework hook.
void onDisconnectComponent() override
Hook for subclass.
DatafieldRefBasePtr getForceDatafield(const std::string &nodeName, const Ice::Current &) override
DatafieldRefBasePtr getTorqueDatafield(const std::string &nodeName, const Ice::Current &) override
DataFieldIdentifierPtr getTorqueDatafieldId(const std::string &nodeName, const std::string &frame)
PropertyDefinitionsPtr createPropertyDefinitions() override
void visualizerFunction()
void onInitObserver() override
Framework hook.
DatafieldRefBasePtr createNulledDatafield(const DatafieldRefBasePtr &forceTorqueDatafieldRef, const Ice::Current &) override
DataFieldIdentifierPtr getForceDatafieldId(const std::string &nodeName, const std::string &frame)
FramedDirection is a 3 dimensional direction vector with a reference frame.
Eigen::Vector3f toGlobalEigen(const SharedRobotInterfacePrx &referenceRobot) const
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.
bool usingProxy(const std::string &name, const std::string &endpoints="")
Registers a proxy for retrieval after initialization and adds it to the dependency list.
void usingTopic(const std::string &name, bool orderedPublishing=false)
Registers a proxy for subscription after initialization.
std::string getName() const
Retrieve name of object.
Ice::ObjectPrx getProxy(long timeoutMs=0, bool waitForScheduler=true) const
Returns the proxy of this object (optionally it waits for the proxy)
DatafieldRefBasePtr createFilteredDatafield(const DatafieldFilterBasePtr &filter, const DatafieldRefBasePtr &datafieldRef)
This function creates a new datafield with new filter on the given datafield.
bool existsChannel(const std::string &channelName) const
void offerChannel(std::string channelName, std::string description)
Offer a channel.
void offerConditionCheck(std::string checkName, ConditionCheck *conditionCheck)
Offer a condition check.
void updateChannel(const std::string &channelName, const std::set< std::string > &updatedDatafields=std::set< std::string >())
Update all conditions for a channel.
void setDataFieldsFlatCopy(const std::string &channelName, const StringVariantBaseMap &datafieldValues, bool triggerFilterUpdate=true)
void offerDataFieldWithDefault(std::string channelName, std::string datafieldName, const Variant &defaultValue, std::string description)
Offer a datafield with default value.
bool existsDataField(const std::string &channelName, const std::string &datafieldName) const
ChannelRegistry getAvailableChannels(bool includeMetaChannels)
Retrieve information on all sensory data channels available from the observer.
void setDataFieldFlatCopy(const std::string &channelName, const std::string &datafieldName, const VariantPtr &value, bool triggerFilterUpdate=true)
bool offerOrUpdateDataField(std::string channelName, std::string datafieldName, const Variant &value, const std::string &description)
The periodic task executes one thread method repeatedly using the time period specified in the constr...
static VirtualRobot::RobotPtr createLocalCloneFromFile(RobotStateComponentInterfacePrx robotStatePrx, VirtualRobot::RobotIO::RobotDescription loadMode=VirtualRobot::RobotIO::eFull)
This is a convenience function for createLocalClone, which automatically gets the filename from the R...
static bool synchronizeLocalClone(VirtualRobot::RobotPtr robot, RobotStateComponentInterfacePrx robotStatePrx)
The OffsetFilter class returns values relative to value from the first call of the filter.
#define ARMARX_INFO
The normal logging level.
#define ARMARX_ERROR
The logging level for unexpected behaviour, that must be fixed.
#define ARMARX_DEBUG
The logging level for output that is only interesting while debugging.
std::string const GlobalFrame
Variable of the global coordinate system.
This file offers overloads of toIce() and fromIce() functions for STL container types.
std::vector< std::string > split(const std::string &source, const std::string &splitBy, bool trimElements=false, bool removeEmptyElements=false)
IceInternal::Handle< Vector3 > Vector3Ptr
std::map< std::string, VariantBasePtr > StringVariantBaseMap
std::vector< std::string > Split(const std::string &source, const std::string &splitBy, bool trimElements=false, bool removeEmptyElements=false)
IceInternal::Handle< FramedDirection > FramedDirectionPtr
IceInternal::Handle< DatafieldRef > DatafieldRefPtr
IceUtil::Handle< class PropertyDefinitionContainer > PropertyDefinitionsPtr
PropertyDefinitions smart pointer type.
IceInternal::Handle< DataFieldIdentifier > DataFieldIdentifierPtr
Typedef of DataFieldIdentifierPtr as IceInternal::Handle<DataFieldIdentifier> for convenience.
std::shared_ptr< Value > value()