2013-12-29 07:56:54 -04:00
|
|
|
#include <AP_HAL.h>
|
|
|
|
#include <AP_Common.h>
|
|
|
|
#include <AP_Math.h>
|
|
|
|
#include <AP_Airspeed.h>
|
|
|
|
#include <AP_Compass.h>
|
|
|
|
#include <AP_GPS.h>
|
|
|
|
#include <AP_Compass.h>
|
|
|
|
#include <AP_Baro.h>
|
|
|
|
#include <AP_InertialSensor.h>
|
|
|
|
#include <DataFlash.h>
|
|
|
|
|
|
|
|
#include "LogReader.h"
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <unistd.h>
|
|
|
|
#include <sys/types.h>
|
|
|
|
#include <sys/stat.h>
|
|
|
|
#include <fcntl.h>
|
|
|
|
|
2015-04-27 00:25:16 -03:00
|
|
|
#include "MsgHandler.h"
|
|
|
|
#include "MsgHandler_PARM.h"
|
|
|
|
#include "MsgHandler_GPS.h"
|
|
|
|
#include "MsgHandler_GPS2.h"
|
|
|
|
#include "MsgHandler_MSG.h"
|
|
|
|
#include "MsgHandler_IMU.h"
|
|
|
|
#include "MsgHandler_IMU2.h"
|
|
|
|
#include "MsgHandler_IMU3.h"
|
|
|
|
#include "MsgHandler_SIM.h"
|
|
|
|
#include "MsgHandler_BARO.h"
|
2015-05-14 23:43:36 -03:00
|
|
|
#include "MsgHandler_ARM.h"
|
2015-05-14 23:59:09 -03:00
|
|
|
#include "MsgHandler_Event.h"
|
2015-04-27 00:25:16 -03:00
|
|
|
#include "MsgHandler_AHR2.h"
|
|
|
|
#include "MsgHandler_ATT.h"
|
|
|
|
#include "MsgHandler_MAG.h"
|
2015-05-15 00:19:55 -03:00
|
|
|
#include "MsgHandler_MAG2.h"
|
2015-04-27 00:25:16 -03:00
|
|
|
#include "MsgHandler_NTUN_Copter.h"
|
|
|
|
#include "MsgHandler_ARSP.h"
|
|
|
|
|
2015-04-22 20:24:45 -03:00
|
|
|
#define streq(x, y) (!strcmp(x, y))
|
|
|
|
|
2013-12-29 07:56:54 -04:00
|
|
|
extern const AP_HAL::HAL& hal;
|
|
|
|
|
2015-01-11 18:30:08 -04:00
|
|
|
LogReader::LogReader(AP_AHRS &_ahrs, AP_InertialSensor &_ins, AP_Baro &_baro, Compass &_compass, AP_GPS &_gps, AP_Airspeed &_airspeed, DataFlash_Class &_dataflash) :
|
2015-04-27 00:25:16 -03:00
|
|
|
vehicle(VehicleType::VEHICLE_UNKNOWN),
|
2013-12-29 07:56:54 -04:00
|
|
|
fd(-1),
|
2014-04-21 05:11:20 -03:00
|
|
|
ahrs(_ahrs),
|
2013-12-29 07:56:54 -04:00
|
|
|
ins(_ins),
|
|
|
|
baro(_baro),
|
|
|
|
compass(_compass),
|
2014-02-17 18:11:46 -04:00
|
|
|
gps(_gps),
|
2014-03-01 17:00:13 -04:00
|
|
|
airspeed(_airspeed),
|
2014-12-07 20:25:22 -04:00
|
|
|
dataflash(_dataflash),
|
2014-11-15 21:31:05 -04:00
|
|
|
accel_mask(7),
|
2015-04-20 02:07:13 -03:00
|
|
|
gyro_mask(7),
|
2015-04-27 00:25:16 -03:00
|
|
|
last_timestamp_usec(0),
|
|
|
|
installed_vehicle_specific_parsers(false)
|
2013-12-29 07:56:54 -04:00
|
|
|
{}
|
|
|
|
|
2015-04-22 20:24:45 -03:00
|
|
|
bool LogReader::open_log(const char *logfile)
|
|
|
|
{
|
|
|
|
fd = ::open(logfile, O_RDONLY);
|
|
|
|
if (fd == -1) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2015-04-27 00:25:16 -03:00
|
|
|
struct log_Format deferred_formats[LOGREADER_MAX_FORMATS];
|
|
|
|
|
|
|
|
// some log entries (e.g. "NTUN") are used by the different vehicle
|
|
|
|
// types with wildy varying payloads. We thus can't use the same
|
|
|
|
// parser for just any e.g. NTUN message. We defer the registration
|
|
|
|
// of a parser for these messages until we know what model we're
|
|
|
|
// dealing with.
|
|
|
|
void LogReader::maybe_install_vehicle_specific_parsers() {
|
|
|
|
if (! installed_vehicle_specific_parsers &&
|
|
|
|
vehicle != VehicleType::VEHICLE_UNKNOWN) {
|
|
|
|
switch(vehicle) {
|
|
|
|
case VehicleType::VEHICLE_COPTER:
|
|
|
|
for (uint8_t i = 0; i<LOGREADER_MAX_FORMATS; i++) {
|
|
|
|
if (deferred_formats[i].type != 0) {
|
|
|
|
msgparser[i] = new MsgHandler_NTUN_Copter
|
|
|
|
(deferred_formats[i], dataflash, last_timestamp_usec,
|
|
|
|
inavpos);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case VehicleType::VEHICLE_PLANE:
|
|
|
|
break;
|
|
|
|
case VehicleType::VEHICLE_ROVER:
|
|
|
|
break;
|
|
|
|
case VehicleType::VEHICLE_UNKNOWN:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
installed_vehicle_specific_parsers = true;
|
2015-04-22 20:24:45 -03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-04-27 00:25:16 -03:00
|
|
|
MsgHandler_PARM *parameter_handler;
|
2015-04-22 20:24:45 -03:00
|
|
|
|
2015-05-10 22:16:05 -03:00
|
|
|
bool LogReader::update(char type[5])
|
2013-12-29 07:56:54 -04:00
|
|
|
{
|
|
|
|
uint8_t hdr[3];
|
|
|
|
if (::read(fd, hdr, 3) != 3) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
if (hdr[0] != HEAD_BYTE1 || hdr[1] != HEAD_BYTE2) {
|
2014-01-04 20:39:43 -04:00
|
|
|
printf("bad log header\n");
|
2013-12-29 07:56:54 -04:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (hdr[2] == LOG_FORMAT_MSG) {
|
2015-04-22 20:24:45 -03:00
|
|
|
struct log_Format f;
|
2013-12-29 07:56:54 -04:00
|
|
|
memcpy(&f, hdr, 3);
|
|
|
|
if (::read(fd, &f.type, sizeof(f)-3) != sizeof(f)-3) {
|
|
|
|
return false;
|
|
|
|
}
|
2015-04-22 20:24:45 -03:00
|
|
|
memcpy(&formats[f.type], &f, sizeof(formats[f.type]));
|
2015-05-10 22:16:05 -03:00
|
|
|
strncpy(type, f.name, 4);
|
|
|
|
type[4] = 0;
|
2015-04-22 20:24:45 -03:00
|
|
|
|
2015-04-27 00:25:16 -03:00
|
|
|
char name[5];
|
|
|
|
memset(name, '\0', 5);
|
|
|
|
memcpy(name, f.name, 4);
|
|
|
|
::printf("Defining log format for type (%d) (%s)\n", f.type, name);
|
|
|
|
|
2015-05-14 23:43:36 -03:00
|
|
|
dataflash.WriteBlock(&f, sizeof(f));
|
|
|
|
|
2015-04-27 00:25:16 -03:00
|
|
|
// map from format name to a parser subclass:
|
|
|
|
if (streq(name, "PARM")) {
|
|
|
|
parameter_handler = new MsgHandler_PARM(formats[f.type], dataflash,
|
|
|
|
last_timestamp_usec);
|
|
|
|
msgparser[f.type] = parameter_handler;
|
|
|
|
} else if (streq(name, "GPS")) {
|
|
|
|
msgparser[f.type] = new MsgHandler_GPS(formats[f.type],
|
|
|
|
dataflash,
|
|
|
|
last_timestamp_usec,
|
|
|
|
gps, ground_alt_cm,
|
|
|
|
rel_altitude);
|
|
|
|
} else if (streq(name, "GPS2")) {
|
|
|
|
msgparser[f.type] = new MsgHandler_GPS2(formats[f.type], dataflash,
|
|
|
|
last_timestamp_usec,
|
|
|
|
gps, ground_alt_cm,
|
|
|
|
rel_altitude);
|
|
|
|
} else if (streq(name, "MSG")) {
|
|
|
|
msgparser[f.type] = new MsgHandler_MSG(formats[f.type], dataflash,
|
|
|
|
last_timestamp_usec,
|
|
|
|
vehicle, ahrs);
|
|
|
|
} else if (streq(name, "IMU")) {
|
|
|
|
msgparser[f.type] = new MsgHandler_IMU(formats[f.type], dataflash,
|
|
|
|
last_timestamp_usec,
|
|
|
|
accel_mask, gyro_mask, ins);
|
|
|
|
} else if (streq(name, "IMU2")) {
|
|
|
|
msgparser[f.type] = new MsgHandler_IMU2(formats[f.type], dataflash,
|
|
|
|
last_timestamp_usec,
|
|
|
|
accel_mask, gyro_mask, ins);
|
|
|
|
} else if (streq(name, "IMU3")) {
|
|
|
|
msgparser[f.type] = new MsgHandler_IMU3(formats[f.type], dataflash,
|
|
|
|
last_timestamp_usec,
|
|
|
|
accel_mask, gyro_mask, ins);
|
|
|
|
} else if (streq(name, "SIM")) {
|
|
|
|
msgparser[f.type] = new MsgHandler_SIM(formats[f.type], dataflash,
|
|
|
|
last_timestamp_usec,
|
|
|
|
sim_attitude);
|
|
|
|
} else if (streq(name, "BARO")) {
|
|
|
|
msgparser[f.type] = new MsgHandler_BARO(formats[f.type], dataflash,
|
|
|
|
last_timestamp_usec, baro);
|
2015-05-14 23:43:36 -03:00
|
|
|
} else if (streq(name, "ARM")) {
|
|
|
|
msgparser[f.type] = new MsgHandler_ARM(formats[f.type], dataflash,
|
|
|
|
last_timestamp_usec);
|
2015-05-14 23:59:09 -03:00
|
|
|
} else if (streq(name, "EV")) {
|
|
|
|
msgparser[f.type] = new MsgHandler_Event(formats[f.type], dataflash,
|
|
|
|
last_timestamp_usec);
|
2015-04-27 00:25:16 -03:00
|
|
|
} else if (streq(name, "AHR2")) {
|
|
|
|
msgparser[f.type] = new MsgHandler_AHR2(formats[f.type], dataflash,
|
|
|
|
last_timestamp_usec,
|
|
|
|
ahr2_attitude);
|
|
|
|
} else if (streq(name, "ATT")) {
|
|
|
|
// this parser handles *all* attitude messages - the common one,
|
|
|
|
// and also the rover/copter/plane-specific (old) messages
|
|
|
|
msgparser[f.type] = new MsgHandler_ATT(formats[f.type], dataflash,
|
|
|
|
last_timestamp_usec,
|
2015-05-09 07:46:27 -03:00
|
|
|
attitude);
|
2015-04-27 00:25:16 -03:00
|
|
|
} else if (streq(name, "MAG")) {
|
|
|
|
msgparser[f.type] = new MsgHandler_MAG(formats[f.type], dataflash,
|
2015-05-15 00:19:55 -03:00
|
|
|
last_timestamp_usec, compass);
|
|
|
|
} else if (streq(name, "MAG2")) {
|
|
|
|
msgparser[f.type] = new MsgHandler_MAG2(formats[f.type], dataflash,
|
2015-04-27 00:25:16 -03:00
|
|
|
last_timestamp_usec, compass);
|
|
|
|
} else if (streq(name, "NTUN")) {
|
|
|
|
// the label "NTUN" is used by rover, copter and plane -
|
|
|
|
// and they all look different! creation of a parser is
|
|
|
|
// deferred until we receive a MSG log entry telling us
|
|
|
|
// which vehicle type to use. Sucks.
|
|
|
|
memcpy(&deferred_formats[f.type], &formats[f.type],
|
|
|
|
sizeof(struct log_Format));
|
|
|
|
} else if (streq(name, "ARSP")) { // plane-specific(?!)
|
|
|
|
msgparser[f.type] = new MsgHandler_ARSP(formats[f.type], dataflash,
|
|
|
|
last_timestamp_usec,
|
|
|
|
airspeed);
|
|
|
|
} else {
|
|
|
|
::printf(" No parser for (%s)\n", name);
|
|
|
|
}
|
2015-04-22 20:24:45 -03:00
|
|
|
|
2013-12-29 07:56:54 -04:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2015-04-22 20:24:45 -03:00
|
|
|
const struct log_Format &f = formats[hdr[2]];
|
2015-04-30 10:39:20 -03:00
|
|
|
if (f.length == 0) {
|
|
|
|
// can't just throw these away as the format specifies the
|
|
|
|
// number of bytes in the message
|
|
|
|
::printf("No format defined for type (%d)\n", hdr[2]);
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
|
2015-04-22 20:24:45 -03:00
|
|
|
uint8_t msg[f.length];
|
2015-04-30 10:39:20 -03:00
|
|
|
|
2015-04-22 20:24:45 -03:00
|
|
|
memcpy(msg, hdr, 3);
|
|
|
|
if (::read(fd, &msg[3], f.length-3) != f.length-3) {
|
2013-12-29 07:56:54 -04:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2015-05-10 22:16:05 -03:00
|
|
|
strncpy(type, f.name, 4);
|
|
|
|
type[4] = 0;
|
2015-01-21 01:26:38 -04:00
|
|
|
|
2015-05-09 19:20:32 -03:00
|
|
|
MsgHandler *p = msgparser[f.type];
|
2015-04-27 00:25:16 -03:00
|
|
|
if (p == NULL) {
|
|
|
|
// I guess this wasn't as self-describing as it could have been....
|
|
|
|
// ::printf("No format message received for type %d; ignoring message\n",
|
|
|
|
// type);
|
|
|
|
return true;
|
2015-01-21 01:26:38 -04:00
|
|
|
}
|
|
|
|
|
2015-04-27 00:25:16 -03:00
|
|
|
p->process_message(msg);
|
2013-12-29 07:56:54 -04:00
|
|
|
|
2015-04-27 00:25:16 -03:00
|
|
|
maybe_install_vehicle_specific_parsers();
|
2013-12-29 07:56:54 -04:00
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2015-05-09 19:20:32 -03:00
|
|
|
bool LogReader::wait_type(const char *wtype)
|
2013-12-29 07:56:54 -04:00
|
|
|
{
|
|
|
|
while (true) {
|
2015-05-10 22:16:05 -03:00
|
|
|
char type[5];
|
|
|
|
if (!update(type)) {
|
2013-12-29 07:56:54 -04:00
|
|
|
return false;
|
|
|
|
}
|
2015-05-09 19:20:32 -03:00
|
|
|
if (streq(type,wtype)) {
|
2013-12-29 07:56:54 -04:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
2015-04-22 20:24:45 -03:00
|
|
|
|
2015-04-27 00:25:16 -03:00
|
|
|
|
|
|
|
bool LogReader::set_parameter(const char *name, float value)
|
|
|
|
{
|
|
|
|
if (parameter_handler == NULL) {
|
|
|
|
::printf("No parameter format message found");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return parameter_handler->set_parameter(name, value);
|
|
|
|
}
|