Calculate an updated steering angle for the rover based on the current pose using the predictive stanley controller.
101 {
102
103 double dSteeringAngle = 0.0;
104 std::vector<BicycleModel::Prediction> vPredictions;
105
106
107 if (m_vReferencePath.empty())
108 {
109
110 LOG_WARNING(logging::g_qSharedLogger, "PredictiveStanleyController::Calculate: Reference path is empty. Cannot calculate drive powers.");
111
112 return DriveVector{0.0, 0.0};
113 }
114
115
116
117 if (m_nCurrentReferencePathTargetIndex >= static_cast<int>(m_vReferencePath.size()) - 1)
118 {
119
121
123
124 return DriveVector{dHeadingToLastWaypoint, 1.0};
125 }
126
127
129
130 m_BicycleModel.
Predict(m_dPredictionTimeStep, m_nPredictionHorizon, vPredictions);
131
132
133 for (size_t nIter = 0.0; nIter < vPredictions.size(); ++nIter)
134 {
135
136 double dPredictedXPosition = vPredictions[nIter].dXPosition;
137 double dPredictedYPosition = vPredictions[nIter].dYPosition;
138 double dPredictedTheta = vPredictions[nIter].dTheta;
139
140
142 stPredictedPosition.dEasting = dPredictedXPosition;
143 stPredictedPosition.dNorthing = dPredictedYPosition;
144
146
147
148 double dHeadingError =
numops::AngularDifference(m_vReferencePathCurvature[m_nCurrentReferencePathTargetIndex], dPredictedTheta);
149
150
151
152
153
154
155
156 double dForwardVectorX = m_vReferencePath[m_nCurrentReferencePathTargetIndex + 1].GetUTMCoordinate().dEasting - stClosestWaypoint.
GetUTMCoordinate().dEasting;
157 double dForwardVectorY =
158 m_vReferencePath[m_nCurrentReferencePathTargetIndex + 1].GetUTMCoordinate().dNorthing - stClosestWaypoint.
GetUTMCoordinate().dNorthing;
159
160 double dForwardNorm =
sqrt(dForwardVectorX * dForwardVectorX + dForwardVectorY * dForwardVectorY);
161 double dFwdUnitX = dForwardVectorX / dForwardNorm;
162 double dFwdUnitY = dForwardVectorY / dForwardNorm;
163
164 double dVehicleVectorX = dPredictedXPosition - stClosestWaypoint.
GetUTMCoordinate().dEasting;
165 double dVehicleVectorY = dPredictedYPosition - stClosestWaypoint.
GetUTMCoordinate().dNorthing;
166
167 double dLongitudinal = dVehicleVectorX * dFwdUnitX + dVehicleVectorY * dFwdUnitY;
168
169 double dLateralX = dVehicleVectorX - dLongitudinal * dFwdUnitX;
170 double dLateralY = dVehicleVectorY - dLongitudinal * dFwdUnitY;
171
172 double dLateralDistance =
sqrt(dLateralX * dLateralX + dLateralY * dLateralY);
173
174 int nCrossTrackErrorSign = (dFwdUnitX * dVehicleVectorY - dFwdUnitY * dVehicleVectorX) > 0 ? 1 : -1;
175
176 double dCrossTrackError = nCrossTrackErrorSign * dLateralDistance;
177
178
179 double dTimeWeight = std::exp(-1.5 * static_cast<double>(nIter));
180
181 dCrossTrackError = std::clamp(m_dControlGain * dCrossTrackError, -m_dSteeringAngleLimit, m_dSteeringAngleLimit);
182
183 dSteeringAngle += dTimeWeight * (dCrossTrackError - dHeadingError);
184
185
186 dSteeringAngle = std::clamp(dSteeringAngle, -m_dSteeringAngleLimit, m_dSteeringAngleLimit);
187 }
188
189
191
192 return DriveVector{dAbsoluteHeadingGoal, dMaxSpeed};
193 }
void Predict(const double dTimeStep, const int nNumPredictions, std::vector< Prediction > &vPredictions)
Accessor for the State private member.
Definition BicycleModel.hpp:195
void UpdateState(const double dXPosition, const double dYPosition, const double dTheta)
Update the state of the model, given a new position and heading. This method will automatically calcu...
Definition BicycleModel.hpp:154
geoops::Waypoint FindClosestWaypointInPath(const geoops::UTMCoordinate &stCurrentPosition, const double dCurrentHeading)
Given the current position of the rover, find the point on the reference path that is closest to the ...
Definition PredictiveStanleyController.cpp:442
void sqrt(InputArray src, OutputArray dst)
GeoMeasurement CalculateGeoMeasurement(const GPSCoordinate &stCoord1, const GPSCoordinate &stCoord2)
The shortest path between two points on an ellipsoid at (lat1, lon1) and (lat2, lon2) is called the g...
Definition GeospatialOperations.hpp:522
constexpr T InputAngleModulus(T tValue, T tMinValue, T tMaxValue)
Calculates the modulus of an input angle.
Definition NumberOperations.hpp:165
constexpr T AngularDifference(T tFirstValue, T tSecondValue)
Calculates the distance in degrees between two angles. This function accounts for wrap around so that...
Definition NumberOperations.hpp:204
double GetCompassHeading() const
Accessor for the Compass Heading private member.
Definition GeospatialOperations.hpp:756
const geoops::UTMCoordinate & GetUTMCoordinate() const
Accessor for the geoops::UTMCoordinate member variable.
Definition GeospatialOperations.hpp:736
This struct stores/contains information about a UTM coordinate.
Definition GeospatialOperations.hpp:195
This struct is used by the WaypointHandler class to store location, size, and type information about ...
Definition GeospatialOperations.hpp:392
const geoops::UTMCoordinate & GetUTMCoordinate() const
Accessor for the geoops::UTMCoordinate member variable.
Definition GeospatialOperations.hpp:477