Mähzonen über GPS Punkte

thorsten-ac

Active member
Hallo zusammen,

ich habe im alten Forum gesehen das sich User mit Mähzonen beschäftigt haben und finde das Projekt echt super, leider habe ich Schwierigkeiten das in die aktuelle AZURIT zu implementieren.

Kann mir einer Helfen ?


vg
Thorsten
 
ich Hänge grate an der Stelle …...

^
exit status 1
'ttimer_t' has no member named 'Area_Timer'

einer ne Idee?
 

Anhänge

  • Area_timer.PNG
    Area_timer.PNG
    65,1 KB · Aufrufe: 23
kleines update jetzt hänge ich an

no matching function for call to 'RemoteControl::sendSlider(StringSumHelper&, const __FlashStringHelper*, timehm_t&, const char [1], int, int, int)'
 
Hallo,

Ich Versuche dem mover beizubringen das es mehrere Flächen gibt ( vor dem Haus und hinter dem Haus ). Die Flächen soll der mover finden in dem er die Perimeterschleife abfährt bis ehr einen gps Punkt erreicht hat.

Einige User hatten da schonmal was gemacht jedoch fehlt eine bisschen was an Code .

VG
 
Hallo Thorsten,
um ein genaues GPS-Signal zu bekommen, braucht man ein Referenz-Signal -> Kosten.
Da halt ich die RFID Ansätze für besser. Am Perimeterdraht verscharrt, erhält der Mäher beim drüberfahren Anweisung was er tun soll.
Eine andere Alternative wäre Bilderkennung. Ich habe zum Testen eine esp32-cam auf den Mäher montiert. Die erkennt Gesichter. Also könnte sie auch andere markante Merkmale unterscheiden (Mäher-Verkehrsschilder). Schnittstelle RX/TX ist vorhanden, bzw. noch einige, wenige Ports. Kosten sehr gering.
Gruß Fürst Ruprecht
 
Hallo,
Nach meiner Vorstellung benötige ich nur einen Punkt Längengrad/breitengrad, die Toleranz von ca 2m kann dabei ignoriert werden.

Der Mower soll dann die Schleife solange abfahren bis er in die Nähe ( Radius 2m) von diesem Punkt kommt und dann anfängt zu mähen.


Die Funktion wurde ja schonmal von Usern umgesetzt, leider nicht ausreichend dokumentiert

VG
Thorsten
 
Hallo,
das kann dann nicht so schwierig sein-> Abfrage der GPS-Koordinate -> im Toleranzfeld? -> setNextState(STATE_FORWARD) zb.
Gruß Fürst Ruprecht
 
Hallo,
ja, ist es aber leider nicht :|

in robot.h
Code:
struct Point
{
    float X;
    float Y;
};

typedef struct Point Point;


unsigned long Peri_Track_P1;
    unsigned long Peri_Track_P2;
    unsigned long Peri_Track_P3;
    unsigned long Peri_Track_P4;
    unsigned long Peri_Track_P5;
    unsigned long Peri_Track_P6;
    unsigned long Peri_Track_P7;

    int Peri_find_Point;
    int Peri_found_Point;
    unsigned long find_Point_EndTime;

    float lon_mid;
    float lat_mid;

    int Area_Soll;
    int Area_Ist;

    int Out_of_Area_Timer;

In Robot.cpp vor void Robot::processGPSData()

Code:
//----------------------------------------------------------------------------------------------------------------------------
// Abstand von Robby zu einem definierten Punkt
//----------------------------------------------------------------------------------------------------------------------------

bool Abstand(Point p, Point r) {     //  int x1, int y1, int x2, int y2) {
  float distx;
  float disty;
  float l;
  if (p.X>=r.X)  distx= p.X-r.X;
  else  distx= r.X-p.X;
  if (p.Y>=r.Y)  disty= p.Y-r.Y;
  else  disty= r.Y-p.Y;
  l =(sqrt((float)(distx*distx)+(float)(disty*disty)));
  Console.println("Abstand: ");
  printDouble(l,6);
  return l <= 0.000030;
}

void Robot::processGPSData()

Code:
void Robot::processGPSData()
{
  if (millis() < nextTimeGPS) return;
  nextTimeGPS = millis() + 1000;
  float nlat, nlon;
  unsigned long age;

  Point P1,P2,P3,P4, P_ROBI;

  gps.f_get_position(&nlat, &nlon, &age);
  if (nlat == GPS::GPS_INVALID_F_ANGLE ) return;
  if (gpsLon == 0){
    gpsLon = nlon;  // this is xy (0,0)
    gpsLat = nlat;
    return;
  }
  gpsX = (float)gps.distance_between(nlat,  gpsLon,  gpsLat, gpsLon);
  gpsY = (float)gps.distance_between(gpsLat, nlon,   gpsLat, gpsLon);

  P_ROBI.X = nlon;
  P_ROBI.Y = nlat;




// Console.println("ROBBY: ");
// printDouble(P_ROBI.X,6);
//  printDouble(P_ROBI.Y,6);


  //----------------   Area 1  --------------------------------------------------------

  P1.X = xx.671150; P1.Y= xx.102400;
  if (Abstand(P1, P_ROBI)) Area_Ist = 1;

  P1.X = xx.671170; P1.Y= xx.102370;
  if (Abstand(P1, P_ROBI)) Area_Ist = 1;

  //----------------   Area 2  --------------------------------------------------------

  P1.X = xx.671040; P1.Y= xx.102440;
  if (Abstand(P1, P_ROBI)) Area_Ist = 2;

  P1.X = xx.671030; P1.Y= xx.102370;
  if (Abstand(P1, P_ROBI)) Area_Ist = 2;

  //----------------   Area 3  --------------------------------------------------------

  P1.X = xx.671280; P1.Y= xx.102480;
  if (Abstand(P1, P_ROBI)) Area_Ist = 3;

  P1.X = xx.671260; P1.Y= xx.102470;
  if (Abstand(P1, P_ROBI)) Area_Ist = 3;

  //----------------   Area 4  --------------------------------------------------------

  P1.X = xx.671270; P1.Y= xx.102630;
  if (Abstand(P1, P_ROBI)) Area_Ist = 4;

  //----------------   Area 5  --------------------------------------------------------

    P1.X = xx.671170; P1.Y= xx.102620;
  if (Abstand(P1, P_ROBI)) Area_Ist = 5;

      P1.X = xx.671090; P1.Y= xx.102590;
  if (Abstand(P1, P_ROBI)) Area_Ist = 5;


  if (Area_Ist == Area_Soll) Out_of_Area_Timer = millis();

  if ((Area_Soll == 0)& (Area_Ist > 0))  Area_Soll = Area_Ist;    // Wenn Schaf in einer Area gestartet wird dann mäht  er auch in dieser Area
   
}

In der state machine

Code:
case STATE_FORWARD:
      // driving forward          
      if (mowPatternCurr == MOW_BIDIR){
        double ratio = motorBiDirSpeedRatio1;
        if (stateTime > 4000) ratio = motorBiDirSpeedRatio2;
        if (rollDir == RIGHT) motorRightSpeedRpmSet = ((double)motorLeftSpeedRpmSet) * ratio;
          else motorLeftSpeedRpmSet = ((double)motorRightSpeedRpmSet) * ratio;                          
      }            
      checkErrorCounter();  
      checkTimer();
      checkRain();
      checkCurrent();          
      checkBumpers();
      checkDrop();                                                                                                                            // Dropsensor - Absturzsensor
      checkSonar();            
      checkPerimeterBoundary();
      checkLawn();    
      checkTimeout();    

// ---------------------------------------------------------------------------------------------------------------------------------------------------------
//     Wenn Schaf eine Zeit lang in einem anderen Bereich mäht.. dann wieder zurück fahren in richtigen Bereich
//----------------------------------------------------------------------------------------------------------------------------------------------------------

      if (((Area_Soll == 1) && (Area_Ist ==2)) or ((Area_Soll == 3) && (Area_Ist ==5)))
         if ((millis() - Out_of_Area_Timer) > 180000)
            {
              setNextState(STATE_STATION_FORW,0);  
              Peri_found_Point = 0;  
              Peri_find_Point = 1;  
              find_Point_EndTime = millis() + Peri_Track_P1;    
              Out_of_Area_Timer = millis();
            }

     
      break;

In der Pfod.cpp

Code:
void RemoteControl::sendGPSMenu(boolean update){

float lat, lon;
unsigned long age;
robot->gps.f_get_position(&lat, &lon, &age);

if (update) Bluetooth.print("{:"); else Bluetooth.print(F("{.GPS`1000"));
Bluetooth.print(F("|q00~Use "));
sendYesNo(robot->gpsUse);
sendSlider("q01", F("Stucked if GPS speed is below"), robot->stuckIfGpsSpeedBelow, "", 0.1, 3);
sendSlider("q02", F("GPS speed ignore time"), robot->gpsSpeedIgnoreTime, "", 1, 10000, robot->motorReverseTime);




serialPort->print(F("|zz~LAT : "));
printDouble(lat,6);
serialPort->print(F("|zz~LON : "));
printDouble(lon,6);
serialPort->print(F("|zz~AREA IST : "));
serialPort->print(robot->Area_Ist);
serialport.println("}"); //ersetz durch Bluetooth.println da alt
}

und

Code:
void RemoteControl::sendTimerDetailMenu(int timerIdx, boolean update){
  if (update) serialPort->print("{:"); else serialPort->print(F("{.Details"));
  serialPort->print("|p0");
  serialPort->print(timerIdx);
  serialPort->print("~Use ");
  sendYesNo(robot->timer[timerIdx].active);      
  int startm = time2minutes(robot->timer[timerIdx].startTime);
  int stopm = time2minutes(robot->timer[timerIdx].stopTime);
  String sidx = String(timerIdx);
  sendSlider("p1"+sidx, F("Start hour "), robot->timer[timerIdx].startTime.hour, "", 1, 23, 0);      
  sendSlider("p2"+sidx, F("Start minute "), robot->timer[timerIdx].startTime.minute, "", 1, 59, 0);        
  sendSlider("p3"+sidx, F("Stop hour "), robot->timer[timerIdx].stopTime.hour, "", 1, 23, 0);      
  sendSlider("p4"+sidx, F("Stop minute "), robot->timer[timerIdx].stopTime.minute, "", 1, 59, 0);            
    for (int i=0; i < 7; i++){
    serialPort->print("|p5");
    serialPort->print(timerIdx);
    serialPort->print(i);
    serialPort->print("~");
    if ((robot->timer[timerIdx].daysOfWeek >> i) & 1) serialPort->print("(X)  ");
      else serialPort->print("(  )  ");
    serialPort->print(dayOfWeek[i]);
  }
  serialPort->print("|p9");
  serialPort->print(timerIdx);
  serialPort->print(F("~Set to current time"));
  sendSlider("p8"+sidx, F("Area "), robot->timer[timerIdx].Area_Timer, "", 1, 5, 0);


Code:
void RemoteControl::printDouble( double val, byte precision){
// prints val with number of decimal places determine by precision
// precision is a number from 0 to 6 indicating the desired decimial places
// example: printDouble( 3.1415, 2); // prints 3.14 (two decimal places)
serialPort->print(int(val));  //prints the int part
if( precision > 0) {
   serialPort->print("."); // print the decimal point
   unsigned long frac;
   unsigned long mult = 1;
   byte padding = precision -1;
   while(precision--)
      mult *=10;
   
   if(val >= 0)
     frac = (val - int(val)) * mult;
   else
     frac = (int(val)- val ) * mult;
   unsigned long frac1 = frac;
   while( frac1 /= 10 )
     padding--;
   while(  padding--)
     serialPort->print("0");
   serialPort->print(frac,DEC) ;
}
}
 
Wenn man noch ein paar fehlende Funktionen einbaut bleiben aber noch ein paar fehlende variabelen....

Vg
Thorsten
 
Hallo,

Habe versucht den Code zu integrieren,

leider komme ich jetzt an einen punkt wo ich nicht weiter komme....

anbei mein Projekt
 

Anhänge

  • Ardumower Mäzohne.zip
    135,1 KB · Aufrufe: 2
Zeichnest Du/Ihr die GPS-Punkte in einer Grafik auf? In der Pfod.cpp gibt es Code. In der esp8266 Lösung nicht.
Was nun? Neu erfinden?

Meine pfod/esp8266 Lösung wird immer komplexer und driftet auch weiter vom Original ab. Aber für die Fehlersuche bzw Erarbeitung abweichender Anforderungen ist das für mich eine gute Lösung.
Gut finde ich, daß man von mehreren Geräten gleichzeitig zugreifen kann, zB. Plot (bei mir Live-Data) auf dem Pad, Einstellparameter auf dem Handy, Langzeitaufnahme (Batterie) auf dem PC. Den Pfod-Server auf Port8080 habe ich bereits rausgeschmissen.
Gruß Fürst Ruprecht
 
Hallo,

habe mal ein Bild zur Erläuterung gemacht.

Der Mower wird auf einen Punkt auf dem Perimeterdrat gesetzt Dieser wird dann gespeichert (geplant über webinterface)

der Mower fährt dann solange die schleife ab bis er an den Punkt kommt wo ehr dann mit dem Mähen startet.

Problem ist halt das ich es nicht in die Azurit eingebaut bekomme …..
erst wenn das funktioniert baue ich das in das Webinterface ein...



ESP:

Ja dein Webinterface finde ich echt gut! vorallem deine Plot/API Lösung
Hast du beobachten können das die Performens steigt wenn du den Pfod-Server rausschmeißt?

vg
Thorsten
 

Anhänge

  • GPS.png
    GPS.png
    1 MB · Aufrufe: 13
Zuletzt bearbeitet:
Hallo,

Soooo nun kann ich den Code kompilieren!! :)

in den nächsten Wochen werde ich versuchen den Code zu testen....

An bei das Projekt für den fall das jemand mit Testen mag. zur zeit können 5 Wegpunkte erzeugt werden.

Über die Pfodapp sollten die entsprechenden menüpunkt vorhanden sein.


**UPDATE***
Bei den ersten Tests ist mir aufgefallen das ich ein paar Fehler gemacht habe..... Die sind jetzt korrigiert...….

Neuer Code im Anhang
 

Anhänge

  • Ardumower Mäzohne.zip
    135,1 KB · Aufrufe: 10
Zuletzt bearbeitet:
Hast du beobachten können das die Performens steigt wenn du den Pfod-Server rausschmeißt?

Hallo Thorsten,
Nicht wirklich. Ich habe zu viele Fehler im Code gehabt um etwas zu beobachten. Wenn auf den Port 8080 nicht zugegriffen wird, ist der Leistungszugewinn auf dem ESP wahrscheinlich sehr gering. Da steht in der pfod.cpp schon etwas mehr drinn.
Habe jetzt einen Prototypen gemacht für GPS2D Plot. Werde ihn die Tage mal testen, mal sehen ob das was fürs Forum wird. Ich würde gerne sehen, wie groß das Streufeld der Daten wird.
Gruß Fürst Ruprecht
 
Zwischenstand, gerade im Test:
Ich habe jetzt ohne groß nachzudenken, das GPS2D-Plot-Menü aus der Pfod visualisiert.
Das sind 500 Meßpunkte, jeden einzelnen kann man antippen und die Koordinate, die Uhrzeit und die Nr. (Reihenfolge) anzeigen.
F5FE414C-9E76-4480-8542-6A779B2A8899.png
Mit Infokasten:
0711C6D0-E19F-41DE-9731-4B08C68E3397.png
500 Werte aus der Station: (Stillstand)
E15C4E10-A009-4A9D-9B7C-C19140A253A7.png
Sobald ich einen Stand habe, der halbwegs funktioniert, stelle ich ihn hier https://forum.ardumower.de/threads/4motion-4wd-allrad.23824/ ein.
Gruß Fürst Ruprecht
 
Hallo Leute,

ich benötige eure hilfe,

ich bastel an einer Mähzonen variante für azurit, komme aber nicht weiter.
Nach mehreren versionen und versuchen stehe ich jetzt an einem punkt den ich nicht verstehe:
1) der robi kennt seine Position und die entfernung zu allen 5 punkten
2) er vergleicht ist Position mit soll Position
3) er sucht die Punkte über die funktion Perritrack
4) macht aber dann nicht weiter ...

Hat jemand lust mir auf die Sprünge zu helfen ?

unter den Kommentaren // Mähzonen

findet man meine änderungen

VG
Thorsten
 

Anhänge

  • ardumower.zip
    136,3 KB · Aufrufe: 2
Moin,
ich habe deinen Code nur kurz überflogen, habe aber gleich mal eine Frage.
So wie es aussieht benutzt du nicht die TinyGPS++ Libary?
Wäre es nicht einfacher, die Startpunkte in die Fläche zu legen und von dort aus zu starten?
Ich meine mit der TinyGPS++ ist es möglich, die Strecke zwischen zwei Wegpunkten zu berechnen.
Ich habe meinen Mower leider noch nicht fertig und werde auch Azuritber benutzen, dort wird ja RFID benutzt. Vielleicht kannst du dort ja mal schauen, wie das umgesetzt wurde. Sollte vom Prinzip her ja gleich sein.
Ich habe da nämlich auch Interesse, da ich noch einen Neo6 hier liegen habe.
 
Oben