GazeController.cpp
Go to the documentation of this file.
1 #include "GazeController.h"
2 
3 #include <SimoxUtility/math/convert/mat3f_to_rpy.h>
4 #include <VirtualRobot/Nodes/RobotNode.h>
5 #include <VirtualRobot/Robot.h>
6 #include <VirtualRobot/RobotNodeSet.h>
7 
9 #include <ArmarXCore/interface/observers/VariantBase.h>
10 
14 #include <RobotAPI/components/units/RobotUnit/RobotUnit.h> // FIXME avoid this
17 
20 #include <armarx/view_selection/gaze_controller/hemisphere/aron/ControllerConfig.aron.generated.h>
22 
24 {
25 
28 
30  const NJointControllerConfigPtr& config,
32  {
33  ARMARX_RT_LOGF("Creating gaze controller");
34  // config
35  ConfigPtrT cfg = ConfigPtrT::dynamicCast(config);
37  // ARMARX_CHECK_EXPRESSION(!cfg->nodeSetName.empty());
38 
39  ARMARX_CHECK_EXPRESSION(robotUnit);
40 
41  const armarx::view_selection::gaze_controller::hemisphere::arondto::Config configData =
42  arondto::Config::FromAron(cfg->config);
43 
44  // robot
45  ARMARX_RT_LOGF("Setting up nodes");
46  {
47  _rtRobot = useSynchronizedRtRobot();
48  _rtRobot->setThreadsafe(false);
49 
50  ARMARX_CHECK_NOT_NULL(_rtRobot);
51  _rtGazeNodeName = configData.params.gazeRootNodeName;
52  _rtGazeNode = _rtRobot->getRobotNode(_rtGazeNodeName);
53  _rtCameraNode = _rtRobot->getRobotNode(configData.params.cameraNodeName);
54  _rtHemiANode = _rtRobot->getRobotNode(configData.params.hemiANodeName);
55  _rtHemiBNode = _rtRobot->getRobotNode(configData.params.hemiBNodeName);
56  _rtYawNode = _rtRobot->getRobotNode(configData.params.yawNodeName);
57  // _rtTorsoNode = _rtRobot->getRobotNode(_config->torsoNodeName);
58  ARMARX_CHECK_NOT_NULL(_rtCameraNode);
59  ARMARX_CHECK_NOT_NULL(_rtHemiANode);
60  ARMARX_CHECK_NOT_NULL(_rtHemiBNode);
61  ARMARX_CHECK_NOT_NULL(_rtYawNode);
62  // ARMARX_CHECK_NOT_NULL(_rtTorsoNode);
63  // joint positions to be controlled
64  _rtHemiACtrlTarget = useControlTarget<armarx::ControlTarget1DoFActuatorPosition>(
65  configData.params.hemiANodeName, ControlModes::Position1DoF);
66  ARMARX_CHECK_NOT_NULL(_rtHemiACtrlTarget);
67 
68  _rtHemiBCtrlTarget = useControlTarget<armarx::ControlTarget1DoFActuatorPosition>(
69  configData.params.hemiBNodeName, ControlModes::Position1DoF);
70  ARMARX_CHECK_NOT_NULL(_rtHemiBCtrlTarget);
71 
72  //_rtPitchCtrlPos = &(_pitchCtrlTarget->position);
73  _rtYawCtrlTarget = useControlTarget<armarx::ControlTarget1DoFActuatorPosition>(
74  configData.params.yawNodeName, ControlModes::Position1DoF);
75  ARMARX_CHECK_NOT_NULL(_rtYawCtrlTarget);
76  }
77 
78  ARMARX_RT_LOGF("Nodes set up successfully");
79  }
80 
82 
83  void
85  const Ice::Current& /*iceCurrent*/)
86  {
87  // ARMARX_VERBOSE << "Controller::updateConfig";
88 
89  auto updateConfigDto = arondto::Config::FromAron(dto);
90 
91  Config config;
92  fromAron(updateConfigDto, config);
93 
94  setControlStruct(config);
95  }
96 
97  void
99  {
100  ;
101  }
102 
103  void
105  {
106  ;
107  }
108 
109  std::string
110  GazeController::getClassName(const Ice::Current&) const
111  {
112  return common::ControllerTypeNames.to_name(
114  }
115 
116  void
117  GazeController::rtRun(const IceUtil::Time& /*sensorValuesTimestamp*/,
118  const IceUtil::Time& /*timeSinceLastIteration*/)
119  {
120  const float currentYawAngle = _rtYawNode->getJointValue();
121  // const float currentPitchAngle = _rtPitchNode->getJointValue();
122  //const float h = _rtCameraNode->getPositionInRootFrame().z();
123 
124  // report debugging variables
125  _publishCurrentYawAngle = currentYawAngle;
126  // _publishCurrentPitchAngle = currentPitchAngle;
127 
128  // if target is not set, use default joint values
129  if (not rtGetControlStruct().target.has_value())
130  {
131  // report debugging variables
132  _publishTargetYawAngle = 0;
133  // _publishTargetPitchAngle = 0;
134 
135  // update control positions
136  _rtYawCtrlTarget->position = 0;
137  _rtHemiACtrlTarget->position = 0;
138  _rtHemiBCtrlTarget->position = 0;
139  return;
140  }
141 
142  auto target = rtGetControlStruct().target->position;
143  if (target.frame.empty())
144  {
145  target.frame = GlobalFrame;
146  }
147 
148  target.changeFrame(_rtRobot, _rtGazeNodeName); // Change frame to gaze root frame.
149  Eigen::Vector3f targetPoint = target.toEigen(); // In gaze root frame.
150 
151  // compute spherical targets: pitch and yaw
152  float targetYawAngle = -std::atan2(targetPoint.x(), targetPoint.y());
153 
154  // The pitch depends on the yaw because in most but one case the head reference frame
155  // (Gaze_Root) is not axis aligned with the robot root frame. We need to rotate the target
156  // point by the negative yaw angle to account for that. If this is not done, the head will
157  // show a sinusoidal movement when the platform is rotated.
158  targetPoint = Eigen::AngleAxisf(-targetYawAngle, Eigen::Vector3f::UnitZ()) * targetPoint;
159 
160  // Limit yaw range to avoid damage.
161  const bool yawTargetReachable = _rtYawNode->checkJointLimits(targetYawAngle);
162  if (not yawTargetReachable)
163  {
164  targetYawAngle = std::clamp(
165  targetYawAngle, _rtYawNode->getJointLimitLow(), _rtYawNode->getJointLimitHigh());
166  }
167 
168  // Derive target head pitch angle.
169  float targetPitchAngle = -std::atan2(targetPoint.z(), targetPoint.y());
170  // Adjust pitch to target position of hemisphere actuators using a simplified quadratic
171  // regression.
172  targetPitchAngle = (rtGetControlStruct().params.yawToHemiFactorLinear * targetPitchAngle) +
173  (rtGetControlStruct().params.yawToHemiFactorQuadratic *
174  targetPitchAngle * targetPitchAngle);
175 
176  // limit pitch range to avoid damage.
177  const bool pitchTargetReachable = _rtHemiANode->checkJointLimits(targetPitchAngle) and
178  _rtHemiBNode->checkJointLimits(targetPitchAngle);
179  if (not pitchTargetReachable)
180  {
181  targetPitchAngle = std::clamp(targetPitchAngle,
182  _rtHemiANode->getJointLimitLow(),
183  _rtHemiANode->getJointLimitHigh());
184 
185  targetPitchAngle = std::clamp(targetPitchAngle,
186  _rtHemiBNode->getJointLimitLow(),
187  _rtHemiBNode->getJointLimitHigh());
188  }
189 
190  // report debugging variables
191  _publishTargetYawAngle = targetYawAngle;
192  // _publishTargetPitchAngle = targetPitchAngle;
193 
194 
195  _publishPlatformOrientation =
196  simox::math::mat3f_to_rpy(_rtRobot->getGlobalOrientation()).z();
197 
198  // update control positions
199  _rtYawCtrlTarget->position = targetYawAngle;
200  _rtHemiACtrlTarget->position = targetPitchAngle;
201  _rtHemiBCtrlTarget->position = targetPitchAngle;
202  }
203 
204  void
206  {
207  ;
208  }
209 
210  void
212  {
213  ;
214  }
215 
216  void
219  const DebugObserverInterfacePrx& debugObserver)
220  {
221 
222  // const float currentPitchAngle = _publishCurrentPitchAngle;
223  const float currentYawAngle = _publishCurrentYawAngle.load();
224  // const float targetPitchAngle = _publishTargetPitchAngle;
225  const float targetYawAngle = _publishTargetYawAngle.load();
226 
227  StringVariantBaseMap datafields;
228  // datafields["currentPitchAngle"] = new Variant(currentPitchAngle);
229  datafields["currentYawAngle"] = new Variant(currentYawAngle);
230  // datafields["targetPitchAngle"] = new Variant(targetPitchAngle);
231  datafields["targetYawAngle"] = new Variant(targetYawAngle);
232  datafields["platformYaw"] = new Variant(_publishPlatformOrientation.load());
233  if (_tripRt2NonRt.updateReadBuffer())
234  {
236  // this->publishTarget(target);
237  }
238  debugObserver->setDebugChannel(getInstanceName(), datafields);
239  }
240 
242  GazeController::getConfig(const ::Ice::Current&)
243  {
244  ARMARX_ERROR << "NYI";
245  return nullptr;
246  }
247 } // namespace armarx::view_selection::gaze_controller::hemisphere
armarx::view_selection::gaze_controller::hemisphere::Config
Definition: GazeController.h:47
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::NJointControllerBase::getInstanceName
std::string getInstanceName(const Ice::Current &=Ice::emptyCurrent) const final override
Definition: NJointControllerBase.h:804
armarx::view_selection::common::ControllerType::GazeControllerHemisphere
@ GazeControllerHemisphere
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< Config >::rtGetControlStruct
const Config & rtGetControlStruct() const
Definition: NJointControllerWithTripleBuffer.h:32
armarx::StringVariantBaseMap
std::map< std::string, VariantBasePtr > StringVariantBaseMap
Definition: ManagedIceObject.h:110
armarx::view_selection::gaze_controller::hemisphere::GazeController::rtPreActivateController
void rtPreActivateController() override
This function is called before the controller is activated.
Definition: GazeController.cpp:205
RobotUnit.h
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::GlobalFrame
const std::string GlobalFrame
Definition: FramedPose.h:65
boost::target
Vertex target(const detail::edge_base< Directed, Vertex > &e, const PCG &)
Definition: point_cloud_graph.h:668
controller_types.h
armarx::view_selection::gaze_controller::hemisphere::GazeController::updateConfig
void updateConfig(const ::armarx::aron::data::dto::DictPtr &dto, const Ice::Current &iceCurrent=Ice::emptyCurrent) override
Definition: GazeController.cpp:84
armarx::NJointControllerBase::ConfigPtrT
NJointControllerConfigPtr ConfigPtrT
Definition: NJointControllerBase.h:587
armarx::view_selection::gaze_controller::hemisphere::GazeController::~GazeController
~GazeController() override
armarx::view_selection::gaze_targets::GazeTarget
Business Object (BO) class of GazeTarget.
Definition: GazeTarget.h:39
armarx::view_selection::gaze_controller::hemisphere::GazeController::rtPostDeactivateController
void rtPostDeactivateController() override
This function is called after the controller is deactivated.
Definition: GazeController.cpp:211
clamp
double clamp(double x, double a, double b)
Definition: point.hpp:136
IceInternal::Handle
Definition: forward_declarations.h:8
armarx::detail::ControlThreadOutputBufferEntry
Definition: ControlThreadOutputBuffer.h:182
armarx::view_selection::gaze_controller::hemisphere::GazeController::onConnectNJointController
void onConnectNJointController() override
Definition: GazeController.cpp:104
armarx::view_selection::common::ControllerTypeNames
const simox::meta::EnumNames< ControllerType > ControllerTypeNames
Definition: controller_types.h:19
FramedPose.h
armarx::view_selection::gaze_controller::hemisphere::GazeController::getConfig
::armarx::aron::data::dto::DictPtr getConfig(const ::Ice::Current &=::Ice::emptyCurrent) override
Definition: GazeController.cpp:242
ControlModes.h
armarx::view_selection::gaze_controller::hemisphere::GazeController::onPublish
void onPublish(const SensorAndControl &, const DebugDrawerInterfacePrx &, const DebugObserverInterfacePrx &) override
Definition: GazeController.cpp:217
armarx::TripleBuffer::getReadBuffer
const T & getReadBuffer() const
Definition: TripleBuffer.h:108
armarx::view_selection::gaze_controller::hemisphere::GazeController::rtRun
void rtRun(const IceUtil::Time &sensorValuesTimestamp, const IceUtil::Time &timeSinceLastIteration) override
TODO make protected and use attorneys.
Definition: GazeController.cpp:117
ControlTarget1DoFActuator.h
ARMARX_ERROR
#define ARMARX_ERROR
Definition: Logging.h:196
armarx::armem::Time
armarx::core::time::DateTime Time
Definition: forward_declarations.h:13
armarx::view_selection::gaze_controller::hemisphere::GazeController::getClassName
std::string getClassName(const Ice::Current &=Ice::emptyCurrent) const override
Definition: GazeController.cpp:110
NJointController.h
armarx::view_selection::gaze_controller::hemisphere::GazeController::onInitNJointController
void onInitNJointController() override
Definition: GazeController.cpp:98
armarx::aron::data::DictPtr
std::shared_ptr< Dict > DictPtr
Definition: Dict.h:41
armarx::view_selection::gaze_controller::hemisphere
This file is part of ArmarX.
Definition: aron_conversions.cpp:29
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::NJointControllerWithTripleBuffer< Config >::setControlStruct
void setControlStruct(const Config &newStruct)
Definition: NJointControllerWithTripleBuffer.h:60
IceUtil::Handle< class RobotUnit >
armarx::view_selection::gaze_controller::hemisphere::fromAron
void fromAron(const arondto::Config &dto, Config &bo)
Definition: aron_conversions.cpp:35
IceInternal::ProxyHandle<::IceProxy::armarx::DebugDrawerInterface >
GazeController.h
armarx::view_selection::gaze_controller::hemisphere::GazeController::GazeController
GazeController(RobotUnitPtr robotUnit, const NJointControllerConfigPtr &config, const VirtualRobot::RobotPtr &robot)
Definition: GazeController.cpp:29
ControlThreadOutputBuffer.h
aron_conversions.h
Logging.h
armarx::view_selection::gaze_controller::hemisphere::RegistrationControllerGazeController
const armarx::NJointControllerRegistration< GazeController > RegistrationControllerGazeController(common::ControllerTypeNames.to_name(common::ControllerType::GazeControllerHemisphere))
aron_conversions.h
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