2 ******************************************************************************
3 * @addtogroup OpenPilotModules OpenPilot Modules
5 * @addtogroup PathFollower CONTROL interface class
6 * @brief PID controller for NE
10 * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2015.
11 * @brief Executes PID control loops for NE directions
13 * @see The GNU Public License (GPL) Version 3
15 *****************************************************************************/
17 * This program is free software; you can redistribute it and/or modify
18 * it under the terms of the GNU General Public License as published by
19 * the Free Software Foundation; either version 3 of the License, or
20 * (at your option) any later version.
22 * This program is distributed in the hope that it will be useful, but
23 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
24 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
27 * You should have received a copy of the GNU General Public License along
28 * with this program; if not, write to the Free Software Foundation, Inc.,
29 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
32 #include <openpilot.h>
34 #include <callbackinfo.h>
38 #include <CoordinateConversions.h>
39 #include <sin_lookup.h>
40 #include <pathdesired.h>
43 #include <pidstatus.h>
45 #include "pathfollowerfsm.h"
46 #include "pidcontrolne.h"
48 PIDControlNE::PIDControlNE()
49 : deltaTime(0), mNECommand(0), mNeutral(0), mVelocityMax(0), mMinCommand(0), mMaxCommand(0), mVelocityFeedforward(0), mActive(false)
52 PIDControlNE::~PIDControlNE() {}
54 void PIDControlNE::Initialize()
57 void PIDControlNE::Deactivate()
62 void PIDControlNE::Activate()
67 void PIDControlNE::UpdateParameters(float kp
, float ki
, float kd
, float beta
, float dT
, float velocityMax
)
69 // pid_configure(&PID, kp, ki, kd, ilimit);
72 float Tt
= (Ti
+ Td
) / 2.0f
;
79 // Avoid Ti being infinite
81 // Tt antiwindup time constant - we don't need antiwindup with no I term
93 } else if (beta
< 0.4f
) {
97 pid2_configure(&PIDvel
[0], kp
, ki
, kd
, Tf
, kt
, dT
, beta
, u0
, 0.0f
, 1.0f
);
98 pid2_configure(&PIDvel
[1], kp
, ki
, kd
, Tf
, kt
, dT
, beta
, u0
, 0.0f
, 1.0f
);
100 mVelocityMax
= velocityMax
;
103 void PIDControlNE::UpdatePositionalParameters(float kp
)
105 pid_configure(&PIDposH
[0], kp
, 0.0f
, 0.0f
, 0.0f
);
106 pid_configure(&PIDposH
[1], kp
, 0.0f
, 0.0f
, 0.0f
);
108 void PIDControlNE::UpdatePositionSetpoint(float setpointNorth
, float setpointEast
)
110 mPositionSetpointTarget
[0] = setpointNorth
;
111 mPositionSetpointTarget
[1] = setpointEast
;
113 void PIDControlNE::UpdatePositionState(float pvNorth
, float pvEast
)
115 mPositionState
[0] = pvNorth
;
116 mPositionState
[1] = pvEast
;
118 // This is a pure position hold position control
119 void PIDControlNE::ControlPosition()
121 // Current progress location relative to end
122 float velNorth
= 0.0f
;
123 float velEast
= 0.0f
;
125 velNorth
= pid_apply(&PIDposH
[0], mPositionSetpointTarget
[0] - mPositionState
[0], deltaTime
);
126 velEast
= pid_apply(&PIDposH
[1], mPositionSetpointTarget
[1] - mPositionState
[1], deltaTime
);
127 UpdateVelocitySetpoint(velNorth
, velEast
);
130 void PIDControlNE::ControlPositionWithPath(struct path_status
*progress
)
132 // Current progress location relative to end
133 float velNorth
= progress
->path_vector
[0];
134 float velEast
= progress
->path_vector
[1];
136 velNorth
+= pid_apply(&PIDposH
[0], progress
->correction_vector
[0], deltaTime
);
137 velEast
+= pid_apply(&PIDposH
[1], progress
->correction_vector
[1], deltaTime
);
138 UpdateVelocitySetpoint(velNorth
, velEast
);
141 void PIDControlNE::UpdateVelocitySetpoint(float setpointNorth
, float setpointEast
)
143 // scale velocity if it is above configured maximum
144 // for braking, we can not help it if initial velocity was greater
145 float velH
= sqrtf(setpointNorth
* setpointNorth
+ setpointEast
* setpointEast
);
147 if (velH
> mVelocityMax
) {
148 setpointNorth
*= mVelocityMax
/ velH
;
149 setpointEast
*= mVelocityMax
/ velH
;
152 mVelocitySetpointTarget
[0] = setpointNorth
;
153 mVelocitySetpointTarget
[1] = setpointEast
;
157 void PIDControlNE::UpdateBrakeVelocity(float startingVelocity
, float dT
, float brakeRate
, float currentVelocity
, float *updatedVelocity
)
159 if (startingVelocity
>= 0.0f
) {
160 *updatedVelocity
= startingVelocity
- dT
* brakeRate
;
161 if (*updatedVelocity
> currentVelocity
) {
162 *updatedVelocity
= currentVelocity
;
164 if (*updatedVelocity
< 0.0f
) {
165 *updatedVelocity
= 0.0f
;
168 *updatedVelocity
= startingVelocity
+ dT
* brakeRate
;
169 if (*updatedVelocity
< currentVelocity
) {
170 *updatedVelocity
= currentVelocity
;
172 if (*updatedVelocity
> 0.0f
) {
173 *updatedVelocity
= 0.0f
;
178 void PIDControlNE::UpdateVelocityStateWithBrake(float pvNorth
, float pvEast
, float path_time
, float brakeRate
)
180 mVelocityState
[0] = pvNorth
;
181 mVelocityState
[1] = pvEast
;
183 float velocitySetpointDesired
[2];
185 UpdateBrakeVelocity(mVelocitySetpointTarget
[0], path_time
, brakeRate
, pvNorth
, &velocitySetpointDesired
[0]);
186 UpdateBrakeVelocity(mVelocitySetpointTarget
[1], path_time
, brakeRate
, pvEast
, &velocitySetpointDesired
[1]);
188 // If rate of change limits required, add here
189 for (int iaxis
= 0; iaxis
< 2; iaxis
++) {
190 mVelocitySetpointCurrent
[iaxis
] = velocitySetpointDesired
[iaxis
];
194 void PIDControlNE::UpdateVelocityState(float pvNorth
, float pvEast
)
196 mVelocityState
[0] = pvNorth
;
197 mVelocityState
[1] = pvEast
;
199 // The FSM controls the actual descent velocity and introduces step changes as required
200 float velocitySetpointDesired
[2];
201 velocitySetpointDesired
[0] = mVelocitySetpointTarget
[0];
202 velocitySetpointDesired
[1] = mVelocitySetpointTarget
[1];
204 // If rate of change limits required, add here
205 for (int iaxis
= 0; iaxis
< 2; iaxis
++) {
206 mVelocitySetpointCurrent
[iaxis
] = velocitySetpointDesired
[iaxis
];
211 void PIDControlNE::UpdateCommandParameters(float minCommand
, float maxCommand
, float velocityFeedforward
)
213 mMinCommand
= minCommand
;
214 mMaxCommand
= maxCommand
;
215 mVelocityFeedforward
= velocityFeedforward
;
219 void PIDControlNE::GetNECommand(float *northCommand
, float *eastCommand
)
221 PIDvel
[0].va
= mVelocitySetpointCurrent
[0] * mVelocityFeedforward
;
222 *northCommand
= pid2_apply(&(PIDvel
[0]), mVelocitySetpointCurrent
[0], mVelocityState
[0], mMinCommand
, mMaxCommand
);
223 PIDvel
[1].va
= mVelocitySetpointCurrent
[1] * mVelocityFeedforward
;
224 *eastCommand
= pid2_apply(&(PIDvel
[1]), mVelocitySetpointCurrent
[1], mVelocityState
[1], mMinCommand
, mMaxCommand
);
226 PIDStatusData pidStatus
;
227 pidStatus
.setpoint
= mVelocitySetpointCurrent
[0];
228 pidStatus
.actual
= mVelocityState
[0];
229 pidStatus
.error
= mVelocitySetpointCurrent
[0] - mVelocityState
[0];
230 pidStatus
.setpoint
= mVelocitySetpointCurrent
[0];
231 pidStatus
.ulow
= mMinCommand
;
232 pidStatus
.uhigh
= mMaxCommand
;
233 pidStatus
.command
= *northCommand
;
234 pidStatus
.P
= PIDvel
[0].P
;
235 pidStatus
.I
= PIDvel
[0].I
;
236 pidStatus
.D
= PIDvel
[0].D
;
237 PIDStatusSet(&pidStatus
);
240 void PIDControlNE::GetVelocityDesired(float *north
, float *east
)
242 *north
= mVelocitySetpointCurrent
[0];
243 *east
= mVelocitySetpointCurrent
[1];