VelocityManipulatingTorque.cpp
Go to the documentation of this file.
1/*
2 * This file is part of ArmarX.
3 *
4 * Copyright (C) 2011-2017, High Performance Humanoid Technologies (H2T), Karlsruhe Institute of Technology (KIT), all rights reserved.
5 *
6 * ArmarX is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 *
10 * ArmarX is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 *
18 * @package ArmarX
19 * @author Mirko Waechter( mirko.waechter at kit dot edu)
20 * @date 2018
21 * @copyright http://www.gnu.org/licenses/gpl-2.0.txt
22 * GNU General Public License
23 */
24
25
27
29
31
33{
34
37 pid(torqueConfigData->pid_proportional_gain,
38 torqueConfigData->pid_integral_gain,
39 torqueConfigData->pid_derivative_gain),
40 pidTargetTorque(0, 1, 0),
41 torqueGaussianFilter(30, 30),
42 torqueMedianFilter(5),
43 actualVelocityFilter(5),
46 {
47
48
49 pid.threadSafe = false;
50 pid.setMaxControlValue(torqueConfigData->pid_max_value);
51 }
52
56 bool limitless,
57 float jointLimitLow,
58 float jointLimitHigh)
59 {
61 configData.pid_proportional_gain = config.getFloat("pid_proportional_gain");
62 configData.pid_integral_gain = config.getFloat("pid_integral_gain");
63 configData.pid_derivative_gain = config.getFloat("pid_derivative_gain");
64 configData.pid_max_value = config.getFloat("pid_max_value");
65 configData.accelerationGain = config.getFloat("accelerationGain");
66 configData.deadZone = config.getFloat("deadZone");
67 configData.decay = config.getFloat("decay");
68 configData.maxVelocity = config.getFloat("maxVelocity");
69 configData.maxAcceleration = config.getFloat("maxAcceleration");
70 configData.torqueToCurrent = config.getFloat("torqueToCurrent");
71 configData.maxTargetTorque = config.getFloat("maxTargetTorque");
72
73 auto v = config.getFloatList("firFilterImpulseResponse");
74 for (auto& elem : v)
75 {
76 configData.firFilterImpulseResponse.push_back(elem);
77 }
78
79 configData.limitless = limitless;
80 configData.jointLimitLow = jointLimitLow;
81 configData.jointLimitHigh = jointLimitHigh;
82
83 return std::make_shared<VelocityManipulatingTorqueControllerConfiguration>(configData);
84 }
85
90
91 double
93 {
94 double jointLimitProtection = 0;
95 if (!torqueConfigData->limitless)
96 {
97 double borderHigh = torqueConfigData->jointLimitHigh - torqueConfigData->pushbackMargin;
98 double borderLow = torqueConfigData->jointLimitLow + torqueConfigData->pushbackMargin;
99 double penetration = 0;
100 if (actualPosition > borderHigh)
101 {
102 penetration = actualPosition - borderHigh;
103 }
104 else if (actualPosition < borderLow)
105 {
106 penetration = actualPosition - borderLow;
107 }
108 jointLimitProtection =
109 penetration / torqueConfigData->pushbackMargin * torqueConfigData->pushBackTorque;
110 }
111 jointLimitProtection =
112 math::MathUtils::LimitTo(jointLimitProtection, torqueConfigData->pushBackTorque);
113 return jointLimitProtection;
114 }
115
116 double
118 {
119 return lastJerk;
120 }
121
122 double
124 {
125 return lastAcceleration;
126 }
127
128 float
129 VelocityManipulatingTorqueController::update(const IceUtil::Time& sensorValuesTimestamp,
130 const IceUtil::Time& timeSinceLastIteration,
131 float gravity,
132 float actualTorque,
133 float targetTorque,
134 float actualVelocity,
135 float actualPosition)
136 {
137 ARMARX_CHECK_EXPRESSION(torqueConfigData);
138 // pidParameterMutex.lock();
139 pid.Kp = torqueConfigData->pid_proportional_gain;
140 pid.Ki = torqueConfigData->pid_integral_gain;
141 pid.Kd = torqueConfigData->pid_derivative_gain;
142
143 pid.maxDerivation = 30; // avoids rapid oscillation of pid controller
144 pid.setMaxControlValue(torqueConfigData->pid_max_value);
145 // ARMARX_INFO << "PID max value: " << torqueConfigData->pid_max_value;
146
147 targetTorque = math::MathUtils::LimitTo(targetTorque, torqueConfigData->maxTargetTorque);
148 double decay = torqueConfigData->decay;
149 double accelerationGain = torqueConfigData->accelerationGain;
150 double maxAcceleration = torqueConfigData->maxAcceleration;
151 double maxJerk = torqueConfigData->maxJerk;
152 double deadZone = torqueConfigData->deadZone;
153 double maxVelocity = torqueConfigData->maxVelocity;
154 double torqueToCurrentFactor = torqueConfigData->torqueToCurrent;
155 // pidParameterMutex.unlock();
156
157
158 double dt = timeSinceLastIteration.toSecondsDouble(); // sampling time of torque values
159 // double actualTorqueF = filter.update(actualTorque);
160 // actualTorque = torqueMedianFilter.update(actualTorque);
161 actualVelocity = actualVelocityFilter.update(actualVelocity);
162 double gravityCompensatedTorque = -gravity + actualTorque;
163
164 // apply a deadzone due to model/sensor error
165 // if (std::abs(targetTorque) < 0.1)
166 {
167 gravityCompensatedTorque =
168 math::MathUtils::Sign(gravityCompensatedTorque) *
169 std::max<float>(0.0f, (std::abs(gravityCompensatedTorque) - deadZone));
170 }
171
172
173 double jointLimitProtectionTorque = calcJointLimitProtectionTorque(actualPosition);
174 if (std::abs(jointLimitProtectionTorque) > 0.0)
175 {
176 pid.integral *= 0.9; // we dont want an high integral if we are out of the joint limits
177 }
178 jointLimitProtectionTorque = math::MathUtils::LimitTo(
179 jointLimitProtectionTorque, std::abs(targetTorque + gravityCompensatedTorque) * 1.00);
180
181 double acceleration =
182 (targetTorque + gravityCompensatedTorque - jointLimitProtectionTorque) *
183 accelerationGain; // torque is an acceleration
184 acceleration = math::MathUtils::LimitTo(
185 acceleration,
186 maxAcceleration); // joints cannot/should not accelerate faster than this by zero torque control
187
188 acceleration = math::MathUtils::LimitMinMax(
189 lastAcceleration - maxJerk * dt, lastAcceleration + maxJerk * dt, acceleration);
190 if (math::MathUtils::Sign(currentTargetVelocity) == math::MathUtils::Sign(acceleration))
191 {
192 decay /= std::max(
193 std::abs(gravityCompensatedTorque),
194 1.0); // less decay when external torque is applied for easier zero torque control
195 }
196 currentTargetVelocity += acceleration * dt;
197 lastJerk = (acceleration - lastAcceleration) / dt;
198 lastAcceleration = acceleration;
199
201 1.0,
202 15.0,
203 std::abs(
204 gravityCompensatedTorque *
205 gravityCompensatedTorque)); // if external torque is applied, the decay is reduced to have a lighter torque control
206
207 decay = math::MathUtils::LimitMinMax(0.0, 1.0, decay);
208 currentTargetVelocity *=
209 1.0 - decay; // damping - slows down joint motion (important if no torque is applied)
210 currentTargetVelocity = math::MathUtils::LimitTo(
211 currentTargetVelocity,
212 maxVelocity); // some joints should not be moved over a certain velocity
213 pid.update(dt, actualVelocity, currentTargetVelocity);
214 double resultingTargetCurrent = -pid.getControlValue() * 1000.0;
215
216
217 double directControlCurrent = 0.; //gravity * torqueToCurrentFactor * 1000;
218
219 // ARMARX_RT_LOGF_INFO("direct-control: %.3f, currentTargetVelocity: %.3f, current Vel: %.3f, g-torque: %.2f, actual torque: %.2f, "
220 // "torqueDiff: %.3f, target torque: %.2f, acc: %.3f, target current: %.3f, Kp: %.1f, Ki: %.1f, cur Integral: %.4f, "
221 // "Kd: %0.2f, pid MaxVal: %.2f, a-gain: %.2f, current jerk: %.2f, deadZone: %.1f, decay: %.4f"
222 // ,
223 // directControlCurrent, currentTargetVelocity, actualVelocity, gravity, actualTorque,
224 // gravityCompensatedTorque, targetTorque, acceleration,
225 // resultingTargetCurrent, pid.Kp, pid.Ki, pid.integral, pid.Kd, pid.maxControlValue,
226 // accelerationGain, lastJerk, deadZone, decay).deactivateSpam(0.3);
227
228 // calculate a current that protects the joint limits
229 auto jointLimitProtectionCurrent =
230 calcJointLimitProtectionTorque(actualPosition) *
231 (torqueToCurrentFactor == 0.0 ? 0.05 : torqueToCurrentFactor) * 1000;
232 // ARMARX_RT_LOGF_INFO("targetCurrent: %.3f, protection torque: %.3f",
233 // resultingTargetCurrent, jointLimitProtectionTorque).deactivateSpam(0.3);
234 return resultingTargetCurrent + directControlCurrent + jointLimitProtectionCurrent;
235 }
236
237 void
239 {
240 pid.reset();
241 currentTargetVelocity = 0.0;
242 lastAcceleration = 0.0;
243 lastJerk = 0.0;
244 }
245
246 double
248 {
249 return currentTargetVelocity;
250 }
251
254 {
255 return *torqueConfigData;
256 }
257
258 bool
261 {
262 // if (pidParameterMutex.try_lock())
263 // {
264 torqueConfigData->pid_proportional_gain = configData.pid_proportional_gain;
265 torqueConfigData->pid_integral_gain = configData.pid_integral_gain;
266 torqueConfigData->pid_derivative_gain = configData.pid_derivative_gain;
267
268 torqueConfigData->decay = configData.decay;
269 torqueConfigData->deadZone = configData.deadZone;
270
271 // ARMARX_INFO << "Updated control parameters";
272
273
274 // }
275
276 return true;
277 }
278
279 const PIDController&
281 {
282 return pid;
283 }
284
285} // namespace armarx::control::joint_controller
constexpr T dt
The Config class is the base class of all specialized configurations that have a direct key -> value ...
Definition Config.h:94
float getFloat(const std::string name)
Get a Float typed Config attribute by name.
Definition Config.cpp:16
std::list< float > getFloatList(const std::string name)
Get a FloatList (std::list<float>) typed Config attribute by name.
Definition Config.cpp:58
static VelocityManipulatingTorqueControllerConfigurationPtr CreateTorqueConfigData(hardware_config::Config &config, bool limitless, float jointLimitLow, float jointLimitHigh)
float update(const IceUtil::Time &sensorValuesTimestamp, const IceUtil::Time &timeSinceLastIteration, float gravity, float actualTorque, float targetTorque, float actualVelocity, float actualPosition)
VelocityManipulatingTorqueController(const VelocityManipulatingTorqueControllerConfigurationPtr &torqueConfigData)
bool setTorqueConfigData(VelocityManipulatingTorqueControllerConfiguration configData)
VelocityManipulatingTorqueControllerConfiguration getTorqueConfigData() const
static int Sign(double value)
Definition MathUtils.h:37
static double LimitTo(double value, double absThreshold)
Definition MathUtils.h:71
static int LimitMinMax(int min, int max, int value)
Definition MathUtils.h:43
#define ARMARX_CHECK_EXPRESSION(expression)
This macro evaluates the expression and if it turns out to be false it will throw an ExpressionExcept...
std::shared_ptr< class VelocityManipulatingTorqueControllerConfiguration > VelocityManipulatingTorqueControllerConfigurationPtr