Skip navigation

Node.JS Ar-Drone Cheap GPS Alternative

Node.JS Ar-Drone Cheap USB Alternative.

While developing a new UAV framework based on the AR-Drone, we wanted to focus on a less heavy payload for the GPS module. The current GPS that is available for the AR-Drone is extremely bulky and a bit pricey.

After some exhaustive research and other positive tests from fellow testers(Here), we settled on the “USB GPS – Navistick LE Black”. We followed the instructions in the provided link to “modify” the GPS for use in the parrot.

After a quick test with the AR.Free Flight module and QGroundControl, we were able to get a GPS lock and plot some waypoint missions.

Our next step was to get access to the raw GPS data so we can continue building upon our own drone platform.

We have been using the Node.js AR-Drone platform (Here) for all of our previous tests involving general flight navigation, so we decided to augment that to use our new GPS.

All of the samples we could find, stated that we simply needed to do the following to just get the GPS coordinates.

var arDrone = require('ar-drone');
var client  = arDrone.createClient();
client.on('navdata', console.log);

After several exhaustive hours of research and trying various other “flags” from the Ar-drone SDK, we stumbled upon a post which provided the “Eureka” moment.

On one of the issues page of the GIT code for “node-ar-drone”, we found (source) that someone had found that the latest firmware of the GPS actually changed, but the GPS parser in the node code had not been fixed.

After editing the “ar-drone\lib\navdata\parseNavdata.js” file and commenting everything after “unk_2” past “pressure” and re-running the code. (My new file is below.

	//around line 546.
  'gps': function(reader) {
    return {
      // from https://github.com/paparazzi/paparazzi/blob/55e3d9d79119f81ed0b11a59487280becf13cf40/sw/airborne/boards/ardrone/at_com.h#L157
      latitude:             reader.double64(),
      longitude:            reader.double64(),
      elevation:            reader.double64(),
      hdop:                 reader.double64(),
      data_available:       reader.int32(),
      unk_0:                timesMap(8, reader.uint8, reader),
      lat0:                 reader.double64(),
      lon0:                 reader.double64(),
      lat_fuse:             reader.double64(),
      lon_fuse:             reader.double64(),
      gps_state:            reader.uint32(),
      unk_1:                timesMap(40, reader.uint8, reader),
      vdop:                 reader.double64(),
      pdop:                 reader.double64(),
      speed:                reader.float32(),
      last_frame_timestamp: droneTimeToMilliSeconds(reader.uint32()),
      degree:               reader.float32(),
      degree_mag:           reader.float32(),
      /*unk_2:                timesMap(16, reader.uint8, reader),
      channels:             timesMap(12, reader.satChannel, reader),
      gps_plugged:          reader.int32(),
      unk_3:                timesMap(108, reader.uint8, reader),
      gps_time:             reader.double64(),
      week:                 reader.uint16(),
      gps_fix:              reader.uint8(),
      num_satellites:       reader.uint8(),
      unk_4:                timesMap(24, reader.uint8, reader),
      ned_vel_c0:           reader.double64(),
      ned_vel_c1:           reader.double64(),
      ned_vel_c2:           reader.double64(),
      pos_accur_c0:         reader.double64(),
      pos_accur_c1:         reader.double64(),
      pos_accur_c2:         reader.double64(),
      speed_accur:          reader.float32(),
      time_accur:           reader.float32(),
      unk_5:                timesMap(72, reader.uint8, reader),
      temperature:          reader.float32(),
      pressure:             reader.float32()
	  */
    };
  }
};

As soon as we did that our node code immediately started returning our GPS locked data stream.

Final Test Data:

//ARDRONE node snippet.
var arDrone = require('ar-drone');
var arDroneConstants = require('ar-drone/lib/constants')
var client = arDrone.createClient();
console.log(">> Connected. Waiting for NAV Data <<<");
var handleNavData = function(data){

navCounter++;polPrint('TEST');
if(navCounter==100){
    console.log(data);
    navCounter=0;
}
}

//Setup data:

//Enable the magnetometer data.
function navdata_option_mask(c) {
return 1 << c;
}

var navdataOptions = (
navdata_option_mask(arDroneConstants.options.VISION_DETECT)
| navdata_option_mask(arDroneConstants.options.MAGNETO)
| navdata_option_mask(arDroneConstants.options.WIFI)
| navdata_option_mask(arDroneConstants.options.WIND_SPEED) 
| navdata_option_mask(arDroneConstants.options.ALTITUDE) 
|navdata_option_mask(arDroneConstants.options.ZIMMU_3000)
);
client.config('general:navdata_options', navdataOptions);
client.on('navdata', handleNavData);

Update 8/26/2014: We had lost our GPS coords for a while. We ended up fixing it by getting the entire node ar-drone library again and replacing our own.

Back to the labs so we can start implemented our custom waypoint system!

Update 8/26/2014: Custom Way Point system is almost complete. We have to put our drone on a leesh, as we don't quite trust the new GPS quite yet.