GazeController.cpp
Go to the documentation of this file.
1#include "GazeController.h"
2
3#include <algorithm>
4#include <cmath>
5#include <string>
6
7#include <Ice/Current.h>
8#include <IceUtil/Time.h>
9
10#include <VirtualRobot/Nodes/RobotNode.h>
11#include <VirtualRobot/Robot.h>
12#include <VirtualRobot/RobotNodeSet.h>
13#include <VirtualRobot/VirtualRobot.h>
14
17#include <ArmarXCore/interface/observers/ObserverInterface.h>
18#include <ArmarXCore/interface/observers/VariantBase.h>
20
24#include <RobotAPI/components/units/RobotUnit/RobotUnit.h> // FIXME avoid thi>
26#include <RobotAPI/interface/aron/Aron.h>
27#include <RobotAPI/interface/units/RobotUnit/NJointController.h>
28#include <RobotAPI/interface/visualization/DebugDrawerInterface.h>
30
33#include <armarx/view_selection/gaze_controller/atan2/aron/ControllerConfig.aron.generated.h>
36
38{
39
42
44 const NJointControllerConfigPtr& config,
46 {
47 ARMARX_RT_LOGF("Creating gaze controller");
48 // config
49 ConfigPtrT cfg = ConfigPtrT::dynamicCast(config);
51 // ARMARX_CHECK_EXPRESSION(!cfg->nodeSetName.empty());
52
53 ARMARX_CHECK_EXPRESSION(robotUnit);
54
55 const armarx::view_selection::gaze_controller::atan2::arondto::Config configData =
56 arondto::Config::FromAron(cfg->config);
57
58 // robot
59 ARMARX_RT_LOGF("Setting up nodes");
60 {
61 _rtRobot = useSynchronizedRtRobot();
62 _rtRobot->setThreadsafe(false);
63
64 ARMARX_CHECK_NOT_NULL(_rtRobot);
65 _rtGazeNodeName = configData.params.gazeRootNodeName;
66 _rtCameraNode = _rtRobot->getRobotNode(configData.params.cameraNodeName);
67 _rtPitchNode = _rtRobot->getRobotNode(configData.params.pitchNodeName);
68 _rtYawNode = _rtRobot->getRobotNode(configData.params.yawNodeName);
69 // _rtTorsoNode = _rtRobot->getRobotNode(_config->torsoNodeName);
70 ARMARX_CHECK_NOT_NULL(_rtCameraNode);
71 ARMARX_CHECK_NOT_NULL(_rtPitchNode);
72 ARMARX_CHECK_NOT_NULL(_rtYawNode);
73 // ARMARX_CHECK_NOT_NULL(_rtTorsoNode);
74 // joint positions to be controlled
76 configData.params.pitchNodeName, ControlModes::Position1DoF);
77 ARMARX_CHECK_NOT_NULL(_rtPitchCtrlTarget);
78 //_rtPitchCtrlPos = &(_pitchCtrlTarget->position);
80 configData.params.yawNodeName, ControlModes::Position1DoF);
81 ARMARX_CHECK_NOT_NULL(_rtYawCtrlTarget);
82 //_rtYawCtrlPos = &(yawCtrlTarget->position);
83 }
84
85 ARMARX_RT_LOGF("Nodes set up successfully");
86 }
87
89
90 void
91 GazeController::updateConfig(const ::armarx::aron::data::dto::DictPtr& dto,
92 const Ice::Current& /*iceCurrent*/)
93 {
94 auto updateConfigDto = arondto::Config::FromAron(dto);
95
96 Config config;
97 fromAron(updateConfigDto, config);
98
99 setControlStruct(config);
100 }
101
102 void
107
108 void
113
114 std::string
119
120 void
121 GazeController::rtRun(const IceUtil::Time& /*sensorValuesTimestamp*/,
122 const IceUtil::Time& /*timeSinceLastIteration*/)
123 {
124 const float currentYawAngle = _rtYawNode->getJointValue();
125 const float currentPitchAngle = _rtPitchNode->getJointValue();
126
127 // report debugging variables
128 _publishCurrentYawAngle = currentYawAngle;
129 _publishCurrentPitchAngle = currentPitchAngle;
130
131 auto const gazeTarget = rtGetControlStruct().target;
132 auto target = gazeTarget.position;
133 if (target.frame.empty())
134 {
135 target.frame = GlobalFrame;
136 }
137
138 target.changeFrame(_rtRobot, _rtGazeNodeName); // Change frame to gaze root frame.
139 Eigen::Vector3f targetPoint = target.toEigen(); // In gaze root frame.
140
141 // compute spherical targets: pitch and yaw
142 float targetYawAngle = -std::atan2(targetPoint.x(), targetPoint.y());
143
144 // The pitch depends on the yaw because in most but one case the head reference frame
145 // (Gaze_Root) is not axis aligned with the robot root frame. We need to rotate the target
146 // point by the negative yaw angle to account for that. If this is not done, the head will
147 // show a sinusoidal movement when the platform is rotated.
148 targetPoint = Eigen::AngleAxisf(-targetYawAngle, Eigen::Vector3f::UnitZ()) * targetPoint;
149
150 // Limit yaw range to avoid damage.
151 const bool yawTargetReachable = _rtYawNode->checkJointLimits(targetYawAngle);
152 if (not yawTargetReachable)
153 {
154 targetYawAngle = std::clamp(
155 targetYawAngle, _rtYawNode->getJointLimitLow(), _rtYawNode->getJointLimitHigh());
156 }
157
158 float targetPitchAngle = -std::atan2(targetPoint.z(), targetPoint.y());
159
160 // check reachability
161 const bool pitchTargetReachable = _rtPitchNode->checkJointLimits(targetPitchAngle);
162 if (not pitchTargetReachable)
163 {
164 targetPitchAngle = std::clamp(targetPitchAngle,
165 _rtPitchNode->getJointLimitLow(),
166 _rtPitchNode->getJointLimitHigh());
167 }
168
169 // report debugging variables
170 _publishTargetYawAngle = targetYawAngle;
171 _publishTargetPitchAngle = targetPitchAngle;
172
173 // update control positions
174 _rtYawCtrlTarget->position = targetYawAngle;
175 _rtPitchCtrlTarget->position = targetPitchAngle;
176 }
177
178 void
183
184 void
189
190 void
193 const DebugObserverInterfacePrx& debugObserver)
194 {
195 const float currentPitchAngle = _publishCurrentPitchAngle;
196 const float currentYawAngle = _publishCurrentYawAngle;
197 const float targetPitchAngle = _publishTargetPitchAngle;
198 const float targetYawAngle = _publishTargetYawAngle;
199
200 StringVariantBaseMap datafields;
201 datafields["currentPitchAngle"] = new Variant(currentPitchAngle);
202 datafields["currentYawAngle"] = new Variant(currentYawAngle);
203 datafields["targetPitchAngle"] = new Variant(targetPitchAngle);
204 datafields["targetYawAngle"] = new Variant(targetYawAngle);
205
206 if (_tripRt2NonRt.updateReadBuffer())
207 {
208 gaze_targets::GazeTarget target = _tripRt2NonRt.getReadBuffer();
209 // this->publishTarget(target);
210 }
211
212 debugObserver->setDebugChannel(getInstanceName(), datafields);
213 }
214
216 GazeController::getConfig(const ::Ice::Current&)
217 {
218 ARMARX_ERROR << "NYI";
219 return nullptr;
220 }
221
222} // namespace armarx::view_selection::gaze_controller::atan2
#define ARMARX_RT_LOGF(...)
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
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...
The Variant class is described here: Variants.
Definition Variant.h:224
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 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 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.
Definition GazeTarget.h:23
#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_ERROR
The logging level for unexpected behaviour, that must be fixed.
Definition Logging.h:196
std::string const GlobalFrame
Variable of the global coordinate system.
Definition FramedPose.h:65
std::shared_ptr< class Robot > RobotPtr
Definition Bus.h:19
::IceInternal::Handle< Dict > DictPtr
const simox::meta::EnumNames< ControllerType > ControllerTypeNames
const armarx::NJointControllerRegistration< GazeController > RegistrationControllerGazeController(common::ControllerTypeNames.to_name(common::ControllerType::GazeControllerAtan2))
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
Definition FTSensor.h:34
::IceInternal::ProxyHandle<::IceProxy::armarx::DebugDrawerInterface > DebugDrawerInterfacePrx
detail::ControlThreadOutputBufferEntry SensorAndControl