1 Reply Latest reply on Sep 25, 2013 5:47 AM by Graham Bird

    GeoLocation Calculate Direction and Speed and Turn on tracking (Android)

    Graham Bird

      There are two questions I have relating to tracking:

       

      1) The GeoLocation API does not appear to provide details of the direction and speed from the GPS device used.

      I have worked on an algorithm (which I will post further down) which can calculate the direction and speed based on the latitude and longitude provided, but I would like to know if I am missing something obvious as I know from development experience that GPS antennae usually provide things like long, lat, direction, speed, number of satellites and some other details in their basic output stream and I am surprised that this is not available in the GeoLocation API.

       

      2) The other question (turning on tracking) relates to the fact that Android devices need the user to turn on GPS in the device settings for the GeoLocation to work.

      Is there a way to either turn on the GPS through the application or check if GPS is on and if it is not then to direct the user to turn it on? The last thing we want from our users is for them to have to remember to have GPS turned on when they are running the application.

       

       

      Anyway, now for the interesting/useful algorithm bit that I think others may find useful:

        # This step needs to go somewhere to turn on tracking (login callback in my case)

        begin

          GeoLocation.set_notification(url_for(:action => :geolocation_callback), "", 0) # a zero frequency means we are using the system interval - whatever that is

        rescue Exception => e

          RhoLog.error("Settings.login_callback:\t","GeoLocation API Error:: \t #{e.message} \n\t#{e.backtrace.join("\n\t")}")

        end

       

        # This step needs to go somewhere to turn off tracking (logout callback in my case)

        begin

          GeoLocation.turnoff

        rescue

          # Catch any GPS error and discard

        end

       

        # this definition goes elsewhere to handle the callback

        def geolocation_callback

          begin

            #RhoLog.info("DEBUG GPS","params " + @params.inspect)

            if @params['available'].to_i != 0 && @params['known_position'].to_i != 0 && @params['status'] =='ok' then

       

              # Calculate the distance travelled, direction and speed from the last update (requires a previous known location)

              if ::Rho.get_app.last_latitude != nil && new_latitude != ::Rho.get_app.last_latitude then # check if we have moved!

                ::Rho.get_app.last_delta = GeoLocation.haversine_distance(::Rho.get_app.last_latitude, ::Rho.get_app.last_longitude, new_latitude, new_longitude)

                delta_time = new_gps_time - ::Rho.get_app.last_gps_time # seconds

                ::Rho.get_app.last_speed = (::Rho.get_app.last_delta * 60 * 60) / delta_time # miles per hour

       

                # Lats, Longs and Deltas must be in Radians for next bit

                lat1_rad = ::Rho.get_app.last_latitude * Math::PI / 180

                long1_rad = ::Rho.get_app.last_longitude * Math::PI / 180

                lat2_rad = new_latitude * Math::PI / 180

                long2_rad = new_longitude * Math::PI / 180

                d_long = long2_rad - long1_rad

                d_lat = lat2_rad - lat1_rad

       

                # direction between two points... (JavaScript version below)

                #         var y = Math.sin(dLon) * Math.cos(lat2);

                #         var x = Math.cos(lat1)*Math.sin(lat2) -

                #                  Math.sin(lat1)*Math.cos(lat2)*Math.cos(dLon);

                #         var brng = Math.atan2(y, x).toDeg();

                y = Math.sin(d_long) * Math.cos(lat2_rad)

                x = Math.cos(lat1_rad) * Math.sin(lat2_rad) - Math.sin(lat1_rad) * Math.cos(lat2_rad) * Math.cos(d_long)

                ::Rho.get_app.last_direction = Math.atan2(y,x)

              end

             

              # update the last locations

              ::Rho.get_app.last_latitude = new_latitude

              ::Rho.get_app.last_longitude = new_longitude

              ::Rho.get_app.last_gps_time = new_gps_time

       

            end

          rescue Exception => e

            RhoLog.error("Settings.geolocation_callback:\t","#{e.message} \n\t#{e.backtrace.join("\n\t")}")

          end

        end

       

      There are a few attr_accessor items set up in the application.rb file and the steps above mean that you can then get the last known location, direction, speed and time from elsewhere in the application for whatever purpose you need it for.

       

      Kind regards,

      Graham Bird.

        • Re: GeoLocation Calculate Direction and Speed and Turn on tracking (Android)
          Graham Bird

          I have been experimenting with the code above and found an interesting issue.

          Due to the erratic nature of the GPS co-ordinates, I am sometimes getting large values for the speed with a device that is not moving at all (45Mph for example)

          This same error margin in the longitude and latitude would cause similar error margins in the direction value.

           

          As such, it may be worth implementing a delay in the recalculation of values to give a larger timeframe between points. This should increase the accuracy of the speed in particular and should give an overall direction rather than the short (1s) direction currently implemented.

          A rolling average may provide a reasonable way of implementing this since this should remove some of the error margin