Perimeterfahrt im Zick Zack

mediamarco

New member
Hallo,

mein Mäher ist jetzt soweit, dass er Altagstauglich ist. Leider trift dies nicht auf das Perimetertracking zu. Er eiert auf dem Draht schon enorm hin und her. Somit funktioniert auch das Einfahren in die Ladestation nur in der Hälfte der Fälle, weil er einfach zu Schräg reinkommt. Ich habe schon alle möglichen Einstellungen in der Pfod App durchprobiert, aber ich mache es immer nur Schlimmer. In diversen Videos ist zu sehen, dass der Ardumower den Perimeterdraht auch ziemlich gerade verfolgen kann. Meine Schleife hat auch keine 90° Ecken mehr, sondern nur noch 2x 45° Ecken, da er sonst völlig vom Weg abgewichen ist. Welche Einstellungen kann ich verändern, dass die Schleife sauber verfolgt wird?

Setup:
Gehäuse entspricht weitestgehend dem Original
Board 1.2 mit 12 Volt
Azurit1.0a6
 
Vielen Dank,

aber was muss ich mit folgendem ersetzen? Wenn ich es einfach anfüge, kann ich es nicht kompilieren.

And the function you need to replace with one tonne of comment


Code:
//PID controller: track perimeter
void Robot::motorControlPerimeter() {

//3 states
//wire is lost
//On the wire staright line pid fast action
//Back slowly to the wire pid soft action


//Control the perimeter motor only each 30ms
  if (millis() < nextTimeMotorPerimeterControl) return;
  nextTimeMotorPerimeterControl = millis() + 30; //possible 15ms with the DUE
  //tell to the pid where is the mower   (Pid.x)
  perimeterPID.x = 5 * (double(perimeterMag) / perimeterMagMaxValue);
  //tell to the Pid where to go (Pid.w)
  if (perimeterInside) {
  perimeterPID.w = -0.5;
  }
  else {
    perimeterPID.w = 0.5;
  }
  //parameter the PID 
  perimeterPID.y_min = -motorSpeedMaxPwm ;
  perimeterPID.y_max = motorSpeedMaxPwm ;
  perimeterPID.max_output = motorSpeedMaxPwm ;
//and compute
  perimeterPID.compute();


//First state wire is lost
//important to understand TrackingPerimeterTransitionTimeOut It's if during this maximum duration the robot does not make a transition in and  out then it is supposed to have lost the wire, the PID is stopped to go into blocking mode of one of the two wheels. 
// If the trackingPerimeterTransitionTimeOut is too large the robot goes too far out of the wire and goes round in a circle outside the wire without finding it



// If the second condition is true the robot has lost the wire since more trackingPerimeterTransitionTimeOut (2500ms) for example it is then necessary to stop one of the 2 wheels to make a half turn and find again the wire
  if ((millis() > stateStartTime + 10000) && (millis() > perimeterLastTransitionTime + trackingPerimeterTransitionTimeOut)) {
     
	//If this condition is true one of the 2 wheels makes backward the other continues with the result of the PID (not advised)
	if (trackingBlockInnerWheelWhilePerimeterStruggling == 0) { //
      if (perimeterInside) {
        rightSpeedperi = max(-MaxSpeedperiPwm, min(MaxSpeedperiPwm, MaxSpeedperiPwm / 2  + perimeterPID.y));
        leftSpeedperi = -MaxSpeedperiPwm / 2;
      }
      else {
        rightSpeedperi = -MaxSpeedperiPwm / 2;
        leftSpeedperi = max(-MaxSpeedperiPwm, min(MaxSpeedperiPwm, MaxSpeedperiPwm / 2 - perimeterPID.y));
      }
    }
	//If this condition is true one of the 2 wheels stop rotate the other continues with the result of the PID (advised)
    if (trackingBlockInnerWheelWhilePerimeterStruggling == 1) {
      if (perimeterInside) {
        rightSpeedperi = max(-MaxSpeedperiPwm, min(MaxSpeedperiPwm, MaxSpeedperiPwm / 2  + perimeterPID.y));
        leftSpeedperi = 0;
      }
      else {
        rightSpeedperi = 0;
        leftSpeedperi = max(-MaxSpeedperiPwm, min(MaxSpeedperiPwm, MaxSpeedperiPwm / 2 - perimeterPID.y));
      }
    }
	
	//send to motor
    setMotorPWM( leftSpeedperi, rightSpeedperi, false);
    // we record The time at which the last wire loss occurred
    lastTimeForgetWire = millis();
// if we have lost the wire from too long time (the robot is running in a circle outside the wire we stop everything)
    if (millis() > perimeterLastTransitionTime + trackingErrorTimeOut) {
      Console.println("Error: tracking error");
      addErrorCounter(ERR_TRACKING);
      //setNextState(STATE_ERROR,0);
      setNextState(STATE_PERI_FIND, 0);
    }
	// out of the fonction until the next loop  
    return;
  }

  

 // here we have just found again the wire we need a slow return to let the pid temp react by decreasing its action (perimeterPID.y / 2)
  if ((millis() - lastTimeForgetWire ) < trackingPerimeterTransitionTimeOut / 1.5 ) {
    rightSpeedperi = max(0, min(MaxSpeedperiPwm, MaxSpeedperiPwm / 2 +  perimeterPID.y / 2));
    leftSpeedperi = max(0, min(MaxSpeedperiPwm, MaxSpeedperiPwm / 2 -  perimeterPID.y / 2));
 }
  else
//we are in straight line the pid is total and not/2
  {
    rightSpeedperi = max(0, min(MaxSpeedperiPwm, MaxSpeedperiPwm/1.5   + perimeterPID.y));
    leftSpeedperi = max(0, min(MaxSpeedperiPwm, MaxSpeedperiPwm/1.5  - perimeterPID.y));
    
  }

  setMotorPWM( leftSpeedperi, rightSpeedperi, false);


  //if the mower move in perfect straight line the transition between in and out is longuer so you need to reset the perimeterLastTransitionTime
    
if (abs(perimeterMag ) < perimeterMagMaxValue/4) { 
    perimeterLastTransitionTime = millis(); //initialise perimeterLastTransitionTime in perfect sthraith line
  }

  
}
 
Such mal in motor.h die Funktion void Robot::motorControlPerimeter() - bei mir startet die in Zeile 224.
Die gesamte Funktion auskommentieren oder löschen und die neue Funktion einbauen.

Gruss
Wolfgang
 
eine Motor.h gibt es bei mir nicht. ich habe die Funktion allerdings in der robot.cpp gefunden und ersetzt, mit dem Ergebnis, das er jetzt alle 2-5 Sekunden nicht mehr innerhalb der Schleife ist und somit die Richtung wechselt.
 
Autsch - wer lesen kann hat mehr vom Leben :) :) :)
Habe übersehen, dass Du die Azurit 1.0a6 hast.
Ich "fahre" mit der 1.0a7 dev und habe die Änderungen aus Post #12516 und #12526 eingebaut - das hat auf Anhieb funktioniert.
So wie ich es aus dem Thread verstehe, arbeitet Alex auch mit der 1.0a6 und hat ebenfalls Erfolg mit den angegebenen Änderungen.
Vielleicht noch einmal neu aufspielen, ADC calibration und Factory settings.

Gruss
Wolfgang
 
Hallo,

ich habe jetzt noch einmal ganz von vorn angefangen. Jetzt bin ich sicher auf dem neusten Softwarestand. ich habe jetzt 1.0a8-Azurit drauf. das Tracking ist jetzt auch deutlich besser nach dem Einbau von besagtem Code. (Warum ist der eigentlich nicht Standardmäßig drin) Aber der Mower ist noch sehr langsam auf dem Perimeter unterwegs. An welcher stelle kann man denn die Geschwindigkeit anpassen? Momentan braucht er ewig um die Schleife abzufahren. Da müsste ich ja allein für den Heimweg einen XXL Akku einbauen.

Gruß
Marco
 
Hallo Marco,
schön, dass es schon besser läuft.
PFOD App - Settings - Motor - Speed max in pwm stellt die Geschwindigkeit auf der Schleife. Ich "fahre" mit 160. Alex, Bernard und Chris haben in dem genannten Thread auch viel mit der Geschwindigkeit gespielt und dafür eine eigene Variable deklariert. Habe ich bei mir (noch) nicht eingebaut , da ich es (noch) nicht brauche.

Gruss
Wolfgang
 
Hallo,

kann es sein das die Perimeterfahrt bei mir so schlecht funktioniert, weil ich keine Odometrie habe? Speed max in pwm steht bei mir auf 255 stelle ich den Wert tiefer ein, fährt der Mäher im Normalbetrieb langsamer, aber auf dem Perimeter bleibt die Geschwindigkeit gleich langsam. Er braucht teilweise eine Minute für einen Meter.
 
mediamarco schrieb:
Hallo,

ich habe jetzt noch einmal ganz von vorn angefangen. Jetzt bin ich sicher auf dem neusten Softwarestand. ich habe jetzt 1.0a8-Azurit drauf. das Tracking ist jetzt auch deutlich besser nach dem Einbau von besagtem Code. (Warum ist der eigentlich nicht Standardmäßig drin)
...
Gruß
Marco

Alexander hat den Code mal rein genommen.
Allerdings läuft das nicht richtig, das einfahren in die Schleifen funktioniert nicht richtig.
Mehrmaliges drehen bis er dann unter Umständen der Schleife folgt.
Die Motoren werden viel zu hart angesteuert.
Das ganze wurde auch von mir getestet, geht denke ich in die richtige Richtung aber ist noch nichts Alltagstaugliches das Problemlos funktioniert. https://www.youtube.com/watch?v=9OusAOOsQOk&feature=youtu.be Wir nehmen gerne Verbesserungen auf, diese sollten mit dem Standard Equipment allerdings Problemlos funktionieren. :)
Vielleicht bekommen wir es ja zum laufen wenn alle mit testen und dran arbeiten.
 
Zuletzt bearbeitet von einem Moderator:
mediamarco schrieb:
Hallo,

kann es sein das die Perimeterfahrt bei mir so schlecht funktioniert, weil ich keine Odometrie habe? Speed max in pwm steht bei mir auf 255 stelle ich den Wert tiefer ein, fährt der Mäher im Normalbetrieb langsamer, aber auf dem Perimeter bleibt die Geschwindigkeit gleich langsam. Er braucht teilweise eine Minute für einen Meter.
Alles was wir Entwickeln ist auf das Standard Equipment ausgerichtet, also Motoren mit Odometrie. Das ist für einen Rasenroboter mit dem auch mal Navigiert werden soll ein muss. Wenn man es ganz einfach halten will gehts natürlich auch ohne Odometrie, muss man halt dann Abstriche bei einigen Sachen machen.
 
Zuletzt bearbeitet von einem Moderator:
Mich würde interessieren ob wir beim Einpflegen des Pull-Requests von holoratte (dem "Erfinder" des "Advanced Tracking") etwas falsch gemacht haben. Ich habe daher holoratte mal gefragt warum der Code nicht das gewünschte Ergebnis zeigt (https://github.com/Ardumower/ardumower/pull/114).
Vielleicht kann ja jemand mal drüber schauen was beim "Mergen" falsch gelaufen sein könnte. Oder jemand kann unsere Entwickler-Version (Github Master-Zweig) einmal ausprobieren bei dem es schon zuvor mit manuellem Einpflegen der Änderung gut lief?

Hier ist die aktuelle Entwickler-Version mit dem durchgeführten Pull-Request (Advanced Tracking eingepflegt ) welche bei uns überhaupt nicht gut laufen will:
https://github.com/Ardumower/ardumower
 
Hallo Wolfgang,
danke Dir - der Code sieht genauso aus wie der von Holoratte welcher jetzt im Github eingepflegt ist (ich sehe da keinen Unterschied) - Dennoch bekommen wir es nicht zum Laufen (siehe Video im Beitrag von Markus). Vielleicht kann jemand mal den aktuellen Github-Code ausprobieren (dieser wurde u.a. auch für PCB1.3 optimiert, z.B. Ladevorgang uvm.).
Gruss,
Alexander
 
Hallo Zusammen,

habe eben de Azurit1.08a code von Alexander auf SheepSheep getestet. Sie hat beim Einlenken zum Perimeter auch 2 Runden gebraucht danach ist das Tracking mit reduziertem perimeterPID.p = 25 aber schön flüssig. Der Rest war alles mit den Factory settings aus dem code.
Ich schau ev. am WE nochmal drüber, falls bis dahin noch keine Lösung gefunden wurde.


Gruess

Chris
 
Hallo Alexander,
ich habe jetzt mal die neue Version - 1.0a8 - Azurit - dev - ausprobiert mit den gleichen Ergebnissen beim Einfädeln wie es Markus auch schon dargestellt hat. Darüberhinaus ist mir folgendes aufgefallen:
- Das Einschalten nach einem Notaus funktioniert besser als in der 1.0a7
- Der Mower fährt jetzt nicht mehr geradeaus - funktionierte sehr gut in der 1.0a7
- Das Einfädeln funktioniert schlecht bis gar nicht - ich hatte bei 3 von 4 Versuchen Fehler - der Mower geht dann in status Error
- Wenn er eingefädelt hat, hält er sich einigermassen auf dem Perimeter
- Die Steuerung im manuell Mode ist anders - Links/Rechts wirkt anders als in den vorigen Versionen, ist aber vielleicht so gewollt
- Nach einem Stop im manuell Mode dauert es sehr lange - 3-5 Sekunden - bis er stehenbleibt. Bremst auch nicht gleichmässig ab, sondern dreht sich dabei
- Beim Überfahren der Schleife hat er das gleiche "Bremsverhalten" wie im manuell Mode
- Beim Zurücksetzen, nach Überfahren der Schleife, setzt er nicht gerade zurück - dreht sich dabei
Insgesamt sind alle Bewegungen des Schafes recht ungenau. Konnte leider nicht weiter testen, da es angefangen hat zu regnen.
Hier zwei Videos vom Perimeter Tracking erst mit der "alten" und dann mit der neuen Softwareversion.

1.0a7-Azurit-dev modified

1.0a8-Azurit-dev

Ich hoffe die Videos funktionieren - weiss nicht wie ich die hier einbinden kann.

Gruss
Wolfgang
 
Vielen Dank euch beiden für die Tests! - @Wolfgang: hört sich danach an als wenn in "mower.h" das falsche PCB gewählt ist (für PCB1.3 wird ein Odometrie-Teiler aktiviert)
 
Hi alexander and all
I follow this post with Google translate so hope i understand all B)

I download the master dev code on Github.
I put it in my Denna with Board v1.2 and Yes there is a big problem with the tracking .

After some search i constate that the motorControlPerimeter is not exactly what i send to Holoratte and Alda on my post 12516 (i thing some {} are not at the right place)

When i put again the right code the tracking work again so here the change to make it work.

First and very important the trackingPerimeterTransitionTimeOut = 0 can't work so in mower.cpp please replace it by this value.

In Mower.cpp

Code:
trackingPerimeterTransitionTimeOut              = 2500;   // never<500 ms

After i 'am not sure (because i use the DUE and special ADCMAN) that the perimeterMagMaxValue is correctly read (maybe on the Mega it's ok).
And not sure it's a good idea to read a value at one point for 200 meter for example of tracking so for me this value need to stay fixed in mower.cpp.

So to be sure and don't make change in your code i set the value to 2000 at the begenning of the function ,or try to remove this line to see if the Holoratte code read it correctly..

With this change and
MaxSpeedperiPwm=160
Perimeter P=16.00 I=8 D=0 the tracking is perfect.

So hope it can work with you.

I prefer to remove my tonne of comment and if you have problem i can send you a debuging version with all the Console.print to find a problem.

In motor.h replace the motorControlPerimeter by this one.


Code:
void Robot::motorControlPerimeter() {
PerimeterMagMaxValue=2000;  //need to change in the future 	
  if (millis() < nextTimeMotorPerimeterControl) return;
  nextTimeMotorPerimeterControl = millis() + 30; //bb read the perimeter each 50 ms
    
  perimeterPID.x = 5 * (double(perimeterMag) / perimeterMagMaxValue);

 
  if (perimeterInside) {
    perimeterPID.w = -0.5;
  }
  else {
    perimeterPID.w = 0.5;
  }


  perimeterPID.y_min = -MaxSpeedperiPwm ;
  perimeterPID.y_max = MaxSpeedperiPwm ;
  perimeterPID.max_output = MaxSpeedperiPwm ;
  perimeterPID.compute();

  if ((millis() > stateStartTime + 10000) && (millis() > perimeterLastTransitionTime + trackingPerimeterTransitionTimeOut)) {
    // robot is wheel-spinning while tracking => roll to get ground again

    if (trackingBlockInnerWheelWhilePerimeterStruggling == 0) {
      if (perimeterInside) {
        rightSpeedperi = max(-MaxSpeedperiPwm, min(MaxSpeedperiPwm, MaxSpeedperiPwm / 1.5  + perimeterPID.y));
        leftSpeedperi = -MaxSpeedperiPwm / 2;
      }
      else {
        rightSpeedperi = -MaxSpeedperiPwm / 2;
        leftSpeedperi = max(-MaxSpeedperiPwm, min(MaxSpeedperiPwm, MaxSpeedperiPwm / 1.5 - perimeterPID.y));
      }
    }
    if (trackingBlockInnerWheelWhilePerimeterStruggling == 1) {
      if (perimeterInside) {
        rightSpeedperi = max(-MaxSpeedperiPwm, min(MaxSpeedperiPwm, MaxSpeedperiPwm / 1.5  + perimeterPID.y));
        leftSpeedperi = 0;
      }
      else {
        rightSpeedperi = 0;
        leftSpeedperi = max(-MaxSpeedperiPwm, min(MaxSpeedperiPwm, MaxSpeedperiPwm / 1.5 - perimeterPID.y));
      }
    }
    
    setMotorPWM( leftSpeedperi, rightSpeedperi, false);

    lastTimeForgetWire = millis();

    if (millis() > perimeterLastTransitionTime + trackingErrorTimeOut) {
      Console.println("Error: tracking error");
      addErrorCounter(ERR_TRACKING);
      setNextState(STATE_PERI_FIND, 0);
    }
    return;
  }

  if ((millis() - lastTimeForgetWire ) < trackingPerimeterTransitionTimeOut) {
    //PeriCoeffAccel move gently from 3 to 1 and so perimeterPID.y/PeriCoeffAccel increase during 3 secondes
    PeriCoeffAccel = (3000.00 - (millis() - lastTimeForgetWire)) / 1000.00 ;
    if (PeriCoeffAccel < 1.00) PeriCoeffAccel = 1.00;
    rightSpeedperi = max(0, min(MaxSpeedperiPwm, MaxSpeedperiPwm / 1.5 +  perimeterPID.y / PeriCoeffAccel));
    leftSpeedperi = max(0, min(MaxSpeedperiPwm, MaxSpeedperiPwm / 1.5 -  perimeterPID.y / PeriCoeffAccel));
    
  }
  else
  {
    rightSpeedperi = max(0, min(MaxSpeedperiPwm, MaxSpeedperiPwm / 1.5   + perimeterPID.y));
    leftSpeedperi = max(0, min(MaxSpeedperiPwm, MaxSpeedperiPwm / 1.5  - perimeterPID.y));
    
  }

  setMotorPWM( leftSpeedperi, rightSpeedperi, false);



  if (abs(perimeterMag ) < perimeterMagMaxValue / 4) { //300 can be replace by timedOutIfBelowSmag to be tested
    perimeterLastTransitionTime = millis(); //initialise perimeterLastTransitionTime if perfect sthraith line
  }

  
}
 
Hi Bernard,

ich habe keinen Unterschied in der motor.h gefunden ausser:
//I did not find any difference in the code of motor.h, except:


Code:
perimeterPID.y_min = -MaxSpeedperiPwm ;
  perimeterPID.y_max = MaxSpeedperiPwm ;
  perimeterPID.max_output = MaxSpeedperiPwm ;

//and perimeter perimeterMagMaxValue is fix.
und perimeterMagMaxValue ist fix.

Ich werde dann noch
Code:
trackingPerimeterTransitionTimeOut              = 2500;   // never<500 ms

testen. das könnte die einfahrt in den Perimeter beeinflussen.?
//Could trackingPerimeterTransitionTimeOut influence the beginning of PERI_TRACK ?

EDIT: now I see some {} are in the wrong place at the end of the function... trying your function tomorrow...
also I have found this line missing in your code of today:

Code:
if ((trackingErrorTimeOut != 0) && (millis() > perimeterLastTransitionTime + trackingErrorTimeOut)){




Gruess

Chris
 
Hi Holoratte
Hope we are loocking at the same code (For me it's the last Azurit 1.08 in master branch on Github)
Yes the first difference is normal it's Alda who find this missing and it's better to use the tracking speed here.
But i spend time to find the error but there is a difference
In the arduino IDE line

Code:
if ((millis() > stateStartTime + 10000) && (millis() > perimeterLastTransitionTime + trackingPerimeterTransitionTimeOut)){
If you click on the last { you are going to see that this condition don' t finish at the right place in fact at the end of the code and it' s here the problem.
The transition timeout at 0 is also very bad for the tracking.

And concerning the PerimeterMagMaxValue i remenber that i tell you it's a good idea but after more reflexion i'am not sure because if the tracking begin in a place where the wire is far Under the ground all the rest of the tracking can be bad, so test and test again and view. And remenber the Mega is limit power on calcul.


The main is that it's work.

I constate also that the OFF state don't stop immediatly the mower and i'm going to see the week end if i can understand why .
Also the motorZeroSettleTime = 3000 ; is too long for my Denna so the perioutrev don't work inned to put 2000 to make the mower work corectly.

By.

And now GOOGLE try to Translate

Hallo Holoratte
Wir hoffen, dass wir am selben Code anhängen (für mich ist es der letzte Azurit 1.08 im Master-Zweig auf Github)
Ja, der erste Unterschied ist normal, es ist Alda, der das fehlt und es ist besser, die Tracking-Geschwindigkeit hier zu benutzen.
Aber ich verbringe Zeit, um den Fehler zu finden, aber es gibt einen Unterschied
In der arduino IDE Linie
If ((millis ()> stateStartTime + 10000) && (millis ()> perimeterLastTransitionTime + trackingPerimeterTransitionTimeOut)) {
Wenn du auf den letzten klickst, wirst du sehen, dass dieser Zustand nicht am richtigen Platz am Ende des Codes endet und es ist hier das Problem.
Die Übergangszeitüberschreitung bei 0 ist auch sehr schlecht für die Verfolgung.

Und in Bezug auf die PerimeterMagMaxValue Ich remenber, dass ich Ihnen sagen, es ist eine gute Idee, aber nach mehr Reflexion Ich bin nicht sicher, denn wenn das Tracking an einem Ort, wo der Draht ist weit unter dem Boden alle anderen der Tracking kann schlecht sein, so Teste und teste nochmal und schau mal. Und remenber die Mega ist Limit Macht auf calcul.


Das Haupt ist, dass es Arbeit ist.

Ich konstituiere auch, dass der OFF-Zustand nicht sofort den Mäher stoppt und ich werde das Wochenende sehen, wenn ich verstehen kann warum.
Auch die motorZeroSettleTime = 3000; Ist zu lang für meine Denna, so dass die Perioutrev nicht arbeiten engged, um 2000 zu machen, um die Mäherarbeit kernweise zu machen.

Durch.
 
Oben