Converting Fileds and Lines fron AOG to ISOXML

Good morning everyone,

I’ve been using AOG for several years and have more or less mapped all fields and marked them with AB lines. A few weeks ago, I acquired another tractor with GPS, this time equipped by the manufacturer (Fendt). I would like to convert all fields, their boundaries, and the corresponding AB lines into ISO XML. Are there any possibilities to create these?

Alternatively, I could manually drive the boundaries and only enter the AB lines so that at least they are identical. Unfortunately, the information in the ABLiines.txt is not in the format that Fendt requires. They request a format where I specify the exact position of points A and B (format stored in ABLines: Spritze AB,345.94954823,108.144,-402.684).

I thank you in advance for reading this far, and I hope you have tips on how I can make this process a bit easier.

Hi, try this? I was speaking to one of the developers months back, they were looking at reading AOG KML files: https://app.geo-bird.com/

Thank you for your quick response and the reference to GEO Bird.

The program is an interesting alternative for mapping field boundaries from the desktop.

Unfortunately, there was an error message when uploading the KML. I tried this with two different fields several times. It seems that the format in the AOG KML is not correct for GEO Bird.

Yeah, I just tried it - looks like they never got around to adding the format. I was going to look at writing a translator, but that was in March and I got a bit waylaid :slight_smile:

I had also tested another converter recommended to me by the dealer. It was just as successful as Geo Bird.

It would be great if there were a standardized interface, then we could shuttle the data back and forth as we please. No pressure in that regard :wink:

Are you well-versed in this topic? Could you explain to me in which format AOG stores the lines and how I can interpret or even convert them?

They’re KML files, you’ll find them in your (usually) Documents\AgOpenGPS\Fields folder. As for explaining how to convert them, it would take some programming.

If you can find the document spec for ISOXML, that would be helpful tho.

I apologize, I believe we might be talking past each other.

Regarding the part about the KML files, I’m aware of where to find the files, and each folder within the /Fields directory corresponds to a field with its boundaries, lines, etc.

I only know about the basic structure of an ISOXML file, that it needs to be in XML format. For the tractor terminal to locate this file, it should be stored on a USB stick in a folder named TASKDATA. I believe the USB stick should be formatted in FAT32, but I’m not entirely sure. That’s the extent of my knowledge on this topic. Unfortunately, I don’t have an ISOXML file that I can inspect with a text editor to get a rough overview.

Regarding programming, I should mention that I possess a dangerous amount of half-knowledge! :wink: So, nothing in terms of structure or the like.

My last question aimed at understanding the structure in the ABLines.txt file. To be more precise, how do I translate something like (345.94954823,108.144,-402.684) into coordinates like this as an example (Point A = 52° 12’ 43.33" N, 12° 44’ 33" E; Point B = 52° 12’ 43.33" N , 12° 44’ 33" E) or as decimal values.

If you open a field kml file in Google Earth then in the left menu you can right click each line, component etc and save as. Be sure to pick kml and not kmz. This should allow you to load into other programs.

The txt files for the ablines are stored in meters from the start point of the field. You need the reverse conversion formula that are in the code. It is doable, but would take some programming. The kml builder does this automatically.

This may or may not be of help, but here is some Python code I wrote a while back to generate basic ISOXML files. It can generate AB lines and field boundaries only. Whenever a coordinate is used as a python parameter or variable, it’s a tuple in the form (longitude, latitude). Boundary comes from a list of such tuples. I can’t remember if the first and last boundary points should be the same to close it. My Pro 700 didn’t seem to care if I recall.

There are some easy-to-use KML and KMZ libraries for Python, so it should be possible to create a conversion script. And it wouldn’t be horribly difficult to convert this code to C# and integrate it into AOG if someone wanted to take that up.

#!/usr/bin/python3
import os
#import datetime

#today = datetime.datetime.now().strftime('%y%m%d')

class ISOXML(object):
    
    def __init__(self, operator, farm):
        self.operator = operator
        self.farm = farm
        self.fields = {}
        self.counters = { 'ggp': 0,
                          'gpn': 0,
                        }


    def make_ab_line(self, field_name, abline_name, a, b):
        if not field_name in self.fields:
            self.fields[field_name] = []

        #abline_name = "%s_%s" % (abline_name, today)
        #print ("field %s, isoxml abline_name is %s" % (field_name, abline_name))

        field = self.fields[field_name]
        field.append('\t\t <GGP A="GGP-%d" B="%s" >\r\n' % (self.counters['ggp'], abline_name))
        field.append('\t\t\t <GPN A="GPN-%d" B="%s" C="1" E="1" F="1" >\r\n' % (self.counters['gpn'], abline_name))
        field.append('\t\t\t\t <LSG A="5" >\r\n')
        field.append('\t\t\t\t\t <PNT A="6" C="%.9f" D="%.9f" />\r\n' % (a[1], a[0]))
        field.append('\t\t\t\t\t <PNT A="7" C="%.9f" D="%.9f" />\r\n' % (b[1], b[0]))
        field.append('\t\t\t\t </LSG>\r\n')
        field.append('\t\t\t </GPN>\r\n')
        field.append('\t\t </GGP>\r\n')
        self.counters['ggp'] +=1
        self.counters['gpn'] +=1

    def make_boundary(self, field_name, boundary_name, boundary_points):
        if not field_name in self.fields:
            self.fields[field_name] = []

        field = self.fields[field_name]

        #boundary_name = "%s_%s" % (boundary_name, today)

        field.append('\t\t <PLN A="1" B="%s" P094_Subtype="0" P094_Impassable="0" >\r\n' % boundary_name)
        field.append('\t\t\t <LSG A="1" >\r\n')
        
        for bp in boundary_points:
            field.append('\t\t\t\t <PNT A="2" C="%.9f" D="%.9f" />\r\n' % (bp[1], bp[0]))

        field.append('\t\t\t </LSG>\r\n')
        field.append('\t\t </PLN>\r\n')

    def write(self, dirname, which_field=None):
        if not os.path.exists(dirname):
            os.mkdir(dirname)

        taskdata = open (os.path.join(dirname,"TASKDATA.XML"), "w")
        with taskdata:
            taskdata.write('<?xml version="1.0" encoding="UTF-8"?>\r\n')
            taskdata.write('<ISO11783_TaskData VersionMajor="4" VersionMinor="2" ManagementSoftwareManufacturer="" ManagementSoftwareVersion="0" TaskControllerManufacturer="CNH" TaskControllerVersion="31.21.0.0" DataTransferOrigin="2" >\r\n')
            taskdata.write('\t <XFR A="CTR00000" B="1"/>\r\n')
            taskdata.write('\t <XFR A="FRM00000" B="1"/>\r\n')
            taskdata.write('\t <XFR A="PFD00000" B="1"/>\r\n')
            taskdata.write('</ISO11783_TaskData>\r\n')

        ctr = open (os.path.join(dirname, "CTR00000.XML"), "w")
        with ctr:
            ctr.write('<?xml version="1.0" encoding="UTF-8"?>\r\n')
            ctr.write('<XFC >\r\n')
            ctr.write('\t <CTR A="CTR-0" B="%s" />\r\n' % self.operator)
            ctr.write('</XFC>\r\n')

        frm = open (os.path.join(dirname, "FRM00000.XML"), "w")
        with frm:
            frm.write('<?xml version="1.0" encoding="UTF-8"?>\r\n')
            frm.write('<XFC >\r\n')
            frm.write('\t <FRM A="FRM-0" B="%s" I="CTR-0" />\r\n' % self.farm)
            frm.write('</XFC>\r\n')

        pfd_id = 0
        pfd = open (os.path.join(dirname, "PFD00000.XML"), "w")
        with pfd:
            pfd.write('<?xml version="1.0" encoding="UTF-8"?>\r\n')
            pfd.write('<XFC >\r\n')
            for field in self.fields:
                if which_field is not None and not field in which_field:
                    # only output one field
                    continue
                print ("ISOXML Processing field %s" % field)
                pfd.write('\t <PFD A="PFD-%d" C="%s" D="0" E="CTR-0" F="FRM-0" >\r\n' % (pfd_id, field))
                for line in self.fields[field]:
                    pfd.write(line)
                pfd.write('\t </PFD>\r\n')
            pfd.write('</XFC>\r\n')

Wow, my jaw just hit the table :smiley:

I was able to easily upload the Field.kml into Google Earth, and everything, even the recorded area, was displayed. After that, I exported the data from Google Maps as KML and tried importing it into Geo Bird, but unfortunately, without success. I also tested the Next Waylines Converter, but it requires the data to be neatly stored on a USB stick (freshly downloaded from the tractor terminal).

Still, thank you for the tip with Google Maps!

Thank you very much for your script! I have zero knowledge of Python, but I’ll play around with it a bit. Maybe something productive will come out of it.

What could possibly go wrong… he said, formatting everything in the tractor terminal. :wink:

If something comes out of it, I’ll post the code or my approach in this thread.

I neglected to include any code that actually used the code posted… the class has to be instantiated as an object and then the methods to add ab lines and boundaries can be called on it. and then of course write the final result out.

When I wrote it, I only had need of AB lines and boundaries, so that’s all I supported. Perhaps if other kinds of lines and also coverage was exported from the OEM monitor, we might be able to figure out how to create them.

javascript isn’t my forte, but I did find a complete javascript implementation: GitHub - dev4Agriculture/isoxml-js

And found this: ISOBUS Data Dictionary - SupportingDocuments File

Did you try to save just a line or a boundary as kml them import? Right click on a feature save as. The coverage is a loop around the coverage. AOG records as zigzag in the sections.txt.

I don’t need more than that, just a field boundary and an AB line, and I have everything I need. Could you complete your code to be usable for that?

No, I haven’t, but I will test it.

Do you use the online version of Google Earth?

I typically use the desktop version of Google earth for most the conversions.

I had used the online version, I’ll try it with the desktop version.

Not in its present state. But it wouldn’t take me too long to hack something together. I’ll see what I can do.

How many fields? I use QGIS to make shape file and Wayline converter to turn into Fendt file.

It’s just my current work around so all our tractors run the same lines and boundaries with 3 different GPS brands.

I could convert one for you if you want and show how I do it?

1 Like

I have all our fields mapped with AOG (on a quad-bike) and then fields transferred to Fendt and Topcon (AGCO). I only used google earth and the wayline converter from Next Farming. A long time ago and wouldn’t remember any details but I think I struggled with QGIS so would welcome instructions from CommonRail.