Data for a bike ride

One of my hobbies is cycling. Like many cyclists, I use a GPS recording device to record data about my bike rides. In this lab you will write a Java program that can read a file containing GPS data from a bike ride and compute the distance travelled and the average speed of the ride.

Here is a link to a text file containing GPS data from a bike ride:

GPS ride data

Each row in the text file contains the following data items:

  1. Latitude measured in degrees
  2. Longitude measured in degrees
  3. Elevation measured in meters
  4. Elapsed time measured in seconds

Your job in this lab exercise is to write a Java program that can use this data to compute the following summary values:

  1. Total distance travelled in miles
  2. Average speed in miles per hour
  3. Total elevation gain in feet

What to do

Start by writing a method that can read the data in the text file and return a two dimensional array containing all of the data.

public static double[][] readData(String fileName)

This method should make two passes through the data file. On the first pass through the file you should simply determine the number of rows N in the data file. Once you know how many rows of data are in the file, create a two dimensional array with N rows and 4 columns. On the second pass through the file you will read the data items from the file and put them in the array.

Next, construct a method that computes deltas:

public static double[][] computeDeltas(double[][] data)

For each pair of rows in the original data file we need to compute three delta values:

  1. The planar distance between the two readings.
  2. The change in elevation in meters between the two readings.
  3. The change in time in seconds between the two readings.

If the original data array has N rows, the array that this method returns will have N-1 rows and 3 columns.

To compute the planar distance between two pairs of GPS recordings you should use the following method:

public static double haversine(double lat1, double lon1, double lat2, double lon2) {
  double R = 6372800;
  double dLat = Math.toRadians(lat2 - lat1);
  double dLon = Math.toRadians(lon2 - lon1);
  lat1 = Math.toRadians(lat1);
  lat2 = Math.toRadians(lat2);

  double a = Math.pow(Math.sin(dLat/2),2) + Math.pow(Math.sin(dLon/2),2) * Math.cos(lat1) * Math.cos(lat2);
  double c = 2 * Math.asin(Math.sqrt(a));
  return R * c;
}

Finally, you will write three methods that can compute three important quantities from the array of delta values.

public static double totalDistance(double[][] deltas)
public static double travelTime(double[][] deltas)
public static double elevationGain(double[][] deltas)

The total distance travelled is the sum of distance deltas over the entire ride. To compute a distance delta you will combine the planar distance delta, p, with the elevation delta, h, to compute

The travel time is the sum of the time deltas over the entire ride, leaving out any time deltas where the planar distance travelled is below some threshold you set. Since the time data value in the data file is the elapsed time in seconds, we could compute the time of the ride by just reading the last time value in the data file. The reason that it does not make sense to do this is that at various points in the ride there will be stretches of time where the bicycle is not in motion. These pauses include stops for traffic lights and longer rest stops. (You can see one example of this effect in lines 385 to 431 in the data file.) What we have to do instead is to sum up only those time deltas in the delta array where the distance travelled is greater than some small distance threshhold.

The elevation gain is simply the sum of all of the elevation deltas that are greater than 0.

Using these last three methods, your main method should then compute and print the distance travelled in miles, the average speed in miles per hour (this is just the distance traveled in miles divided by the travel time in hours), and the total elevation gain in feet.