Alison Bartsch / Mbed 2 deprecated FreeFlyerROS

Dependencies:   mbed ros_lib_kinetic

Committer:
Knillinux
Date:
Tue Feb 14 05:12:54 2017 +0000
Revision:
0:dd126a1080d3
Child:
1:40bdbe1a93b7
test

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Knillinux 0:dd126a1080d3 1 /**
Knillinux 0:dd126a1080d3 2 * @author Aaron Berk
Knillinux 0:dd126a1080d3 3 *
Knillinux 0:dd126a1080d3 4 * @section LICENSE
Knillinux 0:dd126a1080d3 5 *
Knillinux 0:dd126a1080d3 6 * Copyright (c) 2010 ARM Limited
Knillinux 0:dd126a1080d3 7 *
Knillinux 0:dd126a1080d3 8 * Permission is hereby granted, free of charge, to any person obtaining a copy
Knillinux 0:dd126a1080d3 9 * of this software and associated documentation files (the "Software"), to deal
Knillinux 0:dd126a1080d3 10 * in the Software without restriction, including without limitation the rights
Knillinux 0:dd126a1080d3 11 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
Knillinux 0:dd126a1080d3 12 * copies of the Software, and to permit persons to whom the Software is
Knillinux 0:dd126a1080d3 13 * furnished to do so, subject to the following conditions:
Knillinux 0:dd126a1080d3 14 *
Knillinux 0:dd126a1080d3 15 * The above copyright notice and this permission notice shall be included in
Knillinux 0:dd126a1080d3 16 * all copies or substantial portions of the Software.
Knillinux 0:dd126a1080d3 17 *
Knillinux 0:dd126a1080d3 18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
Knillinux 0:dd126a1080d3 19 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
Knillinux 0:dd126a1080d3 20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
Knillinux 0:dd126a1080d3 21 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
Knillinux 0:dd126a1080d3 22 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
Knillinux 0:dd126a1080d3 23 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
Knillinux 0:dd126a1080d3 24 * THE SOFTWARE.
Knillinux 0:dd126a1080d3 25 *
Knillinux 0:dd126a1080d3 26 * @section DESCRIPTION
Knillinux 0:dd126a1080d3 27 *
Knillinux 0:dd126a1080d3 28 * A PID controller is a widely used feedback controller commonly found in
Knillinux 0:dd126a1080d3 29 * industry.
Knillinux 0:dd126a1080d3 30 *
Knillinux 0:dd126a1080d3 31 * This library is a port of Brett Beauregard's Arduino PID library:
Knillinux 0:dd126a1080d3 32 *
Knillinux 0:dd126a1080d3 33 * http://www.arduino.cc/playground/Code/PIDLibrary
Knillinux 0:dd126a1080d3 34 *
Knillinux 0:dd126a1080d3 35 * The wikipedia article on PID controllers is a good place to start on
Knillinux 0:dd126a1080d3 36 * understanding how they work:
Knillinux 0:dd126a1080d3 37 *
Knillinux 0:dd126a1080d3 38 * http://en.wikipedia.org/wiki/PID_controller
Knillinux 0:dd126a1080d3 39 *
Knillinux 0:dd126a1080d3 40 * For a clear and elegant explanation of how to implement and tune a
Knillinux 0:dd126a1080d3 41 * controller, the controlguru website by Douglas J. Cooper (who also happened
Knillinux 0:dd126a1080d3 42 * to be Brett's controls professor) is an excellent reference:
Knillinux 0:dd126a1080d3 43 *
Knillinux 0:dd126a1080d3 44 * http://www.controlguru.com/
Knillinux 0:dd126a1080d3 45 */
Knillinux 0:dd126a1080d3 46
Knillinux 0:dd126a1080d3 47 /**
Knillinux 0:dd126a1080d3 48 * Includes
Knillinux 0:dd126a1080d3 49 */
Knillinux 0:dd126a1080d3 50 #include "PID.h"
Knillinux 0:dd126a1080d3 51
Knillinux 0:dd126a1080d3 52 PID::PID(float Kc, float tauI, float tauD, float interval) {
Knillinux 0:dd126a1080d3 53
Knillinux 0:dd126a1080d3 54 usingFeedForward = false;
Knillinux 0:dd126a1080d3 55 inAuto = false;
Knillinux 0:dd126a1080d3 56
Knillinux 0:dd126a1080d3 57 //Default the limits to the full range of I/O: 3.3V
Knillinux 0:dd126a1080d3 58 //Make sure to set these to more appropriate limits for
Knillinux 0:dd126a1080d3 59 //your application.
Knillinux 0:dd126a1080d3 60 setInputLimits(0.0, 3.3);
Knillinux 0:dd126a1080d3 61 setOutputLimits(0.0, 3.3);
Knillinux 0:dd126a1080d3 62
Knillinux 0:dd126a1080d3 63 tSample_ = interval;
Knillinux 0:dd126a1080d3 64
Knillinux 0:dd126a1080d3 65 setTunings(Kc, tauI, tauD);
Knillinux 0:dd126a1080d3 66
Knillinux 0:dd126a1080d3 67 setPoint_ = 0.0;
Knillinux 0:dd126a1080d3 68 processVariable_ = 0.0;
Knillinux 0:dd126a1080d3 69 prevProcessVariable_ = 0.0;
Knillinux 0:dd126a1080d3 70 controllerOutput_ = 0.0;
Knillinux 0:dd126a1080d3 71 prevControllerOutput_ = 0.0;
Knillinux 0:dd126a1080d3 72
Knillinux 0:dd126a1080d3 73 accError_ = 0.0;
Knillinux 0:dd126a1080d3 74 bias_ = 0.0;
Knillinux 0:dd126a1080d3 75
Knillinux 0:dd126a1080d3 76 realOutput_ = 0.0;
Knillinux 0:dd126a1080d3 77
Knillinux 0:dd126a1080d3 78 }
Knillinux 0:dd126a1080d3 79
Knillinux 0:dd126a1080d3 80 void PID::setInputLimits(float inMin, float inMax) {
Knillinux 0:dd126a1080d3 81
Knillinux 0:dd126a1080d3 82 //Make sure we haven't been given impossible values.
Knillinux 0:dd126a1080d3 83 if (inMin >= inMax) {
Knillinux 0:dd126a1080d3 84 return;
Knillinux 0:dd126a1080d3 85 }
Knillinux 0:dd126a1080d3 86
Knillinux 0:dd126a1080d3 87 //Rescale the working variables to reflect the changes.
Knillinux 0:dd126a1080d3 88 prevProcessVariable_ *= (inMax - inMin) / inSpan_;
Knillinux 0:dd126a1080d3 89 accError_ *= (inMax - inMin) / inSpan_;
Knillinux 0:dd126a1080d3 90
Knillinux 0:dd126a1080d3 91 //Make sure the working variables are within the new limits.
Knillinux 0:dd126a1080d3 92 if (prevProcessVariable_ > 1) {
Knillinux 0:dd126a1080d3 93 prevProcessVariable_ = 1;
Knillinux 0:dd126a1080d3 94 } else if (prevProcessVariable_ < 0) {
Knillinux 0:dd126a1080d3 95 prevProcessVariable_ = 0;
Knillinux 0:dd126a1080d3 96 }
Knillinux 0:dd126a1080d3 97
Knillinux 0:dd126a1080d3 98 inMin_ = inMin;
Knillinux 0:dd126a1080d3 99 inMax_ = inMax;
Knillinux 0:dd126a1080d3 100 inSpan_ = inMax - inMin;
Knillinux 0:dd126a1080d3 101
Knillinux 0:dd126a1080d3 102 setSetPoint(setPoint_);
Knillinux 0:dd126a1080d3 103 }
Knillinux 0:dd126a1080d3 104
Knillinux 0:dd126a1080d3 105 void PID::setOutputLimits(float outMin, float outMax) {
Knillinux 0:dd126a1080d3 106
Knillinux 0:dd126a1080d3 107 //Make sure we haven't been given impossible values.
Knillinux 0:dd126a1080d3 108 if (outMin >= outMax) {
Knillinux 0:dd126a1080d3 109 return;
Knillinux 0:dd126a1080d3 110 }
Knillinux 0:dd126a1080d3 111
Knillinux 0:dd126a1080d3 112 //Rescale the working variables to reflect the changes.
Knillinux 0:dd126a1080d3 113 prevControllerOutput_ *= (outMax - outMin) / outSpan_;
Knillinux 0:dd126a1080d3 114
Knillinux 0:dd126a1080d3 115 //Make sure the working variables are within the new limits.
Knillinux 0:dd126a1080d3 116 if (prevControllerOutput_ > 1) {
Knillinux 0:dd126a1080d3 117 prevControllerOutput_ = 1;
Knillinux 0:dd126a1080d3 118 } else if (prevControllerOutput_ < 0) {
Knillinux 0:dd126a1080d3 119 prevControllerOutput_ = 0;
Knillinux 0:dd126a1080d3 120 }
Knillinux 0:dd126a1080d3 121
Knillinux 0:dd126a1080d3 122 outMin_ = outMin;
Knillinux 0:dd126a1080d3 123 outMax_ = outMax;
Knillinux 0:dd126a1080d3 124 outSpan_ = outMax - outMin;
Knillinux 0:dd126a1080d3 125 }
Knillinux 0:dd126a1080d3 126
Knillinux 0:dd126a1080d3 127 /*void PID::setConInputLimits(float cinMin, float cinMax) {
Knillinux 0:dd126a1080d3 128
Knillinux 0:dd126a1080d3 129 //Make sure we haven't been given impossible values.
Knillinux 0:dd126a1080d3 130 if ((cinMin >= cinMax) || (cinMin < inMin_) || (cinMax > inMax_)) {
Knillinux 0:dd126a1080d3 131 return;
Knillinux 0:dd126a1080d3 132 }
Knillinux 0:dd126a1080d3 133
Knillinux 0:dd126a1080d3 134 cinSMin_ = (cinMin - inMin_)/inSpan_;
Knillinux 0:dd126a1080d3 135 cinSMax_ = (cinMax - inMax_)/inSpan_;
Knillinux 0:dd126a1080d3 136 }*/
Knillinux 0:dd126a1080d3 137
Knillinux 0:dd126a1080d3 138 void PID::setTunings(float Kc, float tauI, float tauD) {
Knillinux 0:dd126a1080d3 139
Knillinux 0:dd126a1080d3 140 //Verify that the tunings make sense.
Knillinux 0:dd126a1080d3 141 if (Kc == 0.0 || tauI < 0.0 || tauD < 0.0) {
Knillinux 0:dd126a1080d3 142 return;
Knillinux 0:dd126a1080d3 143 }
Knillinux 0:dd126a1080d3 144
Knillinux 0:dd126a1080d3 145 //Store raw values to hand back to user on request.
Knillinux 0:dd126a1080d3 146 pParam_ = Kc;
Knillinux 0:dd126a1080d3 147 iParam_ = tauI;
Knillinux 0:dd126a1080d3 148 dParam_ = tauD;
Knillinux 0:dd126a1080d3 149
Knillinux 0:dd126a1080d3 150 float tempTauR;
Knillinux 0:dd126a1080d3 151
Knillinux 0:dd126a1080d3 152 if (tauI == 0.0) {
Knillinux 0:dd126a1080d3 153 tempTauR = 0.0;
Knillinux 0:dd126a1080d3 154 } else {
Knillinux 0:dd126a1080d3 155 tempTauR = (1.0 / tauI) * tSample_;
Knillinux 0:dd126a1080d3 156 }
Knillinux 0:dd126a1080d3 157
Knillinux 0:dd126a1080d3 158 //For "bumpless transfer" we need to rescale the accumulated error.
Knillinux 0:dd126a1080d3 159 if (inAuto) {
Knillinux 0:dd126a1080d3 160 if (tempTauR == 0.0) {
Knillinux 0:dd126a1080d3 161 accError_ = 0.0;
Knillinux 0:dd126a1080d3 162 } else {
Knillinux 0:dd126a1080d3 163 accError_ *= (Kc_ * tauR_) / (Kc * tempTauR);
Knillinux 0:dd126a1080d3 164 }
Knillinux 0:dd126a1080d3 165 }
Knillinux 0:dd126a1080d3 166
Knillinux 0:dd126a1080d3 167 Kc_ = Kc;
Knillinux 0:dd126a1080d3 168 tauR_ = tempTauR;
Knillinux 0:dd126a1080d3 169 tauD_ = tauD / tSample_;
Knillinux 0:dd126a1080d3 170
Knillinux 0:dd126a1080d3 171 }
Knillinux 0:dd126a1080d3 172
Knillinux 0:dd126a1080d3 173 void PID::reset(void) {
Knillinux 0:dd126a1080d3 174
Knillinux 0:dd126a1080d3 175 float scaledBias = 0.0;
Knillinux 0:dd126a1080d3 176
Knillinux 0:dd126a1080d3 177 if (usingFeedForward) {
Knillinux 0:dd126a1080d3 178 scaledBias = (bias_ - outMin_) / outSpan_;
Knillinux 0:dd126a1080d3 179 } else {
Knillinux 0:dd126a1080d3 180 scaledBias = (realOutput_ - outMin_) / outSpan_;
Knillinux 0:dd126a1080d3 181 }
Knillinux 0:dd126a1080d3 182
Knillinux 0:dd126a1080d3 183 prevControllerOutput_ = scaledBias;
Knillinux 0:dd126a1080d3 184 prevProcessVariable_ = (processVariable_ - inMin_) / inSpan_;
Knillinux 0:dd126a1080d3 185
Knillinux 0:dd126a1080d3 186 //Clear any error in the integral.
Knillinux 0:dd126a1080d3 187 accError_ = 0;
Knillinux 0:dd126a1080d3 188
Knillinux 0:dd126a1080d3 189 }
Knillinux 0:dd126a1080d3 190
Knillinux 0:dd126a1080d3 191 void PID::setMode(int mode) {
Knillinux 0:dd126a1080d3 192
Knillinux 0:dd126a1080d3 193 //We were in manual, and we just got set to auto.
Knillinux 0:dd126a1080d3 194 //Reset the controller internals.
Knillinux 0:dd126a1080d3 195 if (mode != 0 && !inAuto) {
Knillinux 0:dd126a1080d3 196 reset();
Knillinux 0:dd126a1080d3 197 }
Knillinux 0:dd126a1080d3 198
Knillinux 0:dd126a1080d3 199 inAuto = (mode != 0);
Knillinux 0:dd126a1080d3 200
Knillinux 0:dd126a1080d3 201 }
Knillinux 0:dd126a1080d3 202
Knillinux 0:dd126a1080d3 203 void PID::setInterval(float interval) {
Knillinux 0:dd126a1080d3 204
Knillinux 0:dd126a1080d3 205 if (interval > 0) {
Knillinux 0:dd126a1080d3 206 //Convert the time-based tunings to reflect this change.
Knillinux 0:dd126a1080d3 207 tauR_ *= (interval / tSample_);
Knillinux 0:dd126a1080d3 208 accError_ *= (tSample_ / interval);
Knillinux 0:dd126a1080d3 209 tauD_ *= (interval / tSample_);
Knillinux 0:dd126a1080d3 210 tSample_ = interval;
Knillinux 0:dd126a1080d3 211 }
Knillinux 0:dd126a1080d3 212
Knillinux 0:dd126a1080d3 213 }
Knillinux 0:dd126a1080d3 214
Knillinux 0:dd126a1080d3 215 void PID::setSetPoint(float sp) {
Knillinux 0:dd126a1080d3 216
Knillinux 0:dd126a1080d3 217 if (sp > inMax_) {
Knillinux 0:dd126a1080d3 218 sp = inMax_;
Knillinux 0:dd126a1080d3 219 } else if (sp < inMin_) {
Knillinux 0:dd126a1080d3 220 sp = inMin_;
Knillinux 0:dd126a1080d3 221 }
Knillinux 0:dd126a1080d3 222 setPoint_ = sp;
Knillinux 0:dd126a1080d3 223
Knillinux 0:dd126a1080d3 224 }
Knillinux 0:dd126a1080d3 225
Knillinux 0:dd126a1080d3 226 void PID::setProcessValue(float pv) {
Knillinux 0:dd126a1080d3 227
Knillinux 0:dd126a1080d3 228 processVariable_ = pv;
Knillinux 0:dd126a1080d3 229
Knillinux 0:dd126a1080d3 230 }
Knillinux 0:dd126a1080d3 231
Knillinux 0:dd126a1080d3 232 void PID::setBias(float bias){
Knillinux 0:dd126a1080d3 233
Knillinux 0:dd126a1080d3 234 bias_ = bias;
Knillinux 0:dd126a1080d3 235 usingFeedForward = 1;
Knillinux 0:dd126a1080d3 236
Knillinux 0:dd126a1080d3 237 }
Knillinux 0:dd126a1080d3 238
Knillinux 0:dd126a1080d3 239 void PID::setAccLimit(float accLimit) {
Knillinux 0:dd126a1080d3 240
Knillinux 0:dd126a1080d3 241 accLimit_ = abs(accLimit);
Knillinux 0:dd126a1080d3 242
Knillinux 0:dd126a1080d3 243 }
Knillinux 0:dd126a1080d3 244
Knillinux 0:dd126a1080d3 245
Knillinux 0:dd126a1080d3 246 float PID::compute() {
Knillinux 0:dd126a1080d3 247
Knillinux 0:dd126a1080d3 248 //Pull in the input and setpoint, and scale them into percent span.
Knillinux 0:dd126a1080d3 249 float scaledPV = (processVariable_ - inMin_) / inSpan_;
Knillinux 0:dd126a1080d3 250
Knillinux 0:dd126a1080d3 251 /*if (scaledPV > 1.0) {
Knillinux 0:dd126a1080d3 252 scaledPV = 1.0;
Knillinux 0:dd126a1080d3 253 } else if (scaledPV < 0.0) {
Knillinux 0:dd126a1080d3 254 scaledPV = 0.0;
Knillinux 0:dd126a1080d3 255 }*/
Knillinux 0:dd126a1080d3 256
Knillinux 0:dd126a1080d3 257 float scaledSP = (setPoint_ - inMin_) / inSpan_;
Knillinux 0:dd126a1080d3 258 /*if (scaledSP > 1.0) {
Knillinux 0:dd126a1080d3 259 scaledSP = 1.0;
Knillinux 0:dd126a1080d3 260 } else if (scaledSP < 0.0) {
Knillinux 0:dd126a1080d3 261 scaledSP = 0.0;
Knillinux 0:dd126a1080d3 262 }*/
Knillinux 0:dd126a1080d3 263
Knillinux 0:dd126a1080d3 264 error_ = scaledSP - scaledPV;
Knillinux 0:dd126a1080d3 265
Knillinux 0:dd126a1080d3 266 //Check and see if the output is pegged at a limit and only
Knillinux 0:dd126a1080d3 267 //integrate if it is not. This is to prevent reset-windup.
Knillinux 0:dd126a1080d3 268 if (!(prevControllerOutput_ >= 1 && error_ > 0) && !(prevControllerOutput_ <= 0 && error_ < 0)) {
Knillinux 0:dd126a1080d3 269 accError_ += error_;
Knillinux 0:dd126a1080d3 270 if (accError_ > accLimit_) {
Knillinux 0:dd126a1080d3 271 accError_ = accLimit_;
Knillinux 0:dd126a1080d3 272 } else if (accError_ < -accLimit_) {
Knillinux 0:dd126a1080d3 273 accError_ = -accLimit_;
Knillinux 0:dd126a1080d3 274 }
Knillinux 0:dd126a1080d3 275 }
Knillinux 0:dd126a1080d3 276
Knillinux 0:dd126a1080d3 277 //Compute the current slope of the input signal.
Knillinux 0:dd126a1080d3 278 float dMeas = (scaledPV - prevProcessVariable_) / tSample_;
Knillinux 0:dd126a1080d3 279
Knillinux 0:dd126a1080d3 280 float scaledBias = 0.0;
Knillinux 0:dd126a1080d3 281
Knillinux 0:dd126a1080d3 282 if (usingFeedForward) {
Knillinux 0:dd126a1080d3 283 scaledBias = (bias_ - outMin_) / outSpan_;
Knillinux 0:dd126a1080d3 284 }
Knillinux 0:dd126a1080d3 285
Knillinux 0:dd126a1080d3 286 //Perform the PID calculation.
Knillinux 0:dd126a1080d3 287 controllerOutput_ = scaledBias + Kc_ * (error_ + (tauR_ * accError_) - (tauD_ * dMeas));
Knillinux 0:dd126a1080d3 288
Knillinux 0:dd126a1080d3 289 //Make sure the computed output is within output constraints.
Knillinux 0:dd126a1080d3 290 if (controllerOutput_ < 0.0) {
Knillinux 0:dd126a1080d3 291 controllerOutput_ = 0.0;
Knillinux 0:dd126a1080d3 292 } else if (controllerOutput_ > 1.0) {
Knillinux 0:dd126a1080d3 293 controllerOutput_ = 1.0;
Knillinux 0:dd126a1080d3 294 }
Knillinux 0:dd126a1080d3 295
Knillinux 0:dd126a1080d3 296 //Remember this output for the windup check next time.
Knillinux 0:dd126a1080d3 297 prevControllerOutput_ = controllerOutput_;
Knillinux 0:dd126a1080d3 298 //Remember the input for the derivative calculation next time.
Knillinux 0:dd126a1080d3 299 prevProcessVariable_ = scaledPV;
Knillinux 0:dd126a1080d3 300
Knillinux 0:dd126a1080d3 301 //Scale the output from percent span back out to a real world number.
Knillinux 0:dd126a1080d3 302 return ((controllerOutput_ * outSpan_) + outMin_);
Knillinux 0:dd126a1080d3 303
Knillinux 0:dd126a1080d3 304 }
Knillinux 0:dd126a1080d3 305
Knillinux 0:dd126a1080d3 306 float PID::getInMin() {
Knillinux 0:dd126a1080d3 307
Knillinux 0:dd126a1080d3 308 return inMin_;
Knillinux 0:dd126a1080d3 309
Knillinux 0:dd126a1080d3 310 }
Knillinux 0:dd126a1080d3 311
Knillinux 0:dd126a1080d3 312 float PID::getInMax() {
Knillinux 0:dd126a1080d3 313
Knillinux 0:dd126a1080d3 314 return inMax_;
Knillinux 0:dd126a1080d3 315
Knillinux 0:dd126a1080d3 316 }
Knillinux 0:dd126a1080d3 317
Knillinux 0:dd126a1080d3 318 float PID::getOutMin() {
Knillinux 0:dd126a1080d3 319
Knillinux 0:dd126a1080d3 320 return outMin_;
Knillinux 0:dd126a1080d3 321
Knillinux 0:dd126a1080d3 322 }
Knillinux 0:dd126a1080d3 323
Knillinux 0:dd126a1080d3 324 float PID::getOutMax() {
Knillinux 0:dd126a1080d3 325
Knillinux 0:dd126a1080d3 326 return outMax_;
Knillinux 0:dd126a1080d3 327
Knillinux 0:dd126a1080d3 328 }
Knillinux 0:dd126a1080d3 329
Knillinux 0:dd126a1080d3 330 float PID::getInterval() {
Knillinux 0:dd126a1080d3 331
Knillinux 0:dd126a1080d3 332 return tSample_;
Knillinux 0:dd126a1080d3 333
Knillinux 0:dd126a1080d3 334 }
Knillinux 0:dd126a1080d3 335
Knillinux 0:dd126a1080d3 336 float PID::getPParam() {
Knillinux 0:dd126a1080d3 337
Knillinux 0:dd126a1080d3 338 return pParam_;
Knillinux 0:dd126a1080d3 339
Knillinux 0:dd126a1080d3 340 }
Knillinux 0:dd126a1080d3 341
Knillinux 0:dd126a1080d3 342 float PID::getIParam() {
Knillinux 0:dd126a1080d3 343
Knillinux 0:dd126a1080d3 344 return iParam_;
Knillinux 0:dd126a1080d3 345
Knillinux 0:dd126a1080d3 346 }
Knillinux 0:dd126a1080d3 347
Knillinux 0:dd126a1080d3 348 float PID::getDParam() {
Knillinux 0:dd126a1080d3 349
Knillinux 0:dd126a1080d3 350 return dParam_;
Knillinux 0:dd126a1080d3 351
Knillinux 0:dd126a1080d3 352 }