10#include <Ice/Current.h>
11#include <IceUtil/Time.h>
13#include <range/v3/range/conversion.hpp>
14#include <range/v3/view/zip.hpp>
16#include <VirtualRobot/IK/GazeIK.h>
17#include <VirtualRobot/Nodes/RobotNode.h>
18#include <VirtualRobot/Nodes/RobotNodePrismatic.h>
19#include <VirtualRobot/Robot.h>
20#include <VirtualRobot/RobotNodeSet.h>
21#include <VirtualRobot/VirtualRobot.h>
28#include <ArmarXCore/interface/core/ManagedIceObjectDefinitions.h>
29#include <ArmarXCore/interface/observers/ObserverInterface.h>
30#include <ArmarXCore/interface/observers/VariantBase.h>
38#include <RobotAPI/interface/aron/Aron.h>
39#include <RobotAPI/interface/units/RobotUnit/NJointController.h>
40#include <RobotAPI/interface/visualization/DebugDrawerInterface.h>
45#include <armarx/view_selection/gaze_controller/gaze_ik/aron/ControllerConfig.aron.generated.h>
56 const NJointControllerConfigPtr& config,
61 ConfigPtrT cfg = ConfigPtrT::dynamicCast(config);
67 const auto configData = arondto::Config::FromAron(cfg->config);
74 _rtRobot->setThreadsafe(
false);
76 _robotAdditionalTask = _rtRobot->clone();
77 _robotAdditionalTask->setThreadsafe(
false);
78 RobotState initialState;
79 initialState.globalRobotPose = _rtRobot->getGlobalPose();
81 ARMARX_INFO <<
"Using nodeset `" << configData.params.nodeSetName <<
"`.";
82 _headNodeSet = _robotAdditionalTask->getRobotNodeSet(configData.params.nodeSetName);
86 for (
const auto& [name, value] : _robotAdditionalTask->getJointValues())
88 initialState.jointValues.push_back(value);
90 const auto node = _rtRobot->getRobotNode(name);
92 _rtRobotNodes.push_back(node);
94 _additionalTaskRobotNodeNames.push_back(name);
99 _robotStateBuffer_rtToAdditionalTask.reinitAllBuffers(initialState);
101 fromAron(configData, initialConfig);
105 _configBuffer_updateConfigToAdditionalTask.reinitAllBuffers(initialConfig);
108 const auto tcpNode = _headNodeSet->getTCP();
109 _virtualPrismaticJoint =
110 std::dynamic_pointer_cast<VirtualRobot::RobotNodePrismatic>(tcpNode);
114 _gazeIK = std::make_unique<VirtualRobot::GazeIK>(_headNodeSet, _virtualPrismaticJoint);
115 _gazeIK->enableJointLimitAvoidance(configData.params.enableJointLimitAvoidance);
116 _gazeIK->setup(configData.params.maxPositionError,
117 configData.params.maxLoops,
118 configData.params.maxGradientDecentSteps);
119 _gazeIK->setVerbose(
false);
125 std::vector<float> controlTargets;
127 for (
const auto& nodeName : _headNodeSet->getNodeNames())
129 if (nodeName == _virtualPrismaticJoint->getName())
134 ARMARX_INFO <<
"Using control target `" << nodeName <<
"`.";
135 auto& target = _rtCtrlTargets.emplace_back(
137 nodeName, ControlModes::Position1DoF));
139 target->position = 0;
141 const auto node = _headNodeSet->getNode(nodeName);
144 controlTargets.emplace_back(0);
156 const Ice::Current& )
160 auto updateConfigDto = arondto::Config::FromAron(dto);
167 _configBuffer_updateConfigToAdditionalTask.getWriteBuffer() = config;
168 _configBuffer_updateConfigToAdditionalTask.commitWrite();
174 runTask(
"GazeControllerAdditionalTask",
179 ARMARX_IMPORTANT <<
"Create a new thread alone PlatformTrajectory controller";
180 while (
getState() == eManagedIceObjectStarted)
187 c.waitForCycleDuration();
205 const IceUtil::Time& )
211 for (std::size_t i = 0; i < _rtCtrlTargets.size(); i++)
217 _robotStateBuffer_rtToAdditionalTask.getWriteBuffer().globalRobotPose =
220 ARMARX_CHECK_EQUAL(_robotStateBuffer_rtToAdditionalTask.getWriteBuffer().jointValues.size(),
221 _rtRobotNodes.size());
222 for (std::size_t i = 0; i < _rtRobotNodes.size(); i++)
225 _robotStateBuffer_rtToAdditionalTask.getWriteBuffer().jointValues.at(i) =
226 _rtRobotNodes.at(i)->getJointValue();
229 _robotStateBuffer_rtToAdditionalTask.commitWrite();
241 rtReady.store(
false);
250 const float currentPitchAngle = _publishCurrentPitchAngle;
251 const float currentYawAngle = _publishCurrentYawAngle;
252 const float targetPitchAngle = _publishTargetPitchAngle;
253 const float targetYawAngle = _publishTargetYawAngle;
256 datafields[
"currentPitchAngle"] =
new Variant(currentPitchAngle);
257 datafields[
"currentYawAngle"] =
new Variant(currentYawAngle);
258 datafields[
"targetPitchAngle"] =
new Variant(targetPitchAngle);
259 datafields[
"targetYawAngle"] =
new Variant(targetYawAngle);
260 if (_gazeTarget_rtRunToPublishing.updateReadBuffer())
269 GazeController::additionalTask()
271 const auto& configBuffer =
276 _robotAdditionalTask->setGlobalPose(robotStateBuffer.globalRobotPose);
279 robotStateBuffer.jointValues.size());
280 const std::map<std::string, float> jointPositions =
281 ranges::views::zip(_additionalTaskRobotNodeNames, robotStateBuffer.jointValues) |
282 ranges::to<std::map>();
284 _robotAdditionalTask->setJointValues(jointPositions);
289 const Eigen::Vector3f globalPosition =
290 configBuffer.target.position.toGlobalEigen(_robotAdditionalTask);
293 const bool solutionFound = _gazeIK->solve(globalPosition);
298 for (std::size_t i = 0; i < _headNodeSet->getSize(); i++)
300 if (
auto node = _headNodeSet->getNode(i); node != _headNodeSet->getTCP())
305 ARMARX_DEBUG << _headNodeSet->getNode(i)->getName() <<
": "
306 << _headNodeSet->getNode(i)->getJointValue();
312 <<
"No IK solution found for Gaze IK to global target "
#define ARMARX_RT_LOGF(...)
#define ARMARX_CHECK_NOT_EMPTY(c)
This util class helps with keeping a cycle time during a control cycle.
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.
ArmarXObjectSchedulerPtr getObjectScheduler() const
int getState() const
Retrieve current state of the ManagedIceObject.
bool isControllerActive(const Ice::Current &=Ice::emptyCurrent) const final override
void runTask(const std::string &taskName, Task &&task)
Executes a given task in a separate thread from the Application ThreadPool.
const VirtualRobot::RobotPtr & useSynchronizedRtRobot(bool updateCollisionModel=false)
Requests a VirtualRobot for use in rtRun *.
std::string getInstanceName(const Ice::Current &=Ice::emptyCurrent) const final override
const VirtualRobot::RobotPtr & rtGetRobot()
TODO make protected and use attorneys.
ControlTargetBase * useControlTarget(const std::string &deviceName, const std::string &controlMode)
Declares to calculate the ControlTarget for the given ControlDevice in the given ControlMode when rtR...
const ControlTarget & rtGetControlStruct() const
void writeControlStruct()
bool rtUpdateControlStruct()
ControlTarget & getWriterControlStruct()
void reinitTripleBuffer(const ControlTarget &initial)
const T & getUpToDateReadBuffer() const
The Variant class is described here: Variants.
std::string getClassName(const Ice::Current &=Ice::emptyCurrent) const override
::armarx::aron::data::dto::DictPtr getConfig(const ::Ice::Current &=::Ice::emptyCurrent) override
GazeController(RobotUnitPtr robotUnit, const NJointControllerConfigPtr &config, const VirtualRobot::RobotPtr &robot)
void onPublish(const SensorAndControl &, const DebugDrawerInterfacePrx &, const DebugObserverInterfacePrx &) override
void onInitNJointController() override
~GazeController() override
void rtPostDeactivateController() override
This function is called after the controller is deactivated.
void rtRun(const IceUtil::Time &sensorValuesTimestamp, const IceUtil::Time &timeSinceLastIteration) override
TODO make protected and use attorneys.
void onConnectNJointController() override
void updateConfig(const ::armarx::aron::data::dto::DictPtr &dto, const Ice::Current &iceCurrent=Ice::emptyCurrent) override
void rtPreActivateController() override
This function is called before the controller is activated.
control::ConfigurableNJointControllerConfigPtr ConfigPtrT
Business Object (BO) class of GazeTarget.
#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_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_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_IMPORTANT
The logging level for always important information, but expected behaviour (in contrast to ARMARX_WAR...
#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.
#define ARMARX_WARNING
The logging level for unexpected behaviour, but not a serious problem.
#define ARMARX_VERBOSE
The logging level for verbose information.
std::shared_ptr< class Robot > RobotPtr
::IceInternal::Handle< Dict > DictPtr
const simox::meta::EnumNames< ControllerType > ControllerTypeNames
This file is part of ArmarX.
const armarx::NJointControllerRegistration< GazeController > RegistrationControllerGazeController(common::ControllerTypeNames.to_name(common::ControllerType::GazeControllerGazeIK))
void fromAron(const arondto::Config &dto, Config &bo)
::IceInternal::ProxyHandle<::IceProxy::armarx::DebugObserverInterface > DebugObserverInterfacePrx
std::map< std::string, VariantBasePtr > StringVariantBaseMap
IceUtil::Handle< class RobotUnit > RobotUnitPtr
::IceInternal::ProxyHandle<::IceProxy::armarx::DebugDrawerInterface > DebugDrawerInterfacePrx
detail::ControlThreadOutputBufferEntry SensorAndControl
armarx::view_selection::gaze_controller::Target target