Hey everybody, me and my friend Chester would like to share our implementation of loading a waypoint into the ArduPilot in air. We use XBee radios, NewSoftSerial, and our own GCS written in Java (using Andrew Rapp's xbee-api) to do this. Our GCS was originally designed to facilitate a collision avoidance system for multiple UAVs (this is part of a research project at Auburn University), but we've added a small GUI to allow the user to type in their own waypoint to push to the plane.
In the ArduPilot code, we added a function to poll the XBee for a waypoint packet (we give it a data type of GCS_packet_t) in the 3 1/3 Hz loop. The XBee's TX pin is hooked up to analog4 (one of the few pins we found was not in use) via NewSoftSerial and runs at 57600 baud. If it has a valid packet, it replaces the ArduPilot's next waypoint value with the one from the packet. After it hits this new waypoint, it loads the old next waypoint back in from EEPROM and continues on its original path.
We tested this in our setup with a Multiplex EasyStar, an ATmega328-based ArduPilot running 2.6.2 modified with our code (compiled in Arduino 0018), and an EM406 GPS also at 57600 baud. We are ArduPilot newbies ourselves, but we think everything worked to our expectations.
Our code is available at this github: http://github.com/wjwwood/au-proteus. In the ArduPilot_2_6/ folder, you can find our modified ArduPilot code, along with an extensive guide (XBee_Guide.txt) written by Chester on where the changes are and the rationale behind them. In the xbee-api/ folder, you can find a Readme for the GCS code (XBeeGCS_README.txt).
While we'll be leaving our research program in a few days and not be able to work directly with the planes at Auburn anymore, we'd be glad to hear your comments on this work. Cheers!
Comments
Operation is simple. Setup the Google Earth globe on a good view. In the GCS: Click the Capture point button, (it will stay selected) and click somewhere on the google earth globe. This will 'capture' a point. Give an altitude value in the GCS, Then hit 'Send Waypoint' to send it up to Ardupilot.
It's very rough, and UNTESTED. I did my best as a hacker to implement the comm protocol into the LV GCS, but i'm no certified programmer. I don't have an Ardupilot to test it with.
Please respond with successful tests or bugs found.
Minor: The point I was making about the call sign in the config was that a single xbee might be swapped between 3 different models. In which case I would like the logs to show which plane is communicating with the gcs and not which xbee. I think it useful that a plane can be registered in a gcs database so that the capabailities are known (quad copterm, copter, plane, config etc), in this case an equipment ID instead of an xbee 64 bit would be more useful. Thanks again
Haha, okay, you are correct on both counts in your 2nd to last post. All packets are sent in big endian format, and we do perform that x10 multiply for lat/lon and x100 for altitude in the transmit() method of XBeeGCS.java.
Yes please. Since this is a binary protocol it will be harder to program into the LV GCS and i will need a tester.
@Varun, your code still works using the old GCS protocol ( 0 I believe) and supports the ability to upload, correct? It would be ASCII down to the ground and binary back up, effectively.
I found it in his Xbee_guide.txt. It's a binary transfer (yuck) of a custom struct consisting of the standard Location struct plus a 4 byte checksum.
The checksum seems to be calculated by adding the the lat and alt numbers. Is this correct Varun?
Also, i guess you send the Lat/Lon in the same format the Ardupilot stores them in memory, which is decimal degrees without the decimal, and times 10 for lat/lon, and times 100 for alt.
@TimL:
Heh, perhaps this was a problem with the commit. We actually create a new GCS, which is in GCS_XBee.pde and has a GCS_PROTOCOL of 6. The reason we do this is mainly because we use Serial.write() instead of Serial.println(). By writing the numbers instead of printing them as ASCII, we can fit a lot more numbers in a single packet (although the XBees support fragmenting a large data stream into single packets, we didn't want it to), and it's potentially easier to parse (just reading 4 bytes at flipping the endianness).
On the second point, yes, everything we added can be removed from compilation by removing the #define XBEE_READ and changing the GCS_PROTOCOL from 6 (thank you for pointing this out actually, we didn't surround some of our code with that #define, so I just fixed that and updated the repository now :) ). The guide shows exactly where all of the code was changed.
Currently our GCS logs show which plane sent the data (although we only tested with 1 plane) by mapping the 64-bit XBee addresses to a number (this number is based off the first plane to transmit valid data to the GCS, first come first serve). We figured this works pretty well since the XBee 64-bit addresses are unique and permanent, but I can see attaching unique call signs being useful if you want the same plane to be #1 every time.
Yup, it's a 16 byte packet composed of 4 4 byte integers. The checksum is the sum of the waypoint's latitude and altitude. The packets are big endian.
@Bill I hope this tidbit at the end and TimL's post answered your question, otherwise could you explain what kind of log that you want?
I'm just finishing the kml work. I am also keen to get the two way resolved because I want the gcs to provide lots of controls such as switching modes, setting waypoints and a joystick based fly by wire alternative. So if anyone has the xbee stuff integrated properly I would appreciate a taster.
were all working on similar processes done different ways.
Itching to test your Tim when you get time.
Bill...we have a working system ready to test with if you care to share!?
Mike.