Developer
I spent today figuring out how to piece together an interface to the APM_BinComm library for talking back and forth to a ground station. My idea was to wrap a serial class around the Stream interface for the arduino. By doing this there is no need to recode the APM_BinComm library. Just compile against it and go. This should make our lives easier trying to interface with the protocol for ground control software. Hopefully if all goes well I can get this added into the Arducopter svn for APM_BinComm. If not, I'll keep it maintained on my git site: http://hsl.dynalias.com/git/?p=apmcomm;a=summary

Here is a zip of the library:

Here is the main code:

#include "AsyncSerial.hpp"
#include "strlcpy.h"
#include <boost/date_time/posix_time/posix_time.hpp>
#include <iostream>

using namespace boost::posix_time;
ptime start = microsec_clock::universal_time();

class Stream
{
public:
Stream(BufferedAsyncSerial * serial) : _serial(serial)
{
}
uint8_t read() {
_serial->read(&data,1);
//std::cout << "avail: " << available() << std::endl;
return data;
}
void write(char c)
{
_serial->write(&c,1);
}
int available() {
return _serial->available();
}
private:
BufferedAsyncSerial * _serial;
char data;
};


long int millis()
{
time_duration diff = microsec_clock::universal_time() - start;
long int elapsed = diff.total_milliseconds();
return elapsed;
}

And now here is what you can do with it!



What is great about the APM_BinComm library is this is how you add a new message definiton

Add the new message:
#
# System heartbeat
#
message 0x01 MSG_HEARTBEAT
uint8_t flightMode
uint16_t timeStamp
uint16_t batteryVoltage
uint16_t commandIndex

And then process it:
awk -f protogen.awk protocol.def > protocol.h

Thanks go out to Michael Smith for this one.
Nice job!

Here is the code for the above program.

#include "AsyncSerial.hpp"
#include "APM_BinComm/APM_BinComm.h"
#include <iostream>
#include <boost/bind.hpp>

These call back functions make life so much easier.

void h_attitude(void * arg, uint8_t messageId, uint8_t messageVersion, void * messageData)
{
int16_t roll=0,pitch=0,yaw=0;
BinComm * comm = (BinComm*)arg;
comm->unpack_msg_attitude(roll,pitch,yaw);
std::cout << "roll, pitch, yaw:\t" << roll << "\t" << pitch << "\t" << yaw << std::endl;
}

void h_location(void * arg, uint8_t messageId, uint8_t messageVersion, void * messageData)
{
BinComm * comm = (BinComm*)arg;
int32_t latitude = 0, longitude = 0;
int16_t altitude = 0, groundSpeed = 0, groundCourse = 0;
uint16_t timeOfWeek = 0;
comm->unpack_msg_location(latitude,longitude,altitude,groundSpeed,groundCourse,timeOfWeek);
std::cout << "latitude, longitude, altitude:\t" << latitude << "\t"
<< longitude << "\t" << altitude << std::endl;
std::cout << "ground speed, ground course, time of week:\t" << groundSpeed << "\t"
<< groundCourse << "\t" << timeOfWeek << std::endl;
}

class CommTest
{
private:
BufferedAsyncSerial serial;
BinComm::MessageHandler handlerTable[10];
Stream stream;
BinComm comm;

public:
CommTest(const std::string & device, long int baud) :
serial(device,baud),
stream(&serial),
comm(handlerTable,&stream)
{
int i=0;

handlerTable[i].messageID = BinComm::MSG_ATTITUDE;
handlerTable[i].handler = h_attitude;
handlerTable[i].arg = &comm;
i++;

handlerTable[i].messageID = BinComm::MSG_LOCATION;
handlerTable[i].handler = h_location;
handlerTable[i].arg = &comm;
i++;

// signals end of handle table
handlerTable[i].messageID = BinComm::MSG_NULL;
}
void update()
{
comm.update();
}
};

int main (int argc, char const* argv[])
{
if (argc != 3)
{
std::cout << "usage: " << argv[0] << " device baud" << std::endl;
return 0;
}
std::string device = argv[1];
long int baud = atol(argv[2]);
std::cout << "device: " << device << std::endl;
std::cout << "baud: " << baud << std::endl;
CommTest test(device,baud);
while(1)
{
test.update();
usleep(1000);
}
return 0;
}



E-mail me when people leave their comments –

You need to be a member of diydrones to add comments!

Join diydrones

Comments

  • hello everyone! I'm trying to run Mission Planner with Debian. I know this wont beas easy as installing a package, but can someone tell me where to start reading? thank you!!

  • (just to clarify: I'm talking about the fixed-wing APM code not the arducopter code)
  • Ah, OK, didn't know that this part is actually from arducopter. Maybe I check at their tracker then.

    It may be possible that I added the call to send the command-list message myself since I wanted to see in the GCS which part of the mission the UAV is executing (at the time there didn't seem to be another call to send that message but since the message itself is part of the protocol I guess it should be supported). Thanks for working on that packaging part. I'll try it out later today or latest this weekend.
    then.it
    This domain may be for sale!
  • Developer
    There is also a debian package that should work for you that I created using cpack -G DEB.
  • Developer
    Everything under APM_BinComm is part of the arducopter library. So we really need to try to get them to patch it. I've got a patch system running right now in cmake to fix the glaring problems. The latest code is here: http://code.google.com/p/ardupilotmegacomm/ I decided to switch to google code to make things easier with integrating the arducopter APM_BinComm svn. Let me know if you are still having issues with the lat/lon packets. On our ground station we haven't noticed any problems.
  • Not sure but I may have found the problem in protocol.def for the MSG_COMMAND_LIST message type. Added an entry to to tracker..
  • Developer
    I was just struggling with the cmake/ autotools decision. I'll switch back to cmake and see If I can't sort out the bugs you mentioned.
  • Hi again,
    thanks for the quick change. I may have another issue with message type MSG_COMMAND (the command list). As I see it, in GCS_Standard the p3 and p4 field correspond to latitude/longitude coordinates. But in protocol.h they seem to be unsigned, which is different from other GPS waypoints. Even after changing it I have the problem that I receive longitude correctly but not latitude (either 0 or something initialised maybe).

    This is with the old code you uploaded above. The latest code from the repository I haven't managed to compile yet because my autoconf/automake seem to have problems. Do you think it would be possible to add a configure.sh or go back to using cmake as in the first version?

    Sorry for making all these change requests :) Great work with the library..
    CONFIGURE.SH
  • Developer
    The updated apmcomm code, with the global function fix is here: http://oooark.git.sourceforge.net/git/gitweb.cgi?p=oooark/apmcomm;a.... Glad the library is working for you. You can post issues here: http://sourceforge.net/tracker/?group_id=295798
  • Ah yes, Michael was suggesting to file issues if some come up. Where do you keep the issue tracker? (one thing that caused problems when linking were these two global functions implemented in two of the header files.. managed to work around this now)
This reply was deleted.