PlatformFollowerController.cpp
Go to the documentation of this file.
2 
3 #include <VirtualRobot/Nodes/RobotNode.h>
4 #include <VirtualRobot/RobotNodeSet.h>
5 #include <VirtualRobot/math/Helpers.h>
6 
12 
15 
18 #include <armarx/control/njoint_controller/platform/platform_follower_controller/aron/PlatformFollowerControllerConfig.aron.generated.h>
20 
22 {
23  const std::string NAME = "PlatformFollowerController";
24 
26 
28  const armarx::NJointControllerConfigPtr& config,
30  {
31  // config
32  ConfigPtrT cfg = ConfigPtrT::dynamicCast(config);
34  // ARMARX_CHECK_EXPRESSION(!cfg->nodeSetName.empty());
35 
36  ARMARX_CHECK_EXPRESSION(robotUnit);
37 
38  const auto robot = useSynchronizedRtRobot();
39 
40  platformTarget = useControlTarget(robotUnit->getRobotPlatformName(),
41  armarx::ControlModes::HolonomicPlatformVelocity)
43  ARMARX_CHECK_EXPRESSION(platformTarget)
44  << "The actuator " << robotUnit->getRobotPlatformName() << " has no control mode "
45  << armarx::ControlModes::HolonomicPlatformVelocity;
46 
47  const Config configData = ::armarx::fromAron<arondto::Config, Config>(cfg->config);
48 
50  configBuffer.reinitAllBuffers(configData);
51 
52  // TODO init tcps
53  const VirtualRobot::RobotNodeSetPtr rnsRight =
54  robot->getRobotNodeSet(configData.params.nodeSetNameRight);
55  ARMARX_CHECK(rnsRight);
56  const VirtualRobot::RobotNodeSetPtr rnsLeft =
57  robot->getRobotNodeSet(configData.params.nodeSetNameLeft);
58  ARMARX_CHECK(rnsLeft);
59  tcpRight = rnsRight->getTCP();
60  tcpLeft = rnsLeft->getTCP();
61  }
62 
63  std::string
64  Controller::getClassName(const Ice::Current& iceCurrent) const
65  {
66  return NAME;
67  }
68 
69  void
70  Controller::rtRun(const IceUtil::Time& sensorValuesTimestamp,
71  const IceUtil::Time& timeSinceLastIteration)
72  {
73  // update state
74  stateBuffer.getWriteBuffer().handPositionRight = tcpRight->getPositionInRootFrame();
75  stateBuffer.getWriteBuffer().handPositionLeft = tcpLeft->getPositionInRootFrame();
76  stateBuffer.getWriteBuffer().time = armarx::Clock::Now();
77  stateBuffer.getWriteBuffer().currentVel.setZero();
78  stateBuffer.commitWrite();
79 
80  // write control targets
82 
83  // FIXME remove
84  //platformTarget->velocityX = 0;
85  //platformTarget->velocityY = 0;
86  //platformTarget->velocityRotation = 0;
87 
88  // FIXME uncomment
89  platformTarget->velocityX = rtGetControlStruct().platformVelocityTargets.x;
90  platformTarget->velocityY = rtGetControlStruct().platformVelocityTargets.y;
91  platformTarget->velocityRotation = rtGetControlStruct().platformVelocityTargets.yaw;
92  }
93 
94  void
96  const Ice::Current& iceCurrent)
97  {
98  ARMARX_IMPORTANT << "Controller::updateConfig";
99 
100  // TODO maybe update pid controller
101 
102  auto updateConfig = ::armarx::fromAron<arondto::Config, Config>(dto);
103  configBuffer.reinitAllBuffers(updateConfig);
104  }
105 
106  void
108  {
109  if (not rtReady.load())
110  {
111  // store result
112  getWriterControlStruct().platformVelocityTargets.x = 0;
113  getWriterControlStruct().platformVelocityTargets.y = 0;
114  getWriterControlStruct().platformVelocityTargets.yaw = 0;
115 
117  }
118 
119  configBuffer.updateReadBuffer();
120  stateBuffer.updateReadBuffer();
121 
122  const auto state = stateBuffer.getReadBuffer();
123  const auto params = configBuffer.getReadBuffer().params;
124 
125  const double deltaT = (state.time - additionalTaskData.lastTime).toSecondsDouble();
126  additionalTaskData.lastTime = state.time;
127 
128  if (deltaT == 0)
129  return;
130 
131  const Eigen::Vector3f currentVel = state.currentVel;
132  const Eigen::Vector3f currentPositionRight = state.handPositionRight;
133  const Eigen::Vector3f currentPositionLeft = state.handPositionLeft;
134  const Eigen::Vector3f positionDeltaRight =
135  currentPositionRight - initialState.handPositionRight;
136  const Eigen::Vector3f positionDeltaLeft =
137  currentPositionLeft - initialState.handPositionLeft;
138 
139  Eigen::Vector2f positionDelta = ((positionDeltaLeft + positionDeltaRight) / 2).head<2>();
140  Eigen::Vector2f velocity = Eigen::Vector2f::Zero();
141  if (positionDelta.norm() >= params.minPosTolerance)
142  {
143  positionDelta =
144  positionDelta - params.minPosTolerance * positionDelta / positionDelta.norm();
145  velocity = positionDelta * params.kPos - currentVel.head<2>() * params.dPos;
146  }
147  const float Tstar = 1 / ((params.filterTimeConstant / deltaT) + 1);
148  additionalTaskData.filteredLinearVel =
149  Tstar * (velocity - additionalTaskData.filteredLinearVel) +
150  additionalTaskData.filteredLinearVel;
151  if (!std::isfinite(additionalTaskData.filteredLinearVel(0)))
152  {
153  additionalTaskData.filteredLinearVel(0) = 0;
154  }
155  if (!std::isfinite(additionalTaskData.filteredLinearVel(1)))
156  {
157  additionalTaskData.filteredLinearVel(1) = 0;
158  }
159  velocity = additionalTaskData.filteredLinearVel.norm() > params.maxPosVel
160  ? additionalTaskData.filteredLinearVel.normalized() * params.maxPosVel
161  : additionalTaskData.filteredLinearVel;
162 
163 
164  const Eigen::Vector3f currentDirection = state.direction();
165  const float cosAlpha = currentDirection.dot(initialState.direction());
166  const Eigen::Vector3f directionDiff = currentDirection - initialState.direction();
167  float alpha = 0;
168  if (directionDiff(1) < 0)
169  {
170  alpha = -acos(cosAlpha);
171  }
172  else
173  {
174  alpha = acos(cosAlpha);
175  }
176  float angularVelocity;
177  if (fabs(alpha) < params.minAngleTolerance)
178  {
179  angularVelocity = 0;
180  }
181  else
182  {
183  if (alpha > 0)
184  {
185  alpha -= params.minAngleTolerance;
186  }
187  else
188  {
189  alpha += params.minAngleTolerance;
190  }
191  angularVelocity = params.kAngle * alpha - params.dAngle * currentVel.z();
192  }
193  additionalTaskData.filteredAngularVel =
194  Tstar * (angularVelocity - additionalTaskData.filteredAngularVel) +
195  additionalTaskData.filteredAngularVel;
196  if (!std::isfinite(additionalTaskData.filteredAngularVel))
197  {
198  additionalTaskData.filteredAngularVel = 0;
199  }
200  angularVelocity = std::min(additionalTaskData.filteredAngularVel, params.maxAngleVel);
201 
202 
203  {
204  auto& onPublishData = onPublishBuffer.getWriteBuffer();
205 
206  onPublishData.target.platformVelocityTargets.x = velocity.x();
207  onPublishData.target.platformVelocityTargets.y = velocity.y();
208  onPublishData.target.platformVelocityTargets.yaw = angularVelocity;
209 
210  onPublishData.position_error_left = positionDeltaLeft;
211  onPublishData.position_error_right = positionDeltaRight;
212  onPublishBuffer.commitWrite();
213  }
214 
215 
216  // store result
217  getWriterControlStruct().platformVelocityTargets.x = velocity.x();
218  getWriterControlStruct().platformVelocityTargets.y = velocity.y();
219  getWriterControlStruct().platformVelocityTargets.yaw = angularVelocity;
220 
222  }
223 
224  void
226  const armarx::DebugDrawerInterfacePrx& /*debugDrawer*/,
227  const armarx::DebugObserverInterfacePrx& debugObservers)
228  {
229  armarx::StringVariantBaseMap datafields;
230 
231  onPublishBuffer.updateReadBuffer();
232  const auto& data = onPublishBuffer.getReadBuffer();
233 
234  datafields["vx"] = new armarx::Variant(data.target.platformVelocityTargets.x);
235  datafields["vy"] = new armarx::Variant(data.target.platformVelocityTargets.y);
236  datafields["vyaw"] = new armarx::Variant(data.target.platformVelocityTargets.yaw);
237 
238  datafields["position_error_left_x"] = new armarx::Variant(data.position_error_left.x());
239  datafields["position_error_left_y"] = new armarx::Variant(data.position_error_left.y());
240  datafields["position_error_left_z"] = new armarx::Variant(data.position_error_left.z());
241  datafields["position_error_right_x"] = new armarx::Variant(data.position_error_right.x());
242  datafields["position_error_right_y"] = new armarx::Variant(data.position_error_right.y());
243  datafields["position_error_right_z"] = new armarx::Variant(data.position_error_right.z());
244 
245  debugObservers->setDebugChannel(NAME, datafields);
246  }
247 
248  void
250  {
251  runTask(NAME + "AdditionalTask",
252  [&]
253  {
255  4); // please don't set this to 0 as it is the rtRun/control thread
258 
259  armarx::CycleUtil c(10);
260  getObjectScheduler()->waitForObjectStateMinimum(
261  armarx::eManagedIceObjectStarted);
262  ARMARX_IMPORTANT << "Create a new thread alone PlatformTrajectory controller";
263  while (getState() == armarx::eManagedIceObjectStarted)
264  {
265  if (isControllerActive() and rtReady.load())
266  {
267  ARMARX_VERBOSE << "additional task";
268  additionalTask();
269  }
270  c.waitForCycleDuration();
271  }
272  });
273 
274  ARMARX_INFO << "PlatformTrajectoryVelocityController::onInitNJointController";
275  }
276 
277  void
279  {
280  initialState.handPositionRight = tcpRight->getPositionInRootFrame();
281  initialState.handPositionLeft = tcpLeft->getPositionInRootFrame();
282  initialState.time = armarx::core::time::DateTime::Now();
283 
284  ARMARX_INFO << "Init done.";
285 
286  rtReady.store(true);
287  }
288 
289  Controller::~Controller() = default;
290 
291 } // namespace armarx::control::njoint_controller::platform::platform_follower_controller
armarx::NJointControllerWithTripleBuffer< Target >::reinitTripleBuffer
void reinitTripleBuffer(const Target &initial)
Definition: NJointControllerWithTripleBuffer.h:68
armarx::ControlTargetHolonomicPlatformVelocity
Brief description of class ControlTargetHolonomicPlatformVelocity.
Definition: ControlTargetHolonomicPlatformVelocity.h:38
armarx::control::njoint_controller::platform::platform_follower_controller
This file is part of ArmarX.
Definition: aron_conversions.cpp:27
armarx::ControlTargetBase::asA
const T * asA() const
Definition: ControlTargetBase.h:76
armarx::Variant
The Variant class is described here: Variants.
Definition: Variant.h:223
ARMARX_VERBOSE
#define ARMARX_VERBOSE
Definition: Logging.h:187
armarx::control::njoint_controller::platform::platform_follower_controller::Controller::Controller
Controller(const armarx::RobotUnitPtr &robotUnit, const armarx::NJointControllerConfigPtr &config, const VirtualRobot::RobotPtr &)
Definition: PlatformFollowerController.cpp:27
armarx::control::ethercat::RTUtility::RT_THREAD_PRIORITY
static constexpr int RT_THREAD_PRIORITY
The thread priority for rt-threads.
Definition: RTUtility.h:24
armarx::control::njoint_controller::platform::platform_follower_controller::Config::params
Params params
Definition: PlatformFollowerController.h:62
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::control::njoint_controller::platform::platform_follower_controller::Controller::onInitNJointController
void onInitNJointController() override
Definition: PlatformFollowerController.cpp:249
armarx::NJointControllerWithTripleBuffer< Target >::rtGetControlStruct
const Target & rtGetControlStruct() const
Definition: NJointControllerWithTripleBuffer.h:32
armarx::StringVariantBaseMap
std::map< std::string, VariantBasePtr > StringVariantBaseMap
Definition: ManagedIceObject.h:110
armarx::control::njoint_controller::platform::platform_follower_controller::Registration
const armarx::NJointControllerRegistration< Controller > Registration(NAME)
ARMARX_IMPORTANT
#define ARMARX_IMPORTANT
Definition: Logging.h:190
PlatformFollowerController.h
armarx::TripleBuffer::commitWrite
void commitWrite()
Definition: TripleBuffer.h:163
armarx::core::time::DateTime::Now
static DateTime Now()
Definition: DateTime.cpp:51
armarx::NJointControllerBase::useControlTarget
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...
Definition: NJointController.cpp:410
armarx::control::ethercat::RTUtility::pinThreadToCPU
static bool pinThreadToCPU(unsigned int cpu)
Pins the calling thread to the CPU with the given id.
Definition: RTUtility.cpp:52
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
c
constexpr T c
Definition: UnscentedKalmanFilterTest.cpp:46
armarx::NJointControllerBase::ConfigPtrT
NJointControllerConfigPtr ConfigPtrT
Definition: NJointControllerBase.h:587
armarx::NJointControllerWithTripleBuffer< Target >::getWriterControlStruct
Target & getWriterControlStruct()
Definition: NJointControllerWithTripleBuffer.h:54
armarx::control::njoint_controller::platform::platform_follower_controller::RobotState::time
armarx::core::time::DateTime time
Definition: PlatformFollowerController.h:49
armarx::ControlTargetHolonomicPlatformVelocity::velocityRotation
float velocityRotation
Definition: ControlTargetHolonomicPlatformVelocity.h:43
type.h
ARMARX_CHECK
#define ARMARX_CHECK(expression)
Shortcut for ARMARX_CHECK_EXPRESSION.
Definition: ExpressionException.h:82
Clock.h
armarx::control::njoint_controller::platform::platform_follower_controller::RobotState::handPositionRight
Eigen::Vector3f handPositionRight
Definition: PlatformFollowerController.h:46
armarx::control::njoint_controller::platform::platform_follower_controller::Controller::additionalTask
void additionalTask()
Definition: PlatformFollowerController.cpp:107
std::isfinite
bool isfinite(const std::vector< T, Ts... > &v)
Definition: algorithm.h:366
armarx::detail::ControlThreadOutputBufferEntry
Definition: ControlThreadOutputBuffer.h:182
armarx::control::njoint_controller::platform::platform_follower_controller::Controller::getClassName
std::string getClassName(const Ice::Current &iceCurrent=Ice::emptyCurrent) const override
Definition: PlatformFollowerController.cpp:64
if
if(!yyvaluep)
Definition: Grammar.cpp:645
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
data
uint8_t data[1]
Definition: EtherCATFrame.h:68
armarx::NJointControllerWithTripleBuffer< Target >::rtUpdateControlStruct
bool rtUpdateControlStruct()
Definition: NJointControllerWithTripleBuffer.h:38
armarx::NJointControllerWithTripleBuffer< Target >::writeControlStruct
void writeControlStruct()
Definition: NJointControllerWithTripleBuffer.h:44
armarx::TripleBuffer::getReadBuffer
const T & getReadBuffer() const
Definition: TripleBuffer.h:108
ArmarXObjectScheduler.h
armarx::control::njoint_controller::platform::platform_follower_controller::Controller::rtPreActivateController
void rtPreActivateController() override
This function is called before the controller is activated.
Definition: PlatformFollowerController.cpp:278
armarx::ControlTargetHolonomicPlatformVelocity::velocityX
float velocityX
Definition: ControlTargetHolonomicPlatformVelocity.h:41
armarx::control::ethercat::RTUtility::elevateThreadPriority
static bool elevateThreadPriority(int priority)
Elevate the thread priority of the calling thread to the given priority.
Definition: RTUtility.cpp:17
armarx::armem::Time
armarx::core::time::DateTime Time
Definition: forward_declarations.h:13
armarx::ControlTargetHolonomicPlatformVelocity::velocityY
float velocityY
Definition: ControlTargetHolonomicPlatformVelocity.h:42
armarx::control::njoint_controller::platform::platform_follower_controller::Controller::rtRun
void rtRun(const IceUtil::Time &sensorValuesTimestamp, const IceUtil::Time &timeSinceLastIteration) override
TODO make protected and use attorneys.
Definition: PlatformFollowerController.cpp:70
CycleUtil.h
ExpressionException.h
armarx::control::njoint_controller::platform::platform_follower_controller::NAME
const std::string NAME
Definition: PlatformFollowerController.cpp:23
armarx::aron::data::DictPtr
std::shared_ptr< Dict > DictPtr
Definition: Dict.h:41
ControlTargetHolonomicPlatformVelocity.h
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
IceUtil::Handle< class RobotUnit >
armarx::control::njoint_controller::platform::platform_follower_controller::RobotState::handPositionLeft
Eigen::Vector3f handPositionLeft
Definition: PlatformFollowerController.h:47
IceInternal::ProxyHandle<::IceProxy::armarx::DebugDrawerInterface >
armarx::core::time::Clock::Now
static DateTime Now()
Current time on the virtual clock.
Definition: Clock.cpp:93
aron_conversions.h
armarx::control::njoint_controller::platform::platform_follower_controller::RobotState::direction
Eigen::Vector3f direction() const
Definition: PlatformFollowerController.h:52
Logging.h
min
T min(T t1, T t2)
Definition: gdiam.h:44
armarx::control::njoint_controller::platform::platform_follower_controller::Controller::updateConfig
void updateConfig(const ::armarx::aron::data::dto::DictPtr &dto, const Ice::Current &iceCurrent=Ice::emptyCurrent) override
Definition: PlatformFollowerController.cpp:95
armarx::control::njoint_controller::platform::platform_follower_controller::Config
Definition: PlatformFollowerController.h:58
armarx::control::njoint_controller::platform::platform_follower_controller::Controller::onPublish
void onPublish(const armarx::SensorAndControl &sac, const armarx::DebugDrawerInterfacePrx &debugDrawer, const armarx::DebugObserverInterfacePrx &debugObservers) override
Definition: PlatformFollowerController.cpp:225
armarx::control::njoint_controller::platform::platform_follower_controller::Controller::~Controller
~Controller() override
armarx::TripleBuffer::reinitAllBuffers
std::enable_if< std::is_copy_constructible< U >::value >::type reinitAllBuffers(const T &init)
Definition: TripleBuffer.h:171
RTUtility.h
NJointControllerRegistry.h
armarx::ManagedIceObject::getObjectScheduler
ArmarXObjectSchedulerPtr getObjectScheduler() const
Definition: ManagedIceObject.cpp:776
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