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