CogniPilot

MODELICA LIBRARY · ENGINEERING REFERENCE

Planning/DubinsPolynomial/smoothOffsets.mo

Download original .moGitHub source

Documentation: Planning.DubinsPolynomial.smoothOffsets

within Planning.DubinsPolynomial;
function smoothOffsets
  "Construct a septic C3 transverse-offset seed, skipping zero-length segments"
  input Planning.Dubins.Path path;
  input Real startCurvature;
  input Real goalCurvature;
  input Real startCurvatureDerivative = 0.0;
  input Real goalCurvatureDerivative = 0.0;
  output Real offsetCoefficient[3, 8]
    "Power-basis coefficients in local physical nominal distance";
  output Boolean accepted
    "False only when the path has no length or a polynomial solve fails";
protected
  Real nominalKappa[3];
  Real segmentLength[3];
  Real desiredStartCurvature;
  Real desiredEndCurvature;
  Real desiredStartCurvatureDerivative;
  Real desiredEndCurvatureDerivative;
  Real startDerivative[4];
  Real endDerivative[4];
  Real coefficient[8];
  Boolean segmentAccepted;
  Integer previousActiveSegment;
  Integer nextActiveSegment;
algorithm
  for segmentIndex in 1:3 loop
    nominalKappa[segmentIndex] :=
      Planning.DubinsPolynomial.nominalCurvature(
        path.pathType, segmentIndex, path.turnRadius);
    segmentLength[segmentIndex] := path.turnRadius
      * path.normalizedSegmentLength[segmentIndex];
  end for;

  offsetCoefficient := zeros(3, 8);
  accepted := path.length > 1.0e-10;
  previousActiveSegment := 0;
  for segmentIndex in 1:3 loop
    if segmentLength[segmentIndex] > 1.0e-10 then
      nextActiveSegment := 0;
      for candidateIndex in segmentIndex + 1:3 loop
        if nextActiveSegment == 0
            and segmentLength[candidateIndex] > 1.0e-10 then
          nextActiveSegment := candidateIndex;
        end if;
      end for;

      desiredStartCurvature := if previousActiveSegment == 0 then
          startCurvature else 0.5 * (nominalKappa[previousActiveSegment]
            + nominalKappa[segmentIndex]);
      desiredEndCurvature := if nextActiveSegment == 0 then
          goalCurvature else 0.5 * (nominalKappa[segmentIndex]
            + nominalKappa[nextActiveSegment]);
      desiredStartCurvatureDerivative := if previousActiveSegment == 0 then
          startCurvatureDerivative else 0.0;
      desiredEndCurvatureDerivative := if nextActiveSegment == 0 then
          goalCurvatureDerivative else 0.0;
      startDerivative := {
        0.0,
        0.0,
        desiredStartCurvature - nominalKappa[segmentIndex],
        desiredStartCurvatureDerivative};
      endDerivative := {
        0.0,
        0.0,
        desiredEndCurvature - nominalKappa[segmentIndex],
        desiredEndCurvatureDerivative};
      (coefficient, segmentAccepted) := Polynomials.hermiteCoefficients(
        startDerivative, endDerivative, segmentLength[segmentIndex]);
      offsetCoefficient[segmentIndex, :] := coefficient;
      accepted := accepted and segmentAccepted;
      previousActiveSegment := segmentIndex;
    end if;
  end for;
end smoothOffsets;