Alfred "schwänzelt" stark beim Perimeter mähen

Reduziert von 0,4 auf 0,25m/s ????

Soweit ich weiss ist Standard = 0,2 m/s
Richtig. 0,3 m/s ist voreingestellt und empfohlen. Man kann aber bis zu 0,5 m/s lt. Beschreibung einstellen.
Da Alfred in der Standard-Einstellung meine 435 m² nur mit 2-mal Nachladen schafft (beim Kauf hatte ich mehr erwartet, da als für bis 1.500 m² beworben) und deshalb nicht an einem Nachmittag fertig wird, hatte ich mit höheren Geschwindigkeiten "experimentiert", um meine Fläche mit nur 1-mal Nachladen zu schaffen.
Mit 0,25 m/sec klappt das jetzt so gerade eben (manchmal fehlen noch so 5-10%).
Um die Frage gleich vorweg zu beantworten, "Warum an einem Nachmittag?": Ich wohne in Flußnähe. Bis zum frühen Nachmittag ist mein Rasen noch feucht und ab ca. 19:30 Uhr setzt um diese Jahreszeit schon wieder die Tau-Feuchtigkeit ein. Mähen bei feuchtem Gras möchte ich nicht, da der Mäher unten drunter verklebt und der Reinigungsaufwand deutlich höher ist.
Vom Kauf des größeren Akkus mit 7 Ah hatte ich zunächst aufgrund des hohen Preises von 479 € Abstand genommen und da der Alfred damit als für 3.000 m² geeignet beworben wurde (also für meine 435 m² also eigentlich überdimensioniert). Mittlerweile ist der größere Akku sogar aus dem Marotronics Shop komplett verschwunden.
Bei höherer Geschwindigkeit ist das Problem sicher größer!
Nicht das von mir hier beschriebene und monierte Problem beim Perimeter-Mähen, da die Geschwindigkeit von Alfred beim Perimeter-Mähen aufgrund der bei mir dicht beieinander liegenden Punkte sehr gering ist (siehe meinen oben geposteten Kartenausschnitt) und deutlich unter den von mir eingestellten 0,25 m/s liegt. Das kann man sehr gut sehen, da er am Perimeter auf einer Strecke zwischen etwas weiter auseinander liegenden Punkten deutlich beschleunigt.
Leider kann ich Videos immer noch nicht hochladen. Auf denen kann man auch dieses Beschleunigen gut sehen.
 
Du wirst sie woanders hochladen müssen.

Wobei ich mir schon vorstellen, kann, wie das Problem aussieht. Es ist nicht das Schwänzeln gemeint, das alle hier erkannt zu haben scheinen, sondern die seltsamen und unnötigen Drehungen an gewissen Drehpunkten, die der Mäher auch in anderen Versionen der FW macht, aber offenbar verstärkt in neueren Versionen.
 
Beim Alfred kann man ja auch die Stanleywerte über die App verändern?
Ich bin mir aber nicht sicher... ich glaube er wendet die Slowparameter nur bei Dock an, nicht bei Point reached... einfach mal probieren.
In der config.h steht folgendes:

/ stanley control for path tracking - determines gain how fast to correct for lateral path errors
#define STANLEY_CONTROL_P_NORMAL 1.1 // 3.0 for path tracking control (angular gain) when mowing
#define STANLEY_CONTROL_K_NORMAL 0.1 // 1.0 for path tracking control (lateral gain) when mowing

#define STANLEY_CONTROL_P_SLOW 1.1 // 1.0 for path tracking control (angular gain) when docking tracking
#define STANLEY_CONTROL_K_SLOW 0.1 // 0.2 for path tracking control (lateral gain) when docking tracking


Probiere doch mal in der App alle Werte mit 1, dann mit 1,5 und dann mit 2,0 zu ersetzen. Also besonders k sehe ich als viel zu gering an, das führt dazu das er Spurabweichungen nicht ausregelt, und wenn er dann immer näher an einen Punkt heranfährt, vergrößert sich der Winkelfehler und er dreht zum Punkt, dann fährt er darüber hinweg und hat schon einen leicht falschen Winkel zum nächsten Punkt, dreht zum Punkt, sitzt aber nicht auf der Bahn. Bei der kurzen Strecke regelt der k wert nichts aus, da viel zu gering eingestellt. das Spiel wiederholt sich dann.

Das mt den unnötigen Drehungen wird bei angletotargetfits ausgelöst, bei mir habe ich die Funktion angepasst, weil diese prefferedrotationdirection funktion die irgendwann mal eingebaut wurde nie das gemacht hat was ich erwarten würde. Der hintergrund der Sache ist, er fährt wie gesagt an einen Punkt herran, der winkelfehler wird durch die kurze Strecke immer größer, dann wird Angletotargetfits>20 Grad abbweichung ausgelöst ----> es gibt eine Berechnung wie rum er sich drehen soll (die meistens falsch ist) und dann dreht er sich oft komplett im Kreis, nur um nicht um 25° in die richtige Richtung zu drehen. Dabei steht er aber schon 7cm vom Punkt entfernt. Dann wackelt evtl. nochmal das GPS und das ganze geht nochmal von vorne los.
 
Beim Alfred kann man ja auch die Stanleywerte über die App verändern?
Ich bin mir aber nicht sicher... ich glaube er wendet die Slowparameter nur bei Dock an, nicht bei Point reached... einfach mal probieren.
Zunächst vielen Dank für Deine Mühe, Dich mit dem Problem zu beschäftigen und Deine Lösungsansätze. Bei Alfred kann ich aber in der App an meinem Windows PC nichts davon einstellen. Oder übersehe ich das was? Hier ist ein Bild von meinem Operating Menu im Expert-Mode:
1694429522352.png
In der config.h steht folgendes:

/ stanley control for path tracking - determines gain how fast to correct for lateral path errors
#define STANLEY_CONTROL_P_NORMAL 1.1 // 3.0 for path tracking control (angular gain) when mowing
#define STANLEY_CONTROL_K_NORMAL 0.1 // 1.0 for path tracking control (lateral gain) when mowing

#define STANLEY_CONTROL_P_SLOW 1.1 // 1.0 for path tracking control (angular gain) when docking tracking
#define STANLEY_CONTROL_K_SLOW 0.1 // 0.2 for path tracking control (lateral gain) when docking tracking


Probiere doch mal in der App alle Werte mit 1, dann mit 1,5 und dann mit 2,0 zu ersetzen. Also besonders k sehe ich als viel zu gering an, das führt dazu das er Spurabweichungen nicht ausregelt, und wenn er dann immer näher an einen Punkt heranfährt, vergrößert sich der Winkelfehler und er dreht zum Punkt, dann fährt er darüber hinweg und hat schon einen leicht falschen Winkel zum nächsten Punkt, dreht zum Punkt, sitzt aber nicht auf der Bahn. Bei der kurzen Strecke regelt der k wert nichts aus, da viel zu gering eingestellt. das Spiel wiederholt sich dann.

Das mt den unnötigen Drehungen wird bei angletotargetfits ausgelöst, bei mir habe ich die Funktion angepasst, weil diese prefferedrotationdirection funktion die irgendwann mal eingebaut wurde nie das gemacht hat was ich erwarten würde. Der hintergrund der Sache ist, er fährt wie gesagt an einen Punkt herran, der winkelfehler wird durch die kurze Strecke immer größer, dann wird Angletotargetfits>20 Grad abbweichung ausgelöst ----> es gibt eine Berechnung wie rum er sich drehen soll (die meistens falsch ist) und dann dreht er sich oft komplett im Kreis, nur um nicht um 25° in die richtige Richtung zu drehen. Dabei steht er aber schon 7cm vom Punkt entfernt. Dann wackelt evtl. nochmal das GPS und das ganze geht nochmal von vorne los.
Abgesehen davon, daß nach meiner Kenntnis solche Dinge beim Alfred sich ja nicht standarmäßig verändern lassen, finde ich Deine Erklärungen sehr interessant. Nochmals Danke.
 
Hmmm, ja... das ist ja Doof. Du kannst die Geschwindigkeit verändern, aber nicht die Regelparameter... Beim Ardumower stehen die unterhalb der Skip to Progress.
Versuche mal noch die Schaltfläche "DEBUG" auf an zu stellen und guck ob die Stanley dann auftauchen!

... Gerade probiert, DEBUG ON und die Stanley Werte werden angezeigt.
 
Hmmm, ja... das ist ja Doof. Du kannst die Geschwindigkeit verändern, aber nicht die Regelparameter... Beim Ardumower stehen die unterhalb der Skip to Progress.
Versuche mal noch die Schaltfläche "DEBUG" auf an zu stellen und guck ob die Stanley dann auftauchen!

... Gerade probiert, DEBUG ON und die Stanley Werte werden angezeigt.
OK. Danke für den Tip. Nach DEBUG anschalten werden tatsächlich die Stanley-Werte zum Verändern angezeigt. Wäre ich nie drauf gekommen! Steht meines Wissens auch in nicht in den ohnehin relativ dürftigen Anleitungen. Auch in den Release Informationen sind ja nur sehr sparsame (und definitiv nicht vollständige) Informationen über die erfolgten Änderungen / Bugfixes.
Da ich dieses erweiterte Menu bisher nicht kannte, habe ich für mich natürlich auch nicht dokumentiert, wie die Stanley-Werte in früheren Releases (die dieses "Schwänzeln" an meinem Perimeter nicht hatten) standardmäßig eingestellt waren und wie sie sich verändert haben.
Muß mich also jetzt näher mit diesen Werten und deren Bedeutung beschäftigen und dann etwas "experimentieren". Erste Hinweise hattest Du ja freundlicherweise schon gegeben.
 
Du kannst experimentieren.

Zum Verständnis:
Bei dock werden die Slow parameter angewandt, ich bin mir nicht sicher ob auch bei nearpoint, glaube aber nicht.

P ist der angular gain. Wenn also der mower im winkel zum punkt abweicht, desto mehr, desto mehr wird angular angewandt. Es kann aber sein, dass der winkelfehler klein ist und er kaum lenkt, aber neben der Spur entlang zum Punkt fährt. Dann kommt K zum einsatz und kämpft gegen P, weil er drehen muss und einen winkelfehler erzeugt. Desto weiter er von der spur abweicht, desto mehr kommt K zum tragen und gewinnt gegen P. K und P sollten meiner Erfahrung nach keine große Differenz haben damit der Mower auch wirklich auf der Spur bleibt. Du kannst dir das also als Paar vorstellen. Desto größer beide Werte, desto agiler setzt er z.b kleine Fehler um. Desto geringer, muss der Fehler zur Bahn und oder Winkel immer größer werden, bevor sichtlich etwas passiert.
 
Du kannst experimentieren.

Zum Verständnis:
Bei dock werden die Slow parameter angewandt, ich bin mir nicht sicher ob auch bei nearpoint, glaube aber nicht.
@Mr. Tree Noch eine Frage dazu, bevor ich mich ans Verändern mache:
Bei mir sind die standardmäßig eingestellten Parameter für "normal" und "slow" exakt gleich (siehe Bild). Ist das denn so normal?

1694515488656.png
 
Die Werte sind von der App Standard... aber die sind nicht im Mower.
Im Mower ist wahrscheinlich normal p 3 k 1 und slow p 3 und k0.1

Versuche mal k normal auf 2 zu setzen.

Du kannst dir eine testmap mit Kurven und geraden machen.
 
@Mr. Tree : Hattest du nicht weiter oben geschrieben, dass die Werte nicht weit auseinander liegen sollen?
Welchen Wertebereich gibt es denn?
0-1
0-10
0-100
0-1000

Nicht so weit auseinander......?!
 
Die Werte sind von der App Standard... aber die sind nicht im Mower.
Im Mower ist wahrscheinlich normal p 3 k 1 und slow p 3 und k0.1
Hier habe ich ein Verständnisproblem. Wenn die Werte aus dem Menu der App auf meinem Windows PC (ggfs. mit meinen individuell vorgenommenen Änderungen) nicht im Alfred sind und dort wirksam werden, welchen Sinn haben dann die Änderungsmöglichkeiten in der App?
Versuche mal k normal auf 2 zu setzen.
Ein erster Test mit K-NORMAL = 2 (statt 0.1, bei unveränderten anderen K und P) führte zu wilden und teilweise schnellen Schwenks, hatte also nicht den gewünschten sondern eher den gegenteiligen Effekt. Auch das Docking verlief damit nicht mehr problemlos.

Hat irgendjemand vielleicht eine Aufstellung darüber, wie sich die Standard-Einstellung der vier K und P Parameter mit den verschiedenen Releases geändert hat?
Damit könnte ich das vorherige Verhalten von Alfred bzgl. dieser vier Parameter nachstellen. (Ich hatte nämlich diese Parameter bisher nie verändert, da mir die Möglichkeit dazu in der App bis gestern gar nicht bekannt war. Mr. Tree hat mich erst auf die Einstellmöglichkeit im "Debug Mode" aufmerksam gemacht.)
 
Das siehst du in der config.h im GitHub. Einfach beim fahren die Werte verändern... wenn die App neu startet stehen diese Werte immer da, unabhängig von dem was auf dem mower ist. K normal ist 1 als config.h Standard. 0.1 als slow Standard. Verändere einfach in 0.1er Schritten.
 
Ich fahre ganz gut wenn k 2/3 von P ist...
Liegt aber sicher auch an der Hardware.

Nehmt einfach k ganz raus, lässt den mäher eine gerade fahren. Dann drehst du ihn beim fahren mit einem Schubs. Jetzt siehst du was P macht... er sollte relativ zügig wieder seine Nase Richtung Punkt justieren. Nun fährt er neben der Bahn... jetzt stellt man k nach, so das er auf die Bahn kommt. Auf der Bahn sollte er dann vielleicht einmal überschwingen. Wenn er zuviel schwingt, k reduzieren oder p noch leicht erhöhen.
 
Hier habe ich ein Verständnisproblem. Wenn die Werte aus dem Menu der App auf meinem Windows PC (ggfs. mit meinen individuell vorgenommenen Änderungen) nicht im Alfred sind und dort wirksam werden, welchen Sinn haben dann die Änderungsmöglichkeiten in der App?

Ein erster Test mit K-NORMAL = 2 (statt 0.1, bei unveränderten anderen K und P) führte zu wilden und teilweise schnellen Schwenks, hatte also nicht den gewünschten sondern eher den gegenteiligen Effekt. Auch das Docking verlief damit nicht mehr problemlos.

Hat irgendjemand vielleicht eine Aufstellung darüber, wie sich die Standard-Einstellung der vier K und P Parameter mit den verschiedenen Releases geändert hat?
Damit könnte ich das vorherige Verhalten von Alfred bzgl. dieser vier Parameter nachstellen. (Ich hatte nämlich diese Parameter bisher nie verändert, da mir die Möglichkeit dazu in der App bis gestern gar nicht bekannt war. Mr. Tree hat mich erst auf die Einstellmöglichkeit im "Debug Mode" aufmerksam gemacht.)
Possible issue is the very slow speed when mower is near a waypoint (<50cm) : in this case firmware adjust speed automatically at 0.1 m/s and if motor don't have enough torque to rotate a very low PWM the motor PWM PID react with stanley control in a looping bad process.
So you need to try to avoid distance between waypoint on your perimeter <0.5 meter or change the code .

Here the linetracker.cpp i use with new speed management
search for linear = and angular = to see the change.
Code:
// Ardumower Sunray
// Copyright (c) 2013-2020 by Alexander Grau, Grau GmbH
// Licensed GPLv3 for open source use
// or Grau GmbH Commercial License for commercial use (http://grauonline.de/cms2/?page_id=153)


#include "LineTracker.h"
#include "robot.h"
#include "StateEstimator.h"
#include "helper.h"
#include "pid.h"
#include "src/op/op.h"


//PID pidLine(0.2, 0.01, 0); // not used
//PID pidAngle(2, 0.1, 0);  // not used
Polygon circle(8);

float stanleyTrackingNormalK = STANLEY_CONTROL_K_NORMAL;
float stanleyTrackingNormalP = STANLEY_CONTROL_P_NORMAL;   
float stanleyTrackingSlowK = STANLEY_CONTROL_K_SLOW;
float stanleyTrackingSlowP = STANLEY_CONTROL_P_SLOW;   

float setSpeed = 0.1; // linear speed (m/s)
float setDockingSpeed = 0.2; // linear speed (m/s)

Point last_rotation_target;
bool rotateLeft = false;
bool rotateRight = false;
bool angleToTargetFits = false;
bool langleToTargetFits = false;
bool targetReached = false;
float trackerDiffDelta = 0;
bool stateKidnapped = false;
bool printmotoroverload = false;
bool trackerDiffDelta_positive = false;

int get_turn_direction_preference() {
  Point target = maps.targetPoint;
  float targetDelta = pointsAngle(stateX, stateY, target.x(), target.y());
  float center_x = stateX;
  float center_y = stateY;
  float r = (MOWER_SIZE / 100);
  float cur_angle = stateDelta;

  if (FREEWHEEL_IS_AT_BACKSIDE) {
      cur_angle = scalePI(stateDelta + PI);
      targetDelta = scalePI(targetDelta + PI);
  }

  // create circle / octagon around center angle 0 - "360"
  circle.points[0].setXY(center_x + cos(deg2rad(0)) * r, center_y + sin(deg2rad(0)) * r);
  circle.points[1].setXY(center_x + cos(deg2rad(45)) * r, center_y + sin(deg2rad(45)) * r);
  circle.points[2].setXY(center_x + cos(deg2rad(90)) * r, center_y + sin(deg2rad(90)) * r);
  circle.points[3].setXY(center_x + cos(deg2rad(135)) * r, center_y + sin(deg2rad(135)) * r);
  circle.points[4].setXY(center_x + cos(deg2rad(180)) * r, center_y + sin(deg2rad(180)) * r);
  circle.points[5].setXY(center_x + cos(deg2rad(225)) * r, center_y + sin(deg2rad(225)) * r);
  circle.points[6].setXY(center_x + cos(deg2rad(270)) * r, center_y + sin(deg2rad(270)) * r);
  circle.points[7].setXY(center_x + cos(deg2rad(315)) * r, center_y + sin(deg2rad(315)) * r);

  // CONSOLE.print("get_turn_direction_preference: ");
  // CONSOLE.print(" pos: ");
  // CONSOLE.print(stateX);
  // CONSOLE.print("/");
  // CONSOLE.print(stateY);
  // CONSOLE.print(" stateDelta: ");
  // CONSOLE.print(cur_angle);
  // CONSOLE.print(" targetDelta: ");
  // CONSOLE.println(targetDelta);
  int right = 0;
  int left = 0;
  for(int i = 0; i < circle.numPoints; ++i) {
    float angle = pointsAngle(stateX, stateY, circle.points[i].x(), circle.points[i].y());
    // CONSOLE.print(angle);
    // CONSOLE.print(" ");
    // CONSOLE.print(i);
    // CONSOLE.print(": ");
    // CONSOLE.print(circle.points[i].x());
    // CONSOLE.print("/");
    // CONSOLE.println(circle.points[i].y());
    if (maps.checkpoint(circle.points[i].x(), circle.points[i].y())) {

            // skip points in front of us
            if (fabs(angle-cur_angle) < 0.05) {
                    continue;
            }

            if (cur_angle < targetDelta) {
                if (angle >= cur_angle && angle <= targetDelta) {
                    left++;
                } else {
                    right++;
                }
            } else {
                   if (angle <= cur_angle && angle >= targetDelta) {
                    right++;
                } else {
                    left++;
                }
            }
    }
  }
  // CONSOLE.print("left/right: ");
  // CONSOLE.print(left);
  // CONSOLE.print("/");
  // CONSOLE.println(right);

  if (right == left) {
          return 0;
  }

  if (right < left) {
          return 1;
  }

  return -1;
}

// control robot velocity (linear,angular) to track line to next waypoint (target)
// uses a stanley controller for line tracking
// https://medium.com/@dingyan7361/three-methods-of-vehicle-lateral-control-pure-pursuit-stanley-and-mpc-db8cc1d32081
void trackLine(bool runControl){ 
  Point target = maps.targetPoint;
  Point lastTarget = maps.lastTargetPoint;
  float linear = setSpeed; 
  bool mow = true;
  if (stateOp == OP_DOCK) mow = false;
  float angular = 0;     
  float targetDelta = pointsAngle(stateX, stateY, target.x(), target.y());     
  if (maps.trackReverse) targetDelta = scalePI(targetDelta + PI);
  targetDelta = scalePIangles(targetDelta, stateDelta);
  trackerDiffDelta = distancePI(stateDelta, targetDelta);                         
  lateralError = distanceLineInfinite(stateX, stateY, lastTarget.x(), lastTarget.y(), target.x(), target.y());       
  float distToPath = distanceLine(stateX, stateY, lastTarget.x(), lastTarget.y(), target.x(), target.y());       
  float targetDist = maps.distanceToTargetPoint(stateX, stateY);
 
  float lastTargetDist = maps.distanceToLastTargetPoint(stateX, stateY); 
  if (SMOOTH_CURVES)
    targetReached = (targetDist < 0.2);   
  else
    targetReached = (targetDist < TARGET_REACHED_TOLERANCE);

  if ( (last_rotation_target.x() != target.x() || last_rotation_target.y() != target.y()) &&
        (rotateLeft || rotateRight ) ) {
    // CONSOLE.println("reset left / right rot (target point changed)");
    rotateLeft = false;
    rotateRight = false;
  }

  // allow rotations only near last or next waypoint or if too far away from path
  // it might race between rotating mower and targetDist check below
  // if we race we still have rotateLeft or rotateRight true
  if ( (targetDist < 0.5) || (lastTargetDist < 0.5) || (fabs(distToPath) > 0.5) ||
       rotateLeft || rotateRight ) {
    if (SMOOTH_CURVES)
      angleToTargetFits = (fabs(trackerDiffDelta)/PI*180.0 < 120);
    else     
      angleToTargetFits = (fabs(trackerDiffDelta)/PI*180.0 < 20);
  } else {
     angleToTargetFits = true;
  }

  if (!angleToTargetFits){
    // angular control (if angle to far away, rotate to next waypoint)
    linear = 0;
    angular = 1.5 * 29.0 / 180.0 * PI; //  29 degree/s (0.5 rad/s);               
    if ((!rotateLeft) && (!rotateRight)){ // decide for one rotation direction (and keep it)
      int r = 0;
      // no idea but don't work in reverse mode...
      if (!maps.trackReverse) {
        r = get_turn_direction_preference();
      }
      // store last_rotation_target point
      last_rotation_target.setXY(target.x(), target.y());
      
      if (r == 1) {
        //CONSOLE.println("force turn right");
        rotateLeft = false;
        rotateRight = true;
      }
      else if (r == -1) {
        //CONSOLE.println("force turn left");
        rotateLeft = true;
        rotateRight = false;
      }
      else if (trackerDiffDelta < 0) {
        rotateRight = true;
      } else {
        rotateLeft = true;
      }

      trackerDiffDelta_positive = (trackerDiffDelta >= 0);
    }       
    if (trackerDiffDelta_positive != (trackerDiffDelta >= 0)) {
      //bber100 remove because repeat each 100ms
      //CONSOLE.println("reset left / right rotation - DiffDelta overflow");
      rotateLeft = false;
      rotateRight = false;
      // reverse rotation (*-1) - slowly rotate back
      angular = 1.5 * 10.0 / 180.0 * PI * -1; //  10 degree/s (0.19 rad/s);               
    }
    if (rotateRight) angular *= -1;
  }
  else {
    // line control (stanley)   
    bool straight = maps.nextPointIsStraight();
    bool trackslow_allowed = true;

    rotateLeft = false;
    rotateRight = false;

    // in case of docking or undocking - check if trackslow is allowed
    if ( maps.isUndocking() || maps.isDocking() ) {
        float dockX = 0;
        float dockY = 0;
        float dockDelta = 0;
        maps.getDockingPos(dockX, dockY, dockDelta);
        float dist_dock = distance(dockX, dockY, stateX, stateY);
        // only allow trackslow if we are near dock (below DOCK_UNDOCK_TRACKSLOW_DISTANCE)
        if (dist_dock > DOCK_UNDOCK_TRACKSLOW_DISTANCE) {
            trackslow_allowed = false;
        }
    }

    if (maps.trackSlow && trackslow_allowed) {
      // planner forces slow tracking (e.g. docking etc)
      if ( maps.isUndocking() || maps.isDocking() )
      {
        linear = setDockingSpeed;
      }         
    } else if (     ((setSpeed > 0.2) && (maps.distanceToTargetPoint(stateX, stateY) < 0.5) && (!straight))   // approaching
          || ((linearMotionStartTime != 0) && (millis() < linearMotionStartTime + 3000))                      // leaving 
       )
    {
      linear = setSpeed / 2; // reduce speed when approaching/leaving waypoints
    }
    else {
      if (gps.solution == SOL_FLOAT)       
        linear = min(setSpeed, setSpeed / 2); // reduce speed for float solution
      else
        linear = setSpeed;         // desired speed
      if (sonar.nearObstacle()) linear = setSpeed / 2; // slow down near obstacles
    }     
    // slow down speed in case of overload and overwrite all prior speed
    if ( (motor.motorLeftOverload) || (motor.motorRightOverload) || (motor.motorMowOverload) ){
      if (!printmotoroverload) {
          CONSOLE.println("motor overload detected: reduce linear speed to 0.1");
      }
      printmotoroverload = true;
      linear = setSpeed / 2;
    } else {
      printmotoroverload = false;
    }   
          
    //angula                                    r = 3.0 * trackerDiffDelta + 3.0 * lateralError;       // correct for path errors
    float k = stanleyTrackingNormalK; // STANLEY_CONTROL_K_NORMAL;
    float p = stanleyTrackingNormalP; // STANLEY_CONTROL_P_NORMAL;   
    if (maps.trackSlow && trackslow_allowed) {
      k = stanleyTrackingSlowK; //STANLEY_CONTROL_K_SLOW;   
      p = stanleyTrackingSlowP; //STANLEY_CONTROL_P_SLOW;         
    }
    angular =  p * trackerDiffDelta + atan2(k * lateralError, (0.001 + fabs(motor.linearSpeedSet)));       // correct for path errors           
    /*pidLine.w = 0;             
    pidLine.x = lateralError;
    pidLine.max_output = PI;
    pidLine.y_min = -PI;
    pidLine.y_max = PI;
    pidLine.compute();
    angular = -pidLine.y;   */
    //CONSOLE.print(lateralError);       
    //CONSOLE.print(",");       
    //CONSOLE.println(angular/PI*180.0);           
    if (maps.trackReverse) linear *= -1;   // reverse line tracking needs negative speed
    // restrict steering angle for stanley  (not required anymore after last state estimation bugfix)
    //if (!SMOOTH_CURVES) angular = max(-PI/16, min(PI/16, angular));
  }
  // check some pre-conditions that can make linear+angular speed zero
  if (fixTimeout != 0){
    if (millis() > lastFixTime + fixTimeout * 1000.0){
      activeOp->onGpsFixTimeout();       
    }       
  }     

  if ((gps.solution == SOL_FIXED) || (gps.solution == SOL_FLOAT)){       
    if (abs(linear) > 0.06) {
      if ((millis() > linearMotionStartTime + 5000) && (stateGroundSpeed < 0.03)){
        // if in linear motion and not enough ground speed => obstacle
        //if ( (GPS_SPEED_DETECTION) && (!maps.isUndocking()) ) {
        if (GPS_SPEED_DETECTION) {         
          CONSOLE.println("gps no speed => obstacle!");
          triggerObstacle();
          return;
        }
      }
    } 
  } else {
    // no gps solution
    if (REQUIRE_VALID_GPS){
      CONSOLE.println("WARN: no gps solution!");
      activeOp->onGpsNoSignal();
    }
  }

  // gps-jump/false fix check
  if (KIDNAP_DETECT){
    float allowedPathTolerance = KIDNAP_DETECT_ALLOWED_PATH_TOLERANCE;     
    if ( maps.isUndocking() || maps.isDocking() ) {
        float dockX = 0;
        float dockY = 0;
        float dockDelta = 0;
        maps.getDockingPos(dockX, dockY, dockDelta);
        float dist = distance(dockX, dockY, stateX, stateY);
        // check if current distance to docking station is below
        // KIDNAP_DETECT_DISTANCE_DOCK_UNDOCK to trigger KIDNAP_DETECT_ALLOWED_PATH_TOLERANCE_DOCK_UNDOCK
        if (dist < KIDNAP_DETECT_DISTANCE_DOCK_UNDOCK) {
            allowedPathTolerance = KIDNAP_DETECT_ALLOWED_PATH_TOLERANCE_DOCK_UNDOCK;
        }
    }
    if (fabs(distToPath) > allowedPathTolerance){ // actually, this should not happen (except on false GPS fixes or robot being kidnapped...)
      if (!stateKidnapped){
        stateKidnapped = true;
        activeOp->onKidnapped(stateKidnapped);
      }           
    } else {
      if (stateKidnapped) {
        stateKidnapped = false;
        activeOp->onKidnapped(stateKidnapped);       
      }
    }
  }
  
  if (mow)  {  // wait until mowing motor is running
    if (millis() < motor.motorMowSpinUpTime + 10000){
      if (!buzzer.isPlaying()) buzzer.sound(SND_WARNING, true);
      linear = 0;
      angular = 0;   
    }
  }

  if (runControl){
    if (angleToTargetFits != langleToTargetFits) {
        //CONSOLE.print("angleToTargetFits: ");
        //CONSOLE.print(angleToTargetFits);
        //CONSOLE.print(" trackerDiffDelta: ");
        //CONSOLE.println(trackerDiffDelta);
        langleToTargetFits = angleToTargetFits;
    }

    motor.setLinearAngularSpeed(linear, angular);     
    if (detectLift()){
       mow = false; // in any case, turn off mower motor if lifted
       motor.setMowState(mow);   
    }
  }

  if (targetReached){
    rotateLeft = false;
    rotateRight = false;
    activeOp->onTargetReached();
    bool straight = maps.nextPointIsStraight();
    if (!maps.nextPoint(false,stateX,stateY)){
      // finish       
      activeOp->onNoFurtherWaypoints();     
    } else {     
      // next waypoint         
      //if (!straight) angleToTargetFits = false;     
    }
  } 
}
 
Vielleicht ist auch p zu hoch für den Alfred, ich weiß es leider nicht. Es gab jedenfalls eine änderung die die Stanley Werte für angular nicht mehr begrenzt. Das könnte vllt etwas mit deinen Beobachtungen zu tun haben. Für die Stanley Justierung sollte der mower soliden fix haben! Ich gehe immer so Ran: ich nehme den mower einfach beim fahren von der Bahn und versetze ihn zügig um mir sein Regelverhalten anzusehen. Für P reicht wie gesagt ein ... kleiner Schubs mit dem Fuss ;)
 
Zuletzt bearbeitet:
Oben