[Touch CDMA Android Development] Shidell:
Testing this morning, my Vogue hardlocked about ~3 miles into my journey. I reset it and continued, and it seems to stay mostly on track, however the direction the indicator faces is off. I'm constantly skewed about 315 degrees, which held for the duration of the trip.

Also, I never once received the "GPS Signal Lost" voice indication, but about 15 miles into my trip, received the "Searching for GPS..." text prompt, and GPS never recovered.

I'm trying to review the changes Dzo's posted in his latest vs. v1.3 right now.

EDIT:

Dzo has cleaned up the original code (thanks for improving the debug logging). Here's the significant change from the send_position_data method:

Original (v1.3) method:

static int send_position_data (struct gps_state data)
{
static uint32_t last_fix;
static double last_lat, last_lon;
uint32_t time_delta;
GpsLocation location;
char cmd[256];

// Added by Shidell
static double last_bearing;
double deltaLongitude, deltaLatitude, adjLatitude, adjLongitude, position_delta;

/* If the fix time hasn't changed, the kernel was probably just
* alerting us to new signal data */
if (data.time == last_fix)
return 0;

time_delta = data.time - last_fix;
last_fix = data.time;

memset(&location, 0, sizeof(location));
location.flags |= GPS_LOCATION_HAS_LAT_LONG;
location.flags |= GPS_LOCATION_HAS_ACCURACY;
location.latitude = ((double)data.lat) / 180000.0;
location.latitude /= correction_factor;
location.longitude = ((double)data.lng) / 180000.0;
location.longitude /= correction_factor;

/* Compute speed and bearing */
if (last_lat && last_lon) {
deltaLongitude = location.longitude - last_lon;
deltaLatitude = location.latitude - last_lat;
position_delta = sqrt(deltaLongitude * deltaLongitude + deltaLatitude * deltaLatitude);
/* Nautical miles per second */
location.speed = 60 * position_delta / time_delta;
/* Convert to meters per second (assuming near sea level) */
location.speed *= 1852.0;
location.flags |= GPS_LOCATION_HAS_SPEED;

if (location.longitude != last_lon) {

// New code from Shidell (advised by jnadke):
adjLongitude = sin(deltaLongitude) * cos(location.latitude);
adjLatitude = cos(last_lat) * sin(location.latitude) - sin(last_lat) * cos(location.latitude) * cos(deltaLongitude);
location.bearing = atan2(adjLongitude, adjLatitude) * 360 / (6.282);
last_bearing = location.bearing;
// End new code

} else {
// Previous code from srwalter (removed to prevent bearing from resetting to North).
// location.bearing = 0.0;

// If new bearing isn't found, hold last bearing.
location.bearing = last_bearing;
}

// Previous code from srwalter:
/*if ((location.latitude - last_lat) < 0) {
if ((location.longitude - last_lon) < 0) {
location.bearing += 180.0;
} else {
location.bearing += 90.0;
}
} else if ((location.longitude - last_lon) < 0) {
location.bearing += 270.0;
}
if (location.bearing >= 360.0)
location.bearing -= 360.0;*/

// New code from Shidell (advised by jnadke):
if (location.bearing < 0)
location.bearing += 360.0;
// End new code

location.flags |= GPS_LOCATION_HAS_BEARING;
#ifdef DEBUG
snprintf(cmd, 256, "echo speed %10g bearing %10g >> /sdcard/gps",
location.speed, location.bearing);
system(cmd);
#endif
}

last_lat = location.latitude;
last_lon = location.longitude;
location.accuracy = 3.0;
location.timestamp = data.time;

GPS_LOG("echo lock >> /sdcard/gps");
#ifdef DEBUG
snprintf(cmd, 256, "echo coords %10g %10g >> /sdcard/gps", location.latitude,
location.longitude);
system(cmd);
#endif

vogue_callbacks.location_cb(&location);
return 1;
}

Here is Dzo's adjusted method:

static int send_position_data (struct gps_state data)
{
static uint32_t last_fix;
static double last_lat, last_lon;
uint32_t time_delta;
GpsLocation location;
char cmd[256];

// Added by Shidell
static double last_bearing;
double deltaLongitude, deltaLatitude, adjLatitude, adjLongitude, position_delta;

/* If the fix time hasn't changed, the kernel was probably just
* alerting us to new signal data */
if (data.time == last_fix)
return 0;

time_delta = data.time - last_fix;
last_fix = data.time;

memset(&location, 0, sizeof(location));
location.flags |= GPS_LOCATION_HAS_LAT_LONG;
location.flags |= GPS_LOCATION_HAS_ACCURACY | GPS_LOCATION_HAS_ALTITUDE;
location.latitude = ((double)data.lat) / 180000.0;
location.latitude /= correction_factor;
location.longitude = ((double)data.lng) / 180000.0;
location.longitude /= correction_factor;
location.altitude = ((double)data.altitude);

/* Compute speed and bearing */
// convert kilometers/hour into meters/second
location.speed= ((double)data.speed)/4.0;
location.bearing= ((double)data.bearing)/4.0;
// if(location.speed !=0)
location.flags |= GPS_LOCATION_HAS_SPEED | GPS_LOCATION_HAS_BEARING;

location.accuracy = 3.0;
location.timestamp = data.time;

GPS_LOG("lock");
GPS_LOG("coords %10g %10g %10g %f %f", location.latitude,
location.longitude, location.altitude, location.speed, location.bearing);

vogue_callbacks.location_cb(&location);
return 1;
}

Altered Dzo's method some on my own, in an attempt to correct the erroneous bearing heading. Not sure if this will help or cause more problems:

static int send_position_data (struct gps_state data)
{
static uint32_t last_fix;
static double last_lat, last_lon;
uint32_t time_delta;
GpsLocation location;
char cmd[256];

// Added by Shidell
static double last_bearing;
double deltaLongitude, deltaLatitude, adjLatitude, adjLongitude, position_delta;

/* If the fix time hasn't changed, the kernel was probably just
* alerting us to new signal data */
if (data.time == last_fix)
return 0;

time_delta = data.time - last_fix;
last_fix = data.time;

memset(&location, 0, sizeof(location));
location.flags |= GPS_LOCATION_HAS_LAT_LONG;
location.flags |= GPS_LOCATION_HAS_ACCURACY | GPS_LOCATION_HAS_ALTITUDE;
location.latitude = ((double)data.lat) / 180000.0;
location.latitude /= correction_factor;
location.longitude = ((double)data.lng) / 180000.0;
location.longitude /= correction_factor;
location.altitude = ((double)data.altitude);

/* Compute speed and bearing */
// convert kilometers/hour into meters/second
location.speed= ((double)data.speed)/4.0;

// Is this calculation correct? I'm guessing this is the culprit for the skewed directional indicator?
// location.bearing= ((double)data.bearing)/4.0;

if (location.longitude != last_lon)
{
deltaLongitude = location.longitude - last_lon;
deltaLatitude = location.latitude - last_lat;

position_delta = sqrt(deltaLongitude * deltaLongitude + deltaLatitude * deltaLatitude);

adjLongitude = sin(deltaLongitude) * cos(location.latitude);
adjLatitude = cos(last_lat) * sin(location.latitude) - sin(last_lat) * cos(location.latitude) * cos(deltaLongitude);

location.bearing = atan2(adjLongitude, adjLatitude) * 360 / (6.282);

last_bearing = location.bearing;
}
else
{
location.bearing = last_bearing;
}

// if(location.speed !=0)
location.flags |= GPS_LOCATION_HAS_SPEED | GPS_LOCATION_HAS_BEARING;

last_lat = location.latitude;
last_lon = location.longitude;

location.accuracy = 3.0;
location.timestamp = data.time;

GPS_LOG("lock");
GPS_LOG("coords %10g %10g %10g %f %f", location.latitude,
location.longitude, location.altitude, location.speed, location.bearing);

vogue_callbacks.location_cb(&location);
return 1;
}