aboutsummaryrefslogtreecommitdiff
path: root/src/modules/mavlink
diff options
context:
space:
mode:
authorThomas Gubler <thomasgubler@gmail.com>2015-01-05 10:02:07 +0100
committerThomas Gubler <thomasgubler@gmail.com>2015-01-05 10:02:07 +0100
commit16b9f666e790a2b939f7890b39cc6e4cf2552165 (patch)
treeee936b06d15e75e12b175f6786772781aff32cd8 /src/modules/mavlink
parente16c4ff76e7eff2da88bcbef5d05dd4ba11e7203 (diff)
parentc3ed35f5cc8e2617e61747e904dbaa652d1cc2c8 (diff)
downloadpx4-firmware-16b9f666e790a2b939f7890b39cc6e4cf2552165.tar.gz
px4-firmware-16b9f666e790a2b939f7890b39cc6e4cf2552165.tar.bz2
px4-firmware-16b9f666e790a2b939f7890b39cc6e4cf2552165.zip
Merge remote-tracking branch 'upstream/master' into dev_ros
Conflicts: src/lib/mathlib/math/Matrix.hpp src/modules/mc_att_control/mc_att_control_main.cpp src/modules/uORB/topics/vehicle_status.h src/platforms/px4_includes.h
Diffstat (limited to 'src/modules/mavlink')
-rw-r--r--src/modules/mavlink/mavlink_main.cpp2
-rw-r--r--src/modules/mavlink/mavlink_messages.cpp113
-rw-r--r--src/modules/mavlink/mavlink_parameters.cpp41
-rw-r--r--src/modules/mavlink/mavlink_parameters.h5
-rw-r--r--src/modules/mavlink/mavlink_receiver.cpp116
-rw-r--r--src/modules/mavlink/mavlink_receiver.h15
-rw-r--r--src/modules/mavlink/mavlink_tests/module.mk4
7 files changed, 280 insertions, 16 deletions
diff --git a/src/modules/mavlink/mavlink_main.cpp b/src/modules/mavlink/mavlink_main.cpp
index f9a3681b3..dc031404d 100644
--- a/src/modules/mavlink/mavlink_main.cpp
+++ b/src/modules/mavlink/mavlink_main.cpp
@@ -1419,6 +1419,8 @@ Mavlink::task_main(int argc, char *argv[])
configure_stream("DISTANCE_SENSOR", 10.0f);
configure_stream("OPTICAL_FLOW_RAD", 10.0f);
configure_stream("VFR_HUD", 10.0f);
+ configure_stream("SYSTEM_TIME", 1.0f);
+ configure_stream("TIMESYNC", 10.0f);
break;
default:
diff --git a/src/modules/mavlink/mavlink_messages.cpp b/src/modules/mavlink/mavlink_messages.cpp
index 0f25c969d..6765100c7 100644
--- a/src/modules/mavlink/mavlink_messages.cpp
+++ b/src/modules/mavlink/mavlink_messages.cpp
@@ -342,6 +342,8 @@ private:
MavlinkStreamStatustext(MavlinkStreamStatustext &);
MavlinkStreamStatustext& operator = (const MavlinkStreamStatustext &);
FILE *fp = nullptr;
+ unsigned write_err_count = 0;
+ static const unsigned write_err_threshold = 5;
protected:
explicit MavlinkStreamStatustext(Mavlink *mavlink) : MavlinkStream(mavlink)
@@ -370,10 +372,21 @@ protected:
/* write log messages in first instance to disk */
if (_mavlink->get_instance_id() == 0) {
if (fp) {
- fputs(msg.text, fp);
- fputs("\n", fp);
- fsync(fileno(fp));
- } else {
+ if (EOF == fputs(msg.text, fp)) {
+ write_err_count++;
+ } else {
+ write_err_count = 0;
+ }
+
+ if (write_err_count >= write_err_threshold) {
+ (void)fclose(fp);
+ fp = nullptr;
+ } else {
+ (void)fputs("\n", fp);
+ (void)fsync(fileno(fp));
+ }
+
+ } else if (write_err_count < write_err_threshold) {
/* string to hold the path to the log */
char log_file_name[32] = "";
char log_file_path[64] = "";
@@ -389,6 +402,10 @@ protected:
strftime(log_file_name, sizeof(log_file_name), "msgs_%Y_%m_%d_%H_%M_%S.txt", &tt);
snprintf(log_file_path, sizeof(log_file_path), "/fs/microsd/%s", log_file_name);
fp = fopen(log_file_path, "ab");
+
+ /* write first message */
+ fputs(msg.text, fp);
+ fputs("\n", fp);
}
}
}
@@ -923,6 +940,92 @@ protected:
}
};
+class MavlinkStreamSystemTime : public MavlinkStream
+{
+public:
+ const char *get_name() const {
+ return MavlinkStreamSystemTime::get_name_static();
+ }
+
+ static const char *get_name_static() {
+ return "SYSTEM_TIME";
+ }
+
+ uint8_t get_id() {
+ return MAVLINK_MSG_ID_SYSTEM_TIME;
+ }
+
+ static MavlinkStream *new_instance(Mavlink *mavlink) {
+ return new MavlinkStreamSystemTime(mavlink);
+ }
+
+ unsigned get_size() {
+ return MAVLINK_MSG_ID_SYSTEM_TIME_LEN + MAVLINK_NUM_NON_PAYLOAD_BYTES;
+ }
+
+private:
+ /* do not allow top copying this class */
+ MavlinkStreamSystemTime(MavlinkStreamSystemTime &);
+ MavlinkStreamSystemTime &operator = (const MavlinkStreamSystemTime &);
+
+protected:
+ explicit MavlinkStreamSystemTime(Mavlink *mavlink) : MavlinkStream(mavlink)
+ {}
+
+ void send(const hrt_abstime t) {
+ mavlink_system_time_t msg;
+ timespec tv;
+
+ clock_gettime(CLOCK_REALTIME, &tv);
+
+ msg.time_boot_ms = hrt_absolute_time() / 1000;
+ msg.time_unix_usec = (uint64_t)tv.tv_sec * 1000000 + tv.tv_nsec / 1000;
+
+ _mavlink->send_message(MAVLINK_MSG_ID_SYSTEM_TIME, &msg);
+ }
+};
+
+class MavlinkStreamTimesync : public MavlinkStream
+{
+public:
+ const char *get_name() const {
+ return MavlinkStreamTimesync::get_name_static();
+ }
+
+ static const char *get_name_static() {
+ return "TIMESYNC";
+ }
+
+ uint8_t get_id() {
+ return MAVLINK_MSG_ID_TIMESYNC;
+ }
+
+ static MavlinkStream *new_instance(Mavlink *mavlink) {
+ return new MavlinkStreamTimesync(mavlink);
+ }
+
+ unsigned get_size() {
+ return MAVLINK_MSG_ID_TIMESYNC_LEN + MAVLINK_NUM_NON_PAYLOAD_BYTES;
+ }
+
+private:
+ /* do not allow top copying this class */
+ MavlinkStreamTimesync(MavlinkStreamTimesync &);
+ MavlinkStreamTimesync &operator = (const MavlinkStreamTimesync &);
+
+protected:
+ explicit MavlinkStreamTimesync(Mavlink *mavlink) : MavlinkStream(mavlink)
+ {}
+
+ void send(const hrt_abstime t) {
+ mavlink_timesync_t msg;
+
+ msg.tc1 = 0;
+ msg.ts1 = hrt_absolute_time() * 1000; // boot time in nanoseconds
+
+ _mavlink->send_message(MAVLINK_MSG_ID_TIMESYNC, &msg);
+ }
+};
class MavlinkStreamGlobalPositionInt : public MavlinkStream
{
@@ -2197,6 +2300,8 @@ StreamListItem *streams_list[] = {
new StreamListItem(&MavlinkStreamAttitudeQuaternion::new_instance, &MavlinkStreamAttitudeQuaternion::get_name_static),
new StreamListItem(&MavlinkStreamVFRHUD::new_instance, &MavlinkStreamVFRHUD::get_name_static),
new StreamListItem(&MavlinkStreamGPSRawInt::new_instance, &MavlinkStreamGPSRawInt::get_name_static),
+ new StreamListItem(&MavlinkStreamSystemTime::new_instance, &MavlinkStreamSystemTime::get_name_static),
+ new StreamListItem(&MavlinkStreamTimesync::new_instance, &MavlinkStreamTimesync::get_name_static),
new StreamListItem(&MavlinkStreamGlobalPositionInt::new_instance, &MavlinkStreamGlobalPositionInt::get_name_static),
new StreamListItem(&MavlinkStreamLocalPositionNED::new_instance, &MavlinkStreamLocalPositionNED::get_name_static),
new StreamListItem(&MavlinkStreamViconPositionEstimate::new_instance, &MavlinkStreamViconPositionEstimate::get_name_static),
diff --git a/src/modules/mavlink/mavlink_parameters.cpp b/src/modules/mavlink/mavlink_parameters.cpp
index cd5f53d88..e9858b73c 100644
--- a/src/modules/mavlink/mavlink_parameters.cpp
+++ b/src/modules/mavlink/mavlink_parameters.cpp
@@ -44,7 +44,9 @@
#include "mavlink_main.h"
MavlinkParametersManager::MavlinkParametersManager(Mavlink *mavlink) : MavlinkStream(mavlink),
- _send_all_index(-1)
+ _send_all_index(-1),
+ _rc_param_map_pub(-1),
+ _rc_param_map()
{
}
@@ -135,6 +137,43 @@ MavlinkParametersManager::handle_message(const mavlink_message_t *msg)
break;
}
+ case MAVLINK_MSG_ID_PARAM_MAP_RC: {
+ /* map a rc channel to a parameter */
+ mavlink_param_map_rc_t map_rc;
+ mavlink_msg_param_map_rc_decode(msg, &map_rc);
+
+ if (map_rc.target_system == mavlink_system.sysid &&
+ (map_rc.target_component == mavlink_system.compid ||
+ map_rc.target_component == MAV_COMP_ID_ALL)) {
+
+ /* Copy values from msg to uorb using the parameter_rc_channel_index as index */
+ size_t i = map_rc.parameter_rc_channel_index;
+ _rc_param_map.param_index[i] = map_rc.param_index;
+ strncpy(&(_rc_param_map.param_id[i][0]), map_rc.param_id, MAVLINK_MSG_PARAM_VALUE_FIELD_PARAM_ID_LEN);
+ /* enforce null termination */
+ _rc_param_map.param_id[i][MAVLINK_MSG_PARAM_MAP_RC_FIELD_PARAM_ID_LEN] = '\0';
+ _rc_param_map.scale[i] = map_rc.scale;
+ _rc_param_map.value0[i] = map_rc.param_value0;
+ _rc_param_map.value_min[i] = map_rc.param_value_min;
+ _rc_param_map.value_max[i] = map_rc.param_value_max;
+ if (map_rc.param_index == -2) { // -2 means unset map
+ _rc_param_map.valid[i] = false;
+ } else {
+ _rc_param_map.valid[i] = true;
+ }
+ _rc_param_map.timestamp = hrt_absolute_time();
+
+ if (_rc_param_map_pub < 0) {
+ _rc_param_map_pub = orb_advertise(ORB_ID(rc_parameter_map), &_rc_param_map);
+
+ } else {
+ orb_publish(ORB_ID(rc_parameter_map), _rc_param_map_pub, &_rc_param_map);
+ }
+
+ }
+ break;
+ }
+
default:
break;
}
diff --git a/src/modules/mavlink/mavlink_parameters.h b/src/modules/mavlink/mavlink_parameters.h
index 5576e6b84..b6736f212 100644
--- a/src/modules/mavlink/mavlink_parameters.h
+++ b/src/modules/mavlink/mavlink_parameters.h
@@ -44,6 +44,8 @@
#include "mavlink_bridge_header.h"
#include "mavlink_stream.h"
+#include <uORB/uORB.h>
+#include <uORB/topics/rc_parameter_map.h>
class MavlinkParametersManager : public MavlinkStream
{
@@ -112,4 +114,7 @@ protected:
void send(const hrt_abstime t);
void send_param(param_t param);
+
+ orb_advert_t _rc_param_map_pub;
+ struct rc_parameter_map_s _rc_param_map;
};
diff --git a/src/modules/mavlink/mavlink_receiver.cpp b/src/modules/mavlink/mavlink_receiver.cpp
index cb55a25aa..ce3f2ae0e 100644
--- a/src/modules/mavlink/mavlink_receiver.cpp
+++ b/src/modules/mavlink/mavlink_receiver.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
*
- * Copyright (c) 2012-2014 PX4 Development Team. All rights reserved.
+ * Copyright (c) 2012-2015 PX4 Development Team. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -68,6 +68,8 @@
#include <mathlib/mathlib.h>
+#include <conversion/rotation.h>
+
#include <systemlib/param/param.h>
#include <systemlib/systemlib.h>
#include <systemlib/err.h>
@@ -121,7 +123,9 @@ MavlinkReceiver::MavlinkReceiver(Mavlink *parent) :
_old_timestamp(0),
_hil_local_proj_inited(0),
_hil_local_alt0(0.0f),
- _hil_local_proj_ref{}
+ _hil_local_proj_ref{},
+ _time_offset_avg_alpha(0.6),
+ _time_offset(0)
{
// make sure the FTP server is started
@@ -188,6 +192,14 @@ MavlinkReceiver::handle_message(mavlink_message_t *msg)
MavlinkFTP::get_server()->handle_message(_mavlink, msg);
break;
+ case MAVLINK_MSG_ID_SYSTEM_TIME:
+ handle_message_system_time(msg);
+ break;
+
+ case MAVLINK_MSG_ID_TIMESYNC:
+ handle_message_timesync(msg);
+ break;
+
default:
break;
}
@@ -251,7 +263,7 @@ MavlinkReceiver::handle_message_command_long(mavlink_message_t *msg)
//check for MAVLINK terminate command
if (cmd_mavlink.command == MAV_CMD_PREFLIGHT_REBOOT_SHUTDOWN && ((int)cmd_mavlink.param1) == 3) {
/* This is the link shutdown command, terminate mavlink */
- warnx("terminated by remote command");
+ warnx("terminated by remote");
fflush(stdout);
usleep(50000);
@@ -261,7 +273,7 @@ MavlinkReceiver::handle_message_command_long(mavlink_message_t *msg)
} else {
if (msg->sysid == mavlink_system.sysid && msg->compid == mavlink_system.compid) {
- warnx("ignoring CMD spoofed with same SYS/COMP (%d/%d) ID",
+ warnx("ignoring CMD with same SYS/COMP (%d/%d) ID",
mavlink_system.sysid, mavlink_system.compid);
return;
}
@@ -307,7 +319,7 @@ MavlinkReceiver::handle_message_command_int(mavlink_message_t *msg)
//check for MAVLINK terminate command
if (cmd_mavlink.command == MAV_CMD_PREFLIGHT_REBOOT_SHUTDOWN && ((int)cmd_mavlink.param1) == 3) {
/* This is the link shutdown command, terminate mavlink */
- warnx("terminated by remote command");
+ warnx("terminated by remote");
fflush(stdout);
usleep(50000);
@@ -317,7 +329,7 @@ MavlinkReceiver::handle_message_command_int(mavlink_message_t *msg)
} else {
if (msg->sysid == mavlink_system.sysid && msg->compid == mavlink_system.compid) {
- warnx("ignoring CMD spoofed with same SYS/COMP (%d/%d) ID",
+ warnx("ignoring CMD with same SYS/COMP (%d/%d) ID",
mavlink_system.sysid, mavlink_system.compid);
return;
}
@@ -358,6 +370,9 @@ MavlinkReceiver::handle_message_optical_flow_rad(mavlink_message_t *msg)
mavlink_optical_flow_rad_t flow;
mavlink_msg_optical_flow_rad_decode(msg, &flow);
+ enum Rotation flow_rot;
+ param_get(param_find("SENS_FLOW_ROT"),&flow_rot);
+
struct optical_flow_s f;
memset(&f, 0, sizeof(f));
@@ -374,6 +389,10 @@ MavlinkReceiver::handle_message_optical_flow_rad(mavlink_message_t *msg)
f.sensor_id = flow.sensor_id;
f.gyro_temperature = flow.temperature;
+ /* rotate measurements according to parameter */
+ float zeroval = 0.0f;
+ rotate_3f(flow_rot, f.pixel_flow_x_integral, f.pixel_flow_y_integral, zeroval);
+
if (_flow_pub < 0) {
_flow_pub = orb_advertise(ORB_ID(optical_flow), &f);
@@ -689,7 +708,7 @@ MavlinkReceiver::handle_message_vision_position_estimate(mavlink_message_t *msg)
// Use the component ID to identify the vision sensor
vision_position.id = msg->compid;
- vision_position.timestamp_boot = hrt_absolute_time();
+ vision_position.timestamp_boot = to_hrt(pos.usec); // Synced time
vision_position.timestamp_computer = pos.usec;
vision_position.x = pos.x;
vision_position.y = pos.y;
@@ -861,7 +880,7 @@ MavlinkReceiver::handle_message_manual_control(mavlink_message_t *msg)
manual.r = man.r / 1000.0f;
manual.z = man.z / 1000.0f;
- warnx("pitch: %.2f, roll: %.2f, yaw: %.2f, throttle: %.2f", (double)manual.x, (double)manual.y, (double)manual.r, (double)manual.z);
+ // warnx("pitch: %.2f, roll: %.2f, yaw: %.2f, throttle: %.2f", (double)manual.x, (double)manual.y, (double)manual.r, (double)manual.z);
if (_manual_pub < 0) {
_manual_pub = orb_advertise(ORB_ID(manual_control_setpoint), &manual);
@@ -919,6 +938,66 @@ MavlinkReceiver::handle_message_request_data_stream(mavlink_message_t *msg)
}
void
+MavlinkReceiver::handle_message_system_time(mavlink_message_t *msg)
+{
+ mavlink_system_time_t time;
+ mavlink_msg_system_time_decode(msg, &time);
+
+ timespec tv;
+ clock_gettime(CLOCK_REALTIME, &tv);
+
+ // date -d @1234567890: Sat Feb 14 02:31:30 MSK 2009
+ bool onb_unix_valid = tv.tv_sec > PX4_EPOCH_SECS;
+ bool ofb_unix_valid = time.time_unix_usec > PX4_EPOCH_SECS * 1000ULL;
+
+ if (!onb_unix_valid && ofb_unix_valid) {
+ tv.tv_sec = time.time_unix_usec / 1000000ULL;
+ tv.tv_nsec = (time.time_unix_usec % 1000000ULL) * 1000ULL;
+ if(clock_settime(CLOCK_REALTIME, &tv)) {
+ warn("failed setting clock");
+ }
+ else {
+ warnx("[timesync] UTC time synced.");
+ }
+ }
+
+}
+
+void
+MavlinkReceiver::handle_message_timesync(mavlink_message_t *msg)
+{
+ mavlink_timesync_t tsync;
+ mavlink_msg_timesync_decode(msg, &tsync);
+
+ uint64_t now_ns = hrt_absolute_time() * 1000LL ;
+
+ if (tsync.tc1 == 0) {
+
+ mavlink_timesync_t rsync; // return timestamped sync message
+
+ rsync.tc1 = now_ns;
+ rsync.ts1 = tsync.ts1;
+
+ _mavlink->send_message(MAVLINK_MSG_ID_TIMESYNC, &rsync);
+
+ return;
+
+ } else if (tsync.tc1 > 0) {
+
+ int64_t offset_ns = (tsync.ts1 + now_ns - tsync.tc1*2)/2 ;
+ int64_t dt = _time_offset - offset_ns;
+
+ if (dt > 10000000LL || dt < -10000000LL) { // 10 millisecond skew
+ _time_offset = offset_ns;
+ warnx("[timesync] Hard setting offset.");
+ } else {
+ smooth_time_offset(offset_ns);
+ }
+ }
+
+}
+
+void
MavlinkReceiver::handle_message_hil_sensor(mavlink_message_t *msg)
{
mavlink_hil_sensor_t imu;
@@ -1110,7 +1189,7 @@ MavlinkReceiver::handle_message_hil_sensor(mavlink_message_t *msg)
/* print HIL sensors rate */
if ((timestamp - _old_timestamp) > 10000000) {
- printf("receiving HIL sensors at %d hz\n", _hil_frames / 10);
+ // printf("receiving HIL sensors at %d hz\n", _hil_frames / 10);
_old_timestamp = timestamp;
_hil_frames = 0;
}
@@ -1128,7 +1207,7 @@ MavlinkReceiver::handle_message_hil_gps(mavlink_message_t *msg)
memset(&hil_gps, 0, sizeof(hil_gps));
hil_gps.timestamp_time = timestamp;
- hil_gps.time_gps_usec = gps.time_usec;
+ hil_gps.time_utc_usec = gps.time_usec;
hil_gps.timestamp_position = timestamp;
hil_gps.lat = gps.lat;
@@ -1385,6 +1464,23 @@ void MavlinkReceiver::print_status()
}
+uint64_t MavlinkReceiver::to_hrt(uint64_t usec)
+{
+ return usec - (_time_offset / 1000) ;
+}
+
+
+void MavlinkReceiver::smooth_time_offset(uint64_t offset_ns)
+{
+ /* alpha = 0.6 fixed for now. The closer alpha is to 1.0,
+ * the faster the moving average updates in response to
+ * new offset samples.
+ */
+
+ _time_offset = (_time_offset_avg_alpha * offset_ns) + (1.0 - _time_offset_avg_alpha) * _time_offset;
+}
+
+
void *MavlinkReceiver::start_helper(void *context)
{
MavlinkReceiver *rcv = new MavlinkReceiver((Mavlink *)context);
diff --git a/src/modules/mavlink/mavlink_receiver.h b/src/modules/mavlink/mavlink_receiver.h
index a057074a7..4afc9b372 100644
--- a/src/modules/mavlink/mavlink_receiver.h
+++ b/src/modules/mavlink/mavlink_receiver.h
@@ -75,6 +75,8 @@
#include "mavlink_ftp.h"
+#define PX4_EPOCH_SECS 1234567890ULL
+
class Mavlink;
class MavlinkReceiver
@@ -124,12 +126,23 @@ private:
void handle_message_manual_control(mavlink_message_t *msg);
void handle_message_heartbeat(mavlink_message_t *msg);
void handle_message_request_data_stream(mavlink_message_t *msg);
+ void handle_message_system_time(mavlink_message_t *msg);
+ void handle_message_timesync(mavlink_message_t *msg);
void handle_message_hil_sensor(mavlink_message_t *msg);
void handle_message_hil_gps(mavlink_message_t *msg);
void handle_message_hil_state_quaternion(mavlink_message_t *msg);
void *receive_thread(void *arg);
+ /**
+ * Convert remote nsec timestamp to local hrt time (usec)
+ */
+ uint64_t to_hrt(uint64_t nsec);
+ /**
+ * Exponential moving average filter to smooth time offset
+ */
+ void smooth_time_offset(uint64_t offset_ns);
+
mavlink_status_t status;
struct vehicle_local_position_s hil_local_pos;
struct vehicle_control_mode_s _control_mode;
@@ -164,6 +177,8 @@ private:
bool _hil_local_proj_inited;
float _hil_local_alt0;
struct map_projection_reference_s _hil_local_proj_ref;
+ double _time_offset_avg_alpha;
+ uint64_t _time_offset;
/* do not allow copying this class */
MavlinkReceiver(const MavlinkReceiver&);
diff --git a/src/modules/mavlink/mavlink_tests/module.mk b/src/modules/mavlink/mavlink_tests/module.mk
index 1cc28cce1..b46d2bd35 100644
--- a/src/modules/mavlink/mavlink_tests/module.mk
+++ b/src/modules/mavlink/mavlink_tests/module.mk
@@ -47,4 +47,6 @@ MODULE_STACKSIZE = 5000
MAXOPTIMIZATION = -Os
-EXTRACXXFLAGS = -Weffc++ -DMAVLINK_FTP_UNIT_TEST
+EXTRACXXFLAGS = -Weffc++ -DMAVLINK_FTP_UNIT_TEST -Wno-attributes -Wno-packed
+
+EXTRACFLAGS = -Wno-packed