WholeBodyTrajectoryController.h
Go to the documentation of this file.
1/**
2 * This file is part of ArmarX.
3 *
4 * ArmarX is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 *
8 * ArmarX is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * @author Fabian Reister (fabian dot reister at kit dot edu)
17 * @date 2024
18 * @copyright http://www.gnu.org/licenses/gpl-2.0.txt
19 * GNU General Public License
20 */
21
22#pragma once
23
24#include <cstddef>
25#include <vector>
26
27#include <VirtualRobot/VirtualRobot.h>
28
32
38
39#include <armarx/control/interface/ConfigurableNJointControllerInterface.h>
41#include <armarx/control/njoint_controller/joint_space/aron/WholeBodyTrajectoryControllerConfig.aron.generated.h>
42
43namespace armarx
44{
46 class SensorValueHolonomicPlatformWithAbsolutePosition;
47 class ControlTarget1DoFActuatorVelocity;
48 class ControlTarget1DoFActuatorPosition;
49 class SensorValue1DoFActuatorPosition;
50} // namespace armarx
51
53{
54 struct Target
55 {
56 };
57
59 {
60 public:
61 using TrajectoryPoint = armarx::control::njoint_controller::joint_space::
62 whole_body_trajectory_controller::arondto::TrajectoryPoint;
63
64 using TimestampUS = std::int64_t;
65
66 Trajectory(const std::vector<TrajectoryPoint>& traj) : trajectory_(traj)
67 {
68 }
69
70 const TrajectoryPoint&
72 {
73 return trajectory_.front();
74 }
75
76 void
78 {
79 startTimestampUS_ = timestamp;
80 }
81
83 {
86
87 bool
89 {
90 return timestamp >= min and timestamp <= max;
91 }
92 };
93
94 std::optional<TrajectoryPoint>
96 {
97 ARMARX_CHECK_NOT_NULL(startTimestampUS_);
98
99 // check if timestamp is in range
100 if (not timeBounds().isWithin(timestamp))
101 {
102 if (timestamp <= timeBounds().min)
103 {
104 return trajectory_.front();
105 }
106
107 if (timestamp >= timeBounds().max)
108 {
109 return trajectory_.back();
110 }
111
112 ARMARX_WARNING << "Should not get here!";
113 return std::nullopt;
114 }
115
116 // relative timestamp wrt to start of trajectory
117 const TimestampUS relativeTimeUS = timestamp - startTimestampUS_.value();
118
119 // we assume that our trajectory is sorted (monotonically increasing timestamps)
120
121 // we identify the first element which is timewise after the current time
122
123 const auto compareFn = [](const TrajectoryPoint& lhs, const TimestampUS& val) -> bool
124 { return lhs.timestampMicroSeconds < val; };
125
126 const auto it =
127 std::lower_bound(trajectory_.begin(), trajectory_.end(), relativeTimeUS, compareFn);
128
129 // if match is first element, return it without interpolation
130 if (it == trajectory_.begin())
131 {
132 return *it;
133 }
134
135 const auto itBefore = std::prev(it);
136
137 // interpolation factor [0,1]
138 const double f = static_cast<double>(relativeTimeUS - itBefore->timestampMicroSeconds) /
139 (it->timestampMicroSeconds - itBefore->timestampMicroSeconds);
140
141
142 const auto linearInterpolate = [](const std::vector<double>& a,
143 const std::vector<double>& b,
144 const double f) -> std::vector<double>
145 {
146 // FIXME consider 2 pi bounds
147 ARMARX_CHECK_EQUAL(a.size(), b.size());
150
151 const std::size_t n = a.size();
152
153 std::vector<double> c(n);
154
155 for (std::size_t i = 0; i < n; i++)
156 {
157 c.at(i) = (1 - f) * a.at(i) + f * b.at(i);
158 }
159
160 return c;
161 };
162
163 // const auto noInterpolate = [](const std::vector<double>& a,
164 // const std::vector<double>& b,
165 // const double f) -> std::vector<double> { return b; };
166
167
169 tp.timestampMicroSeconds = timestamp;
170 tp.jointValues = linearInterpolate(itBefore->jointValues, it->jointValues, f);
171 tp.jointValuesPlatform =
172 linearInterpolate(itBefore->jointValuesPlatform, it->jointValuesPlatform, f);
173 tp.handJointValues =
174 linearInterpolate(itBefore->handJointValues, it->handJointValues, f);
175
176 tp.jointVelocities =
177 linearInterpolate(itBefore->jointVelocities, it->jointVelocities, f);
178 tp.jointVelocitiesPlatform = linearInterpolate(
179 itBefore->jointVelocitiesPlatform, it->jointVelocitiesPlatform, f);
180
181
182 return tp;
183 }
184
185 bool
187 {
188 ARMARX_CHECK_NOT_NULL(startTimestampUS_);
189
190 return timeBounds().isWithin(timestamp);
191 }
192
193 TimeInterval
195 {
196 ARMARX_CHECK_NOT_NULL(startTimestampUS_);
197
198 return {.min = trajectory_.front().timestampMicroSeconds + startTimestampUS_.value(),
199 .max = trajectory_.back().timestampMicroSeconds + startTimestampUS_.value()};
200 }
201
202 protected:
203 private:
204 const std::vector<armarx::control::njoint_controller::joint_space::
205 whole_body_trajectory_controller::arondto::TrajectoryPoint>
206 trajectory_;
207
208 std::optional<std::int64_t> startTimestampUS_;
209 };
210
212 {
213 std::int64_t localTimestamp;
214
217
218 std::vector<float> jointPosDiff;
219
220 arondto::TrajectoryPoint targetState;
221
222 Eigen::Isometry3f currentTcpPose;
223 Eigen::Isometry3f currentPlatformPose;
224
226 };
227
229 virtual public NJointControllerWithTripleBuffer<Target>,
230 virtual public core::ConfigurableNJointControllerBase<arondto::Config>
231 {
232 public:
233 Controller(const RobotUnitPtr& robotUnit,
234 const NJointControllerConfigPtr& config,
235 const VirtualRobot::RobotPtr& robot);
236
237
238 std::string getClassName(const Ice::Current& iceCurrent = Ice::emptyCurrent) const override;
239
240 void rtRun(const IceUtil::Time& sensorValuesTimestamp,
241 const IceUtil::Time& timeSinceLastIteration) override;
242
243
244 void onPublish(const SensorAndControl&,
246 const DebugObserverInterfacePrx&) override;
247
248
249 protected:
250 void rtPreActivateController() override;
251
252 virtual void onDisconnectNJointController();
253
254 void
256 {
257 // NYI
258 }
259
260 private:
261 struct ControlTargets
262 {
264 std::vector<ControlTarget1DoFActuatorVelocity*> jointTargets;
265 std::vector<ControlTarget1DoFActuatorPosition*> handTargets;
266 } controlTargets_;
267
268 const GlobalRobotLocalizationSensorDevice::SensorValueType* svGlobalRobotLocalization_;
269 std::vector<const SensorValue1DoFActuatorPosition*> jointSensorValues_;
270
271
272 std::optional<Trajectory> trajectory_;
273
274 // std::size_t trajIdx_ = 0;
275
276 MultiDimPIDController pidPlatform_;
277 PIDController opidPlatform_;
278
279 std::optional<MultiDimPIDController> pidArm_;
280
281 std::vector<std::string> jointNames_;
282 std::vector<std::string> fingerJointNames_;
283
285 VirtualRobot::RobotNodePtr rtTcpNode_;
286
287 VirtualRobot::RobotPtr debugRobot_;
288 VirtualRobot::RobotNodePtr publishTcpNode_;
289
290
291 TripleBuffer<DebugData> bufferRtToOnPublish_;
292
293
294 std::vector<DebugData> whatever_;
295 std::atomic_bool whateverFlag_ = true;
296 };
297
298} // namespace armarx::control::njoint_controller::joint_space::whole_body_trajectory_controller
std::string timestamp()
constexpr T c
Brief description of class ControlTargetHolonomicPlatformVelocity.
NJointControllerWithTripleBuffer(const Target &initialCommands=Target())
A simple triple buffer for lockfree comunication between a single writer and a single reader.
void onPublish(const SensorAndControl &, const DebugDrawerInterfacePrx &, const DebugObserverInterfacePrx &) override
Controller(const RobotUnitPtr &robotUnit, const NJointControllerConfigPtr &config, const VirtualRobot::RobotPtr &robot)
void rtRun(const IceUtil::Time &sensorValuesTimestamp, const IceUtil::Time &timeSinceLastIteration) override
TODO make protected and use attorneys.
void updateConfig(const ConfigurableNJointControllerBaseT::AronConfigT &configData) override
std::string getClassName(const Ice::Current &iceCurrent=Ice::emptyCurrent) const override
void rtPreActivateController() override
This function is called before the controller is activated.
armarx::control::njoint_controller::joint_space:: whole_body_trajectory_controller::arondto::TrajectoryPoint TrajectoryPoint
#define ARMARX_CHECK_LESS_EQUAL(lhs, rhs)
This macro evaluates whether lhs is less or equal (<=) rhs and if it turns out to be false it will th...
#define ARMARX_CHECK_GREATER_EQUAL(lhs, rhs)
This macro evaluates whether lhs is greater or equal (>=) rhs and if it turns out to be false it will...
#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_WARNING
The logging level for unexpected behaviour, but not a serious problem.
Definition Logging.h:193
std::shared_ptr< class Robot > RobotPtr
Definition Bus.h:19
This file offers overloads of toIce() and fromIce() functions for STL container types.
::IceInternal::ProxyHandle<::IceProxy::armarx::DebugObserverInterface > DebugObserverInterfacePrx
MultiDimPIDControllerTemplate<> MultiDimPIDController
std::vector< T > max(const std::vector< T > &v1, const std::vector< T > &v2)
IceUtil::Handle< class RobotUnit > RobotUnitPtr
Definition FTSensor.h:34
::IceInternal::ProxyHandle<::IceProxy::armarx::DebugDrawerInterface > DebugDrawerInterfacePrx
detail::ControlThreadOutputBufferEntry SensorAndControl
std::vector< T > min(const std::vector< T > &v1, const std::vector< T > &v2)