Raspberry-pi-tank and GPS navigation

    After experimenting with artificial intelligence, the autopilot of my tank decided to take a step back and learn to navigate the good old satellites.

    The picture is staged, hinting that any GPS transport can self-heat under the control of a navigator.

    Raspberry Pi + GPS

    First, a simple USB GPS module was purchased.

    Guided by the article on Adafrukt , I started implementation.

    Despite the fact that the article was written 6 years ago, nothing has changed much in the world of old-school navigation.

    Only some nuances did not match:

    • the piece of iron was discovered as / dev / ttyACM0 instead of / dev / ttyUSB0
    • when installing gpsd I did not find the device myself, it turned out to be necessary to register in / etc / default / gpsd:
    • for python-3 gps the package must be delivered by hand, it does not go with gpsd

    The device itself looks like a regular USB flash drive:

    And then I got stuck for a long time, because my GPS did not see the coordinates.

    The device worked, reported the version, manufacturer and other useful information, but nothing more.

    At first I thought that he was still defective. From previous experiments, I still have an SD card from Raspbian 2017, on which GPS worked.

    Booted from it and - lo and behold - GPS came to life and blinked a light bulb, and showered in the log coordinates.
    I racked my brains for a week, compared all the configs, began to sin on a new buggy Raspbian and was getting ready to rebuild gpsd in the debug, when suddenly at the Raspberry forum in one of the topics on GPS problems (and there are many of them there) I came across advice to take out the device on the street in clear weather and let it find satellites, which can take up to half an hour.

    This idea came to my mind, but apparently the weather was not clear enough, but then everything coincided, and the device came to life. If you dig a little deeper, it turns out that the necessary information about the satellites is cached in the firmware of the device and can not be controlled by Raspbian.

    How can my application get almanac / ephemeris / pseudorange data?

    Sorry, there's no easy way to do these things through GPSD yet. The reason is that there is no consistent way to make GPS receivers report this information.

    Many don't ship it at all. Others (including some but not all devices shipping SiRF binary packets) ship it occasionally in SUBFRAME information, but you have to know exactly how to grovel through the SUBFRAME fields to get it and the documentation of those in IS-GPS-200E (the over -the-air protocol used by GPS satellites) is extremely obscure. Still others report varying subsets of almanac / ephemeris / pseudorange data in reasonably straightforward ways, but in vendor-proprietary sentences that are extremely specific to individual receiver types, poorly documented or undocumented, and often needing to be activated by control sequences that are equally specific and even worse documented.
    The tricky mechanism has worked and it is time to take advantage of it.
    The script for reading data from gpsd in python is very simple:

    import gps
    gs = gps.gps("localhost", "2947")
    gs.stream(gps.WATCH_ENABLE | gps.WATCH_NEWSTYLE)
    for i in range(0,10):
        report = gs.next()
        print (report)

    Google Maps API

    I control the tank from the phone, so I had to study working with Google Maps.
    Google did a good job simplifying the work with maps, so there were no problems.
    Android Studio can create an empty project with a map, from where it is necessary to carefully transfer all the important details to the main project.

    Google requires a key registration to work with the Maps API, it is done for free (for now).

    I expanded the REST interface of the tank so that it would give its coordinates, transfer the coordinates to the map, draw a tank icon and everything looks quite decent.

    Next you need to pave the way.

    A point on the map selects the target and feeds it in the Directions API .

    Directions is a web service that takes the coordinates of two points and in response dumps a bunch of information about the route taken, including addresses, noteworthy names and explanations. But I needed only a sequence of steps. We select the coordinates and draw them on the map.

    Now there is everything necessary for visual control and management.

    GPS Navigation

    Further from the phone to the tank the first point of the route is transmitted.

    The tank has a small problem - at the initial time, it does not know its direction.
    The problem is easily solved by the compass, but anyone can handle the compass ...

    It was possible to get out by the fact that for the first few seconds the tank passes simply ahead, receiving the coordinates of the beginning and end of the path and calculating its direction from them. It is worth noting that the same data can be obtained directly from GPS, there is a track field, which shows the deviation from the angle to the north pole.

    But in any case, for this to fill up afterwards, movement is needed.

    Calculation of direction:

    def azimuth(pos1, pos2):
        lat1 = toRadians(pos1["lat"])
        lon1 = toRadians(pos1["lon"])
        lat2 = toRadians(pos2["lat"])
        lon2 = toRadians(pos2["lon"])
        dlat = lat2 - lat1
        dlon = lon2 - lon1
        x = math.sin(dlon) * math.cos(lat2)
        y = math.cos(lat1) * math.sin(lat2) - math.sin(lat1) * math.cos(lat2) * math.cos(dlon)
        return math.atan2(x, y)

    I note that GPS does not always work accurately, and it may well turn out that the coordinates of the beginning and end of the test path will be with an error making measurements meaningless (even to the extent that when moving forward, the coordinate of the end of the path is behind).

    In this case, the GPS gives the direction through the track quite reliably, therefore this field was used by default, and if it was not there, I had to navigate by the difference in coordinates.

    Having orientated on the terrain, the tank turns approximately where necessary (approximately - because it is difficult to accurately determine the direction without a compass or gyroscope) and moves for several seconds. Then he again receives the coordinates, checks the direction, turns, rides. And so on until the target is within the radius of error.

    In general, the biggest problem is the error in GPS coordinates, because of which the tank loses direction and starts to rush in different directions.

    Everything goes to the fact that without a compass you can’t survive.


    1. Introductory article on setting up a GPS module for the Raspberry Pi
    2. Service for working with GPS on Linux
    3. Useful site with formulas for calculating the distance and direction by the coordinates of two points
    4. GPS tank firmware source code
    5. Google Maps Documentation for Android

    Also popular now: