GazeController.cpp
Go to the documentation of this file.
1 
2 #include "GazeController.h"
3 
4 #include <VirtualRobot/IK/GazeIK.h>
5 #include <VirtualRobot/Nodes/RobotNode.h>
6 #include <VirtualRobot/Nodes/RobotNodePrismatic.h>
7 #include <VirtualRobot/Robot.h>
8 #include <VirtualRobot/RobotNodeSet.h>
9 #include <VirtualRobot/VirtualRobot.h>
10 
15 #include <ArmarXCore/interface/observers/VariantBase.h>
16 
20 #include <RobotAPI/components/units/RobotUnit/RobotUnit.h> // FIXME avoid this
23 
26 #include <armarx/view_selection/gaze_controller/gaze_ik/aron/ControllerConfig.aron.generated.h>
28 
29 #include <range/v3/range/conversion.hpp>
30 #include <range/v3/view/zip.hpp>
31 
33 {
34 
37 
39  const NJointControllerConfigPtr& config,
41  {
42  ARMARX_RT_LOGF("Creating gaze controller");
43  // config
44  ConfigPtrT cfg = ConfigPtrT::dynamicCast(config);
46  // ARMARX_CHECK_EXPRESSION(!cfg->nodeSetName.empty());
47 
48  ARMARX_CHECK_EXPRESSION(robotUnit);
49 
50  const auto configData = arondto::Config::FromAron(cfg->config);
51 
52  // robot
53  ARMARX_RT_LOGF("Setting up nodes");
54  {
55  _rtRobot = useSynchronizedRtRobot();
56  ARMARX_CHECK_NOT_NULL(_rtRobot);
57  _rtRobot->setThreadsafe(false);
58 
59  _robotAdditionalTask = _rtRobot->clone();
60  _robotAdditionalTask->setThreadsafe(false);
61  RobotState initialState;
62  initialState.globalRobotPose = _rtRobot->getGlobalPose();
63 
64  ARMARX_INFO << "Using nodeset `" << configData.params.nodeSetName << "`.";
65  _headNodeSet = _robotAdditionalTask->getRobotNodeSet(configData.params.nodeSetName);
66  ARMARX_CHECK_NOT_NULL(_headNodeSet);
67  ARMARX_INFO << VAROUT(_headNodeSet->size());
68 
69  for (const auto& [name, value] : _robotAdditionalTask->getJointValues())
70  {
71  initialState.jointValues.push_back(value);
72 
73  const auto node = _rtRobot->getRobotNode(name);
74  ARMARX_CHECK_NOT_NULL(node) << name;
75  _rtRobotNodes.push_back(node);
76 
77  _additionalTaskRobotNodeNames.push_back(name);
78  }
79 
80  ARMARX_CHECK_EQUAL(initialState.jointValues.size(), _rtRobotNodes.size());
81 
82  _robotStateBuffer_rtToAdditionalTask.reinitAllBuffers(initialState);
83  Config initialConfig;
84  fromAron(configData, initialConfig);
85 
86  if (initialConfig.target.has_value())
87  {
88  ARMARX_INFO << VAROUT(initialConfig.target->position);
89  }
90  else
91  {
92  ARMARX_INFO << "No initial target provided.";
93  }
94 
95  _configBuffer_updateConfigToAdditionalTask.reinitAllBuffers(initialConfig);
96  ARMARX_CHECK_NOT_NULL(_headNodeSet);
97 
98  const auto tcpNode = _headNodeSet->getTCP();
99  _virtualPrismaticJoint =
100  std::dynamic_pointer_cast<VirtualRobot::RobotNodePrismatic>(tcpNode);
101  ARMARX_CHECK_NOT_NULL(_virtualPrismaticJoint);
102 
103  ARMARX_INFO << "Setting up GazeIK.";
104  _gazeIK = std::make_unique<VirtualRobot::GazeIK>(_headNodeSet, _virtualPrismaticJoint);
105  _gazeIK->enableJointLimitAvoidance(configData.params.enableJointLimitAvoidance);
106  _gazeIK->setup(configData.params.maxPositionError,
107  configData.params.maxLoops,
108  configData.params.maxGradientDecentSteps);
109  _gazeIK->setVerbose(false);
110 
111  // ARMARX_CHECK_NOT_NULL(_rtTorsoNode);
112  // joint positions to be controlled
113 
114  ARMARX_INFO << "Requesting control targets";
115  std::vector<float> controlTargets;
116 
117  for (const auto& nodeName : _headNodeSet->getNodeNames())
118  {
119  if (nodeName == _virtualPrismaticJoint->getName())
120  {
121  continue;
122  }
123 
124  ARMARX_INFO << "Using control target `" << nodeName << "`.";
125  auto& target = _rtCtrlTargets.emplace_back(
126  useControlTarget<armarx::ControlTarget1DoFActuatorPosition>(
127  nodeName, ControlModes::Position1DoF));
129  target->position = 0;
130 
131  const auto node = _headNodeSet->getNode(nodeName);
132  ARMARX_CHECK_NOT_NULL(node) << nodeName;
133  // controlTargets.emplace_back(node->getJointValue());
134  controlTargets.emplace_back(0);
135  }
136  reinitTripleBuffer(controlTargets);
137  }
138 
139 
140  ARMARX_RT_LOGF("Nodes set up successfully");
141  }
142 
144 
145  void
147  const Ice::Current& /*iceCurrent*/)
148  {
149  ARMARX_INFO << "Controller::updateConfig";
150 
151  auto updateConfigDto = arondto::Config::FromAron(dto);
152 
153  Config config;
154  fromAron(updateConfigDto, config);
155 
156  if (config.target.has_value())
157  {
158  ARMARX_INFO << VAROUT(config.target->position.frame);
159  }
160 
161  _configBuffer_updateConfigToAdditionalTask.getWriteBuffer() = config;
162  _configBuffer_updateConfigToAdditionalTask.commitWrite();
163  }
164 
165  void
167  {
168  runTask("GazeControllerAdditionalTask",
169  [&]
170  {
171  CycleUtil c(10);
172  getObjectScheduler()->waitForObjectStateMinimum(eManagedIceObjectStarted);
173  ARMARX_IMPORTANT << "Create a new thread alone PlatformTrajectory controller";
174  while (getState() == eManagedIceObjectStarted)
175  {
176  if (isControllerActive() and rtReady.load())
177  {
178  ARMARX_VERBOSE << "additional task";
179  additionalTask();
180  }
181  c.waitForCycleDuration();
182  }
183  });
184  }
185 
186  void
188  {
189  }
190 
191  std::string
192  GazeController::getClassName(const Ice::Current&) const
193  {
195  }
196 
197  void
198  GazeController::rtRun(const IceUtil::Time& /*sensorValuesTimestamp*/,
199  const IceUtil::Time& /*timeSinceLastIteration*/)
200  {
202 
203  // update control devices
204  ARMARX_CHECK_EQUAL(_rtCtrlTargets.size(), rtGetControlStruct().size());
205  for (std::size_t i = 0; i < _rtCtrlTargets.size(); i++)
206  {
207  _rtCtrlTargets.at(i)->position = rtGetControlStruct().at(i);
208  }
209 
210  // read data (for non-rt)
211  _robotStateBuffer_rtToAdditionalTask.getWriteBuffer().globalRobotPose =
212  rtGetRobot()->getGlobalPose();
213 
214  ARMARX_CHECK_EQUAL(_robotStateBuffer_rtToAdditionalTask.getWriteBuffer().jointValues.size(),
215  _rtRobotNodes.size());
216  for (std::size_t i = 0; i < _rtRobotNodes.size(); i++)
217  {
218  ARMARX_CHECK_NOT_NULL(_rtRobotNodes.at(i)) << i;
219  _robotStateBuffer_rtToAdditionalTask.getWriteBuffer().jointValues.at(i) =
220  _rtRobotNodes.at(i)->getJointValue();
221  }
222 
223  _robotStateBuffer_rtToAdditionalTask.commitWrite();
224  }
225 
226  void
228  {
229  rtReady.store(true);
230  }
231 
232  void
234  {
235  rtReady.store(false);
236  }
237 
238  void
241  const DebugObserverInterfacePrx& debugObserver)
242  {
243 
244  const float currentPitchAngle = _publishCurrentPitchAngle;
245  const float currentYawAngle = _publishCurrentYawAngle;
246  const float targetPitchAngle = _publishTargetPitchAngle;
247  const float targetYawAngle = _publishTargetYawAngle;
248 
249  StringVariantBaseMap datafields;
250  datafields["currentPitchAngle"] = new Variant(currentPitchAngle);
251  datafields["currentYawAngle"] = new Variant(currentYawAngle);
252  datafields["targetPitchAngle"] = new Variant(targetPitchAngle);
253  datafields["targetYawAngle"] = new Variant(targetYawAngle);
254  if (_gazeTarget_rtRunToPublishing.updateReadBuffer())
255  {
256  gaze_targets::GazeTarget target = _gazeTarget_rtRunToPublishing.getReadBuffer();
257  // this->publishTarget(target);
258  }
259  debugObserver->setDebugChannel(getInstanceName(), datafields);
260  }
261 
262  void
263  GazeController::additionalTask()
264  {
265  const auto& configBuffer =
266  _configBuffer_updateConfigToAdditionalTask.getUpToDateReadBuffer();
267  const auto& robotStateBuffer = _robotStateBuffer_rtToAdditionalTask.getUpToDateReadBuffer();
268 
269  // update robot
270  _robotAdditionalTask->setGlobalPose(robotStateBuffer.globalRobotPose);
271 
272  ARMARX_CHECK_EQUAL(_additionalTaskRobotNodeNames.size(),
273  robotStateBuffer.jointValues.size());
274  const std::map<std::string, float> jointPositions =
275  ranges::views::zip(_additionalTaskRobotNodeNames, robotStateBuffer.jointValues) |
276  ranges::to<std::map>();
277 
278  _robotAdditionalTask->setJointValues(jointPositions);
279 
280  if (not configBuffer.target.has_value())
281  {
282  // likely, look straight
283  auto& w = getWriterControlStruct();
284  std::fill(w.begin(), w.end(), 0); // set targets to 0
286  return;
287  }
288 
289  ARMARX_CHECK_NOT_NULL(_gazeIK);
290  ARMARX_CHECK(configBuffer.target.has_value());
291  ARMARX_CHECK_NOT_EMPTY(configBuffer.target->position.frame);
292 
293  const Eigen::Vector3f globalPosition =
294  configBuffer.target->position.toGlobalEigen(_robotAdditionalTask);
295  ARMARX_VERBOSE << deactivateSpam(5) << "Trying to solve IK for target global position "
296  << globalPosition;
297  const bool solutionFound = _gazeIK->solve(globalPosition);
298 
299  // store result
300  if (solutionFound)
301  {
302  for (std::size_t i = 0; i < _headNodeSet->getSize(); i++)
303  {
304  if (auto node = _headNodeSet->getNode(i); node != _headNodeSet->getTCP())
305  {
306  getWriterControlStruct().at(i) = node->getJointValue();
307  }
308 
309  ARMARX_DEBUG << _headNodeSet->getNode(i)->getName() << ": "
310  << _headNodeSet->getNode(i)->getJointValue();
311  }
312  }
313  else
314  {
316  << "No IK solution found for Gaze IK to global target "
317  << globalPosition;
318  }
320 
321  // store results (onPublish)
322  }
323 
325  GazeController::getConfig(const ::Ice::Current&)
326  {
327  ARMARX_ERROR << "NYI";
328  return nullptr;
329  }
330 } // namespace armarx::view_selection::gaze_controller::gaze_ik
armarx::NJointControllerWithTripleBuffer< ControlTarget >::reinitTripleBuffer
void reinitTripleBuffer(const ControlTarget &initial)
Definition: NJointControllerWithTripleBuffer.h:68
armarx::view_selection::gaze_controller::gaze_ik::GazeController::updateConfig
void updateConfig(const ::armarx::aron::data::dto::DictPtr &dto, const Ice::Current &iceCurrent=Ice::emptyCurrent) override
Definition: GazeController.cpp:146
armarx::Variant
The Variant class is described here: Variants.
Definition: Variant.h:223
ARMARX_RT_LOGF
#define ARMARX_RT_LOGF(...)
Definition: ControlThreadOutputBuffer.h:285
ARMARX_VERBOSE
#define ARMARX_VERBOSE
Definition: Logging.h:187
armarx::view_selection::common::ControllerType::GazeControllerGazeIK
@ GazeControllerGazeIK
armarx::NJointControllerBase::getInstanceName
std::string getInstanceName(const Ice::Current &=Ice::emptyCurrent) const final override
Definition: NJointControllerBase.h:804
armarx::TripleBuffer::getWriteBuffer
T & getWriteBuffer()
Definition: TripleBuffer.h:92
armarx::NJointControllerRegistration
Definition: NJointControllerRegistry.h:74
armarx::NJointControllerBase::useSynchronizedRtRobot
const VirtualRobot::RobotPtr & useSynchronizedRtRobot(bool updateCollisionModel=false)
Requests a VirtualRobot for use in rtRun *.
Definition: NJointController.cpp:293
armarx::NJointControllerWithTripleBuffer< ControlTarget >::rtGetControlStruct
const ControlTarget & rtGetControlStruct() const
Definition: NJointControllerWithTripleBuffer.h:32
armarx::StringVariantBaseMap
std::map< std::string, VariantBasePtr > StringVariantBaseMap
Definition: ManagedIceObject.h:110
ARMARX_IMPORTANT
#define ARMARX_IMPORTANT
Definition: Logging.h:190
armarx::view_selection::gaze_controller::gaze_ik::GazeController::rtRun
void rtRun(const IceUtil::Time &sensorValuesTimestamp, const IceUtil::Time &timeSinceLastIteration) override
TODO make protected and use attorneys.
Definition: GazeController.cpp:198
armarx::view_selection::gaze_controller::gaze_ik::fromAron
void fromAron(const arondto::Config &dto, Config &bo)
Definition: aron_conversions.cpp:35
armarx::view_selection::gaze_controller::gaze_ik::GazeController::~GazeController
~GazeController() override
RobotUnit.h
armarx::TripleBuffer::commitWrite
void commitWrite()
Definition: TripleBuffer.h:163
armarx::view_selection::gaze_controller::gaze_ik::RegistrationControllerGazeController
const armarx::NJointControllerRegistration< GazeController > RegistrationControllerGazeController(common::ControllerTypeNames.to_name(common::ControllerType::GazeControllerGazeIK))
ARMARX_CHECK_NOT_NULL
#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...
Definition: ExpressionException.h:206
armarx::view_selection::gaze_controller::gaze_ik::GazeController::rtPostDeactivateController
void rtPostDeactivateController() override
This function is called after the controller is deactivated.
Definition: GazeController.cpp:233
boost::target
Vertex target(const detail::edge_base< Directed, Vertex > &e, const PCG &)
Definition: point_cloud_graph.h:668
armarx::CycleUtil
This util class helps with keeping a cycle time during a control cycle.
Definition: CycleUtil.h:40
armarx::ManagedIceObject::getState
int getState() const
Retrieve current state of the ManagedIceObject.
Definition: ManagedIceObject.cpp:769
controller_types.h
c
constexpr T c
Definition: UnscentedKalmanFilterTest.cpp:46
armarx::NJointControllerBase::ConfigPtrT
NJointControllerConfigPtr ConfigPtrT
Definition: NJointControllerBase.h:587
ARMARX_CHECK_NOT_EMPTY
#define ARMARX_CHECK_NOT_EMPTY(c)
Definition: ExpressionException.h:224
armarx::view_selection::gaze_targets::GazeTarget
Business Object (BO) class of GazeTarget.
Definition: GazeTarget.h:39
armarx::NJointControllerWithTripleBuffer< ControlTarget >::getWriterControlStruct
ControlTarget & getWriterControlStruct()
Definition: NJointControllerWithTripleBuffer.h:54
armarx::view_selection::gaze_controller::gaze_ik::GazeController::rtPreActivateController
void rtPreActivateController() override
This function is called before the controller is activated.
Definition: GazeController.cpp:227
GazeController.h
ARMARX_CHECK
#define ARMARX_CHECK(expression)
Shortcut for ARMARX_CHECK_EXPRESSION.
Definition: ExpressionException.h:82
IceInternal::Handle
Definition: forward_declarations.h:8
armarx::NJointControllerBase::rtGetRobot
const VirtualRobot::RobotPtr & rtGetRobot()
TODO make protected and use attorneys.
Definition: NJointControllerBase.h:846
armarx::detail::ControlThreadOutputBufferEntry
Definition: ControlThreadOutputBuffer.h:182
cxxopts::value
std::shared_ptr< Value > value()
Definition: cxxopts.hpp:855
armarx::view_selection::common::ControllerTypeNames
const simox::meta::EnumNames< ControllerType > ControllerTypeNames
Definition: controller_types.h:19
armarx::view_selection::gaze_controller::gaze_ik::GazeController::onInitNJointController
void onInitNJointController() override
Definition: GazeController.cpp:166
FramedPose.h
armarx::view_selection::gaze_controller::gaze_ik::Config::target
std::optional< armarx::view_selection::gaze_controller::Target > target
Definition: GazeController.h:56
armarx::NJointControllerBase::isControllerActive
bool isControllerActive(const Ice::Current &=Ice::emptyCurrent) const final override
Definition: NJointControllerBase.h:778
armarx::NJointControllerBase::runTask
void runTask(const std::string &taskName, Task &&task)
Executes a given task in a separate thread from the Application ThreadPool.
Definition: NJointControllerBase.h:754
ARMARX_DEBUG
#define ARMARX_DEBUG
Definition: Logging.h:184
ControlModes.h
armarx::NJointControllerWithTripleBuffer< ControlTarget >::rtUpdateControlStruct
bool rtUpdateControlStruct()
Definition: NJointControllerWithTripleBuffer.h:38
armarx::view_selection::gaze_controller::gaze_ik::GazeController::GazeController
GazeController(RobotUnitPtr robotUnit, const NJointControllerConfigPtr &config, const VirtualRobot::RobotPtr &robot)
Definition: GazeController.cpp:38
armarx::NJointControllerWithTripleBuffer< ControlTarget >::writeControlStruct
void writeControlStruct()
Definition: NJointControllerWithTripleBuffer.h:44
armarx::TripleBuffer::getReadBuffer
const T & getReadBuffer() const
Definition: TripleBuffer.h:108
ArmarXObjectScheduler.h
ControlTarget1DoFActuator.h
ARMARX_ERROR
#define ARMARX_ERROR
Definition: Logging.h:196
armarx::view_selection::gaze_controller::gaze_ik
This file is part of ArmarX.
Definition: aron_conversions.cpp:29
armarx::view_selection::gaze_controller::gaze_ik::GazeController::onConnectNJointController
void onConnectNJointController() override
Definition: GazeController.cpp:187
armarx::armem::Time
armarx::core::time::DateTime Time
Definition: forward_declarations.h:13
CycleUtil.h
ExpressionException.h
armarx::aron::data::DictPtr
std::shared_ptr< Dict > DictPtr
Definition: Dict.h:41
ARMARX_CHECK_EXPRESSION
#define ARMARX_CHECK_EXPRESSION(expression)
This macro evaluates the expression and if it turns out to be false it will throw an ExpressionExcept...
Definition: ExpressionException.h:73
ARMARX_INFO
#define ARMARX_INFO
Definition: Logging.h:181
VAROUT
#define VAROUT(x)
Definition: StringHelpers.h:198
IceUtil::Handle< class RobotUnit >
IceInternal::ProxyHandle<::IceProxy::armarx::DebugDrawerInterface >
aron_conversions.h
armarx::view_selection::gaze_controller::gaze_ik::Config
Definition: GazeController.h:53
armarx::Logging::deactivateSpam
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.
Definition: Logging.cpp:99
ControlThreadOutputBuffer.h
Logging.h
armarx::TripleBuffer::getUpToDateReadBuffer
const T & getUpToDateReadBuffer() const
Definition: TripleBuffer.h:116
ARMARX_CHECK_EQUAL
#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...
Definition: ExpressionException.h:130
ARMARX_WARNING
#define ARMARX_WARNING
Definition: Logging.h:193
armarx::view_selection::gaze_controller::gaze_ik::GazeController::getClassName
std::string getClassName(const Ice::Current &=Ice::emptyCurrent) const override
Definition: GazeController.cpp:192
armarx::view_selection::gaze_controller::gaze_ik::GazeController::getConfig
::armarx::aron::data::dto::DictPtr getConfig(const ::Ice::Current &=::Ice::emptyCurrent) override
Definition: GazeController.cpp:325
armarx::TripleBuffer::reinitAllBuffers
std::enable_if< std::is_copy_constructible< U >::value >::type reinitAllBuffers(const T &init)
Definition: TripleBuffer.h:171
NJointControllerRegistry.h
armarx::ManagedIceObject::getObjectScheduler
ArmarXObjectSchedulerPtr getObjectScheduler() const
Definition: ManagedIceObject.cpp:776
aron_conversions.h
armarx::view_selection::gaze_controller::gaze_ik::GazeController::onPublish
void onPublish(const SensorAndControl &, const DebugDrawerInterfacePrx &, const DebugObserverInterfacePrx &) override
Definition: GazeController.cpp:239
VirtualRobot::RobotPtr
std::shared_ptr< class Robot > RobotPtr
Definition: Bus.h:19
armarx::TripleBuffer::updateReadBuffer
bool updateReadBuffer() const
Swaps in the hidden buffer if it contains new data.
Definition: TripleBuffer.h:143