dRonin  adbada4
dRonin firmware
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
UAVOMavlinkBridge.c
Go to the documentation of this file.
1 
16 /*
17  * This program is free software; you can redistribute it and/or modify
18  * it under the terms of the GNU General Public License as published by
19  * the Free Software Foundation; either version 3 of the License, or
20  * (at your option) any later version.
21  *
22  * This program is distributed in the hope that it will be useful, but
23  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
24  * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
25  * for more details.
26  *
27  * You should have received a copy of the GNU General Public License along
28  * with this program; if not, see <http://www.gnu.org/licenses/>
29  *
30  * Additional note on redistribution: The copyright and license notices above
31  * must be maintained in each individual source file that is a derivative work
32  * of this source file; otherwise redistribution is prohibited.
33  */
34 
35 // ****************
36 #include "openpilot.h"
37 #include "physical_constants.h"
38 #include "modulesettings.h"
39 #include "flightbatterysettings.h"
40 #include "flightbatterystate.h"
41 #include "gpsposition.h"
42 #include "manualcontrolcommand.h"
43 #include "attitudeactual.h"
44 #include "airspeedactual.h"
45 #include "actuatordesired.h"
46 #include "flightstatus.h"
47 #include "systemstats.h"
48 #include "homelocation.h"
49 #include "baroaltitude.h"
50 #include "mavlink.h"
51 #include "pios_thread.h"
52 #include "pios_modules.h"
53 
54 #include <pios_hal.h>
55 
56 #include "custom_types.h"
57 
58 // ****************
59 // Private functions
60 
61 static void uavoMavlinkBridgeTask(void *parameters);
62 static bool stream_trigger(enum MAV_DATA_STREAM stream_num);
63 
64 // ****************
65 // Private constants
66 
67 #if defined(PIOS_MAVLINK_STACK_SIZE)
68 #define STACK_SIZE_BYTES PIOS_MAVLINK_STACK_SIZE
69 #else
70 #define STACK_SIZE_BYTES 696
71 #endif
72 
73 #define TASK_PRIORITY PIOS_THREAD_PRIO_LOW
74 #define TASK_RATE_HZ 10
75 
76 static const uint8_t mav_rates[] =
77  { [MAV_DATA_STREAM_RAW_SENSORS]=0x02, //2Hz
78  [MAV_DATA_STREAM_EXTENDED_STATUS]=0x02, //2Hz
79  [MAV_DATA_STREAM_RC_CHANNELS]=0x05, //5Hz
80  [MAV_DATA_STREAM_POSITION]=0x02, //2Hz
81  [MAV_DATA_STREAM_EXTRA1]=0x0A, //10Hz
82  [MAV_DATA_STREAM_EXTRA2]=0x02 }; //2Hz
83 
84 #define MAXSTREAMS sizeof(mav_rates)
85 
86 // ****************
87 // Private variables
88 
89 static struct pios_thread *uavoMavlinkBridgeTaskHandle;
90 
91 static uint32_t mavlink_port;
92 
93 static bool module_enabled = false;
94 
95 static uint8_t * stream_ticks;
96 
97 static mavlink_message_t *mav_msg;
98 
99 static void updateSettings();
100 
106 static int32_t uavoMavlinkBridgeStart(void) {
107  if (module_enabled) {
108  // Start tasks
110  uavoMavlinkBridgeTask, "uavoMavlinkBridge", STACK_SIZE_BYTES, NULL, TASK_PRIORITY);
111  TaskMonitorAdd(TASKINFO_RUNNING_UAVOMAVLINKBRIDGE,
113  return 0;
114  }
115  return -1;
116 }
122 static int32_t uavoMavlinkBridgeInitialize(void) {
124 
126  updateSettings();
127 
128  mav_msg = PIOS_malloc(sizeof(*mav_msg));
130 
131  if (mav_msg && stream_ticks) {
132  for (int x = 0; x < MAXSTREAMS; ++x) {
133  stream_ticks[x] = (TASK_RATE_HZ / mav_rates[x]);
134  }
135 
136  module_enabled = true;
137  }else {
138  module_enabled = false;
139  return -1;
140  }
141  }
142 
143  return 0;
144 }
146 
147 static void send_message() {
148  uint16_t msg_length = MAVLINK_NUM_NON_PAYLOAD_BYTES +
149  mav_msg->len;
150 
151  PIOS_COM_SendBuffer(mavlink_port, &mav_msg->magic, msg_length);
152 }
153 
158 static void uavoMavlinkBridgeTask(void *parameters) {
159  uint32_t lastSysTime;
160  // Main task loop
161  lastSysTime = PIOS_Thread_Systime();
162 
163  FlightBatterySettingsData batSettings = {};
164 
165  if (FlightBatterySettingsHandle() != NULL )
166  FlightBatterySettingsGet(&batSettings);
167 
168  SystemStatsData systemStats;
169 
170  while (1) {
171  PIOS_Thread_Sleep_Until(&lastSysTime, 1000 / TASK_RATE_HZ);
172 
173  if (stream_trigger(MAV_DATA_STREAM_EXTENDED_STATUS)) {
174  FlightBatteryStateData batState = {};
175 
176  if (FlightBatteryStateHandle() != NULL )
177  FlightBatteryStateGet(&batState);
178 
179  SystemStatsGet(&systemStats);
180 
181  int8_t battery_remaining = 0;
182  if (batSettings.Capacity != 0) {
183  if (batState.ConsumedEnergy < batSettings.Capacity) {
184  battery_remaining = 100 - lroundf(batState.ConsumedEnergy / batSettings.Capacity * 100);
185  }
186  }
187 
188  uint16_t voltage = 0;
189  if (batSettings.VoltagePin != FLIGHTBATTERYSETTINGS_VOLTAGEPIN_NONE)
190  voltage = lroundf(batState.Voltage * 1000);
191 
192  uint16_t current = 0;
193  if (batSettings.CurrentPin != FLIGHTBATTERYSETTINGS_CURRENTPIN_NONE)
194  current = lroundf(batState.Current * 100);
195 
196  mavlink_msg_sys_status_pack(0, 200, mav_msg,
197  // onboard_control_sensors_present Bitmask showing which onboard controllers and sensors are present. Value of 0: not present. Value of 1: present. Indices: 0: 3D gyro, 1: 3D acc, 2: 3D mag, 3: absolute pressure, 4: differential pressure, 5: GPS, 6: optical flow, 7: computer vision position, 8: laser based position, 9: external ground-truth (Vicon or Leica). Controllers: 10: 3D angular rate control 11: attitude stabilization, 12: yaw position, 13: z/altitude control, 14: x/y position control, 15: motor outputs / control
198  0,
199  // onboard_control_sensors_enabled Bitmask showing which onboard controllers and sensors are enabled: Value of 0: not enabled. Value of 1: enabled. Indices: 0: 3D gyro, 1: 3D acc, 2: 3D mag, 3: absolute pressure, 4: differential pressure, 5: GPS, 6: optical flow, 7: computer vision position, 8: laser based position, 9: external ground-truth (Vicon or Leica). Controllers: 10: 3D angular rate control 11: attitude stabilization, 12: yaw position, 13: z/altitude control, 14: x/y position control, 15: motor outputs / control
200  0,
201  // onboard_control_sensors_health Bitmask showing which onboard controllers and sensors are operational or have an error: Value of 0: not enabled. Value of 1: enabled. Indices: 0: 3D gyro, 1: 3D acc, 2: 3D mag, 3: absolute pressure, 4: differential pressure, 5: GPS, 6: optical flow, 7: computer vision position, 8: laser based position, 9: external ground-truth (Vicon or Leica). Controllers: 10: 3D angular rate control 11: attitude stabilization, 12: yaw position, 13: z/altitude control, 14: x/y position control, 15: motor outputs / control
202  0,
203  // load Maximum usage in percent of the mainloop time, (0%: 0, 100%: 1000) should be always below 1000
204  (uint16_t)systemStats.CPULoad * 10,
205  // voltage_battery Battery voltage, in millivolts (1 = 1 millivolt)
206  voltage,
207  // current_battery Battery current, in 10*milliamperes (1 = 10 milliampere), -1: autopilot does not measure the current
208  current,
209  // battery_remaining Remaining battery energy: (0%: 0, 100%: 100), -1: autopilot estimate the remaining battery
210  battery_remaining,
211  // drop_rate_comm Communication drops in percent, (0%: 0, 100%: 10'000), (UART, I2C, SPI, CAN), dropped packets on all links (packets that were corrupted on reception on the MAV)
212  0,
213  // errors_comm Communication errors (UART, I2C, SPI, CAN), dropped packets on all links (packets that were corrupted on reception on the MAV)
214  0,
215  // errors_count1 Autopilot-specific errors
216  0,
217  // errors_count2 Autopilot-specific errors
218  0,
219  // errors_count3 Autopilot-specific errors
220  0,
221  // errors_count4 Autopilot-specific errors
222  0);
223 
224  send_message();
225  }
226 
227  if (stream_trigger(MAV_DATA_STREAM_RC_CHANNELS)) {
228  ManualControlCommandData manualState;
229  FlightStatusData flightStatus;
230 
231  ManualControlCommandGet(&manualState);
232  FlightStatusGet(&flightStatus);
233  SystemStatsGet(&systemStats);
234 
235  //TODO connect with RSSI object and pass in last argument
236  mavlink_msg_rc_channels_raw_pack(0, 200, mav_msg,
237  // time_boot_ms Timestamp (milliseconds since system boot)
238  systemStats.FlightTime,
239  // port Servo output port (set of 8 outputs = 1 port). Most MAVs will just use one, but this allows to encode more than 8 servos.
240  0,
241  // chan1_raw RC channel 1 value, in microseconds
242  manualState.Channel[0],
243  // chan2_raw RC channel 2 value, in microseconds
244  manualState.Channel[1],
245  // chan3_raw RC channel 3 value, in microseconds
246  manualState.Channel[2],
247  // chan4_raw RC channel 4 value, in microseconds
248  manualState.Channel[3],
249  // chan5_raw RC channel 5 value, in microseconds
250  manualState.Channel[4],
251  // chan6_raw RC channel 6 value, in microseconds
252  manualState.Channel[5],
253  // chan7_raw RC channel 7 value, in microseconds
254  manualState.Channel[6],
255  // chan8_raw RC channel 8 value, in microseconds
256  manualState.Channel[7],
257  // rssi Receive signal strength indicator, 0: 0%, 255: 100%
258  manualState.Rssi);
259 
260  send_message();
261  }
262 
263  if (stream_trigger(MAV_DATA_STREAM_POSITION)) {
264  GPSPositionData gpsPosData = {};
265  HomeLocationData homeLocation = {};
266  SystemStatsGet(&systemStats);
267 
268  if (GPSPositionHandle() != NULL )
269  GPSPositionGet(&gpsPosData);
270  if (HomeLocationHandle() != NULL )
271  HomeLocationGet(&homeLocation);
272  SystemStatsGet(&systemStats);
273 
274  uint8_t gps_fix_type;
275  switch (gpsPosData.Status)
276  {
277  case GPSPOSITION_STATUS_NOGPS:
278  gps_fix_type = 0;
279  break;
280  case GPSPOSITION_STATUS_NOFIX:
281  gps_fix_type = 1;
282  break;
283  case GPSPOSITION_STATUS_FIX2D:
284  gps_fix_type = 2;
285  break;
286  case GPSPOSITION_STATUS_FIX3D:
287  case GPSPOSITION_STATUS_DIFF3D:
288  gps_fix_type = 3;
289  break;
290  default:
291  gps_fix_type = 0;
292  break;
293  }
294 
295  mavlink_msg_gps_raw_int_pack(0, 200, mav_msg,
296  // time_usec Timestamp (microseconds since UNIX epoch or microseconds since system boot)
297  (uint64_t)systemStats.FlightTime * 1000,
298  // fix_type 0-1: no fix, 2: 2D fix, 3: 3D fix. Some applications will not use the value of this field unless it is at least two, so always correctly fill in the fix.
299  gps_fix_type,
300  // lat Latitude in 1E7 degrees
301  gpsPosData.Latitude,
302  // lon Longitude in 1E7 degrees
303  gpsPosData.Longitude,
304  // alt Altitude in 1E3 meters (millimeters) above MSL
305  gpsPosData.Altitude * 1000,
306  // eph GPS HDOP horizontal dilution of position in cm (m*100). If unknown, set to: 65535
307  gpsPosData.HDOP * 100,
308  // epv GPS VDOP horizontal dilution of position in cm (m*100). If unknown, set to: 65535
309  gpsPosData.VDOP * 100,
310  // vel GPS ground speed (m/s * 100). If unknown, set to: 65535
311  gpsPosData.Groundspeed * 100,
312  // cog Course over ground (NOT heading, but direction of movement) in degrees * 100, 0.0..359.99 degrees. If unknown, set to: 65535
313  gpsPosData.Heading * 100,
314  // satellites_visible Number of satellites visible. If unknown, set to 255
315  gpsPosData.Satellites);
316 
317  send_message();
318 
319  mavlink_msg_gps_global_origin_pack(0, 200, mav_msg,
320  // latitude Latitude (WGS84), expressed as * 1E7
321  homeLocation.Latitude,
322  // longitude Longitude (WGS84), expressed as * 1E7
323  homeLocation.Longitude,
324  // altitude Altitude(WGS84), expressed as * 1000
325  homeLocation.Altitude * 1000);
326 
327  send_message();
328 
329  //TODO add waypoint nav stuff
330  //wp_target_bearing
331  //wp_dist = mavlink_msg_nav_controller_output_get_wp_dist(&msg);
332  //alt_error = mavlink_msg_nav_controller_output_get_alt_error(&msg);
333  //aspd_error = mavlink_msg_nav_controller_output_get_aspd_error(&msg);
334  //xtrack_error = mavlink_msg_nav_controller_output_get_xtrack_error(&msg);
335  //mavlink_msg_nav_controller_output_pack
336  //wp_number
337  //mavlink_msg_mission_current_pack
338  }
339 
340  if (stream_trigger(MAV_DATA_STREAM_EXTRA1)) {
341  AttitudeActualData attActual;
342  SystemStatsData systemStats;
343 
344  AttitudeActualGet(&attActual);
345  SystemStatsGet(&systemStats);
346 
347  mavlink_msg_attitude_pack(0, 200, mav_msg,
348  // time_boot_ms Timestamp (milliseconds since system boot)
349  systemStats.FlightTime,
350  // roll Roll angle (rad)
351  attActual.Roll * DEG2RAD,
352  // pitch Pitch angle (rad)
353  attActual.Pitch * DEG2RAD,
354  // yaw Yaw angle (rad)
355  attActual.Yaw * DEG2RAD,
356  // rollspeed Roll angular speed (rad/s)
357  0,
358  // pitchspeed Pitch angular speed (rad/s)
359  0,
360  // yawspeed Yaw angular speed (rad/s)
361  0);
362 
363  send_message();
364  }
365 
366  if (stream_trigger(MAV_DATA_STREAM_EXTRA2)) {
367  ActuatorDesiredData actDesired;
368  AttitudeActualData attActual;
369  AirspeedActualData airspeedActual = {};
370  GPSPositionData gpsPosData = {};
371  BaroAltitudeData baroAltitude = {};
372  FlightStatusData flightStatus;
373 
374  if (AirspeedActualHandle() != NULL )
375  AirspeedActualGet(&airspeedActual);
376  if (GPSPositionHandle() != NULL )
377  GPSPositionGet(&gpsPosData);
378  if (BaroAltitudeHandle() != NULL )
379  BaroAltitudeGet(&baroAltitude);
380  ActuatorDesiredGet(&actDesired);
381  AttitudeActualGet(&attActual);
382  FlightStatusGet(&flightStatus);
383 
384  float altitude = 0;
385  if (BaroAltitudeHandle() != NULL)
386  altitude = baroAltitude.Altitude;
387  else if (GPSPositionHandle() != NULL)
388  altitude = gpsPosData.Altitude;
389 
390  // round attActual.Yaw to nearest int and transfer from (-180 ... 180) to (0 ... 360)
391  int16_t heading = lroundf(attActual.Yaw);
392  if (heading < 0)
393  heading += 360;
394 
395  mavlink_msg_vfr_hud_pack(0, 200, mav_msg,
396  // airspeed Current airspeed in m/s
397  airspeedActual.TrueAirspeed,
398  // groundspeed Current ground speed in m/s
399  gpsPosData.Groundspeed,
400  // heading Current heading in degrees, in compass units (0..360, 0=north)
401  heading,
402  // throttle Current throttle setting in integer percent, 0 to 100
403  actDesired.Thrust * 100,
404  // alt Current altitude (MSL), in meters
405  altitude,
406  // climb Current climb rate in meters/second
407  0);
408 
409  send_message();
410 
411  uint8_t armed_mode = 0;
412  if (flightStatus.Armed == FLIGHTSTATUS_ARMED_ARMED)
413  armed_mode |= MAV_MODE_FLAG_SAFETY_ARMED;
414 
415  uint8_t custom_mode = CUSTOM_MODE_STAB;
416 
417  switch (flightStatus.FlightMode) {
418  case FLIGHTSTATUS_FLIGHTMODE_MANUAL:
419  case FLIGHTSTATUS_FLIGHTMODE_VIRTUALBAR:
420  case FLIGHTSTATUS_FLIGHTMODE_HORIZON:
421  /* Kinda a catch all */
422  custom_mode = CUSTOM_MODE_SPORT;
423  break;
424  case FLIGHTSTATUS_FLIGHTMODE_ACRO:
425  case FLIGHTSTATUS_FLIGHTMODE_AXISLOCK:
426  custom_mode = CUSTOM_MODE_ACRO;
427  break;
428  case FLIGHTSTATUS_FLIGHTMODE_STABILIZED1:
429  case FLIGHTSTATUS_FLIGHTMODE_STABILIZED2:
430  case FLIGHTSTATUS_FLIGHTMODE_STABILIZED3:
431  /* May want these three to try and
432  * infer based on roll axis */
433  case FLIGHTSTATUS_FLIGHTMODE_LEVELING:
434  custom_mode = CUSTOM_MODE_STAB;
435  break;
436  case FLIGHTSTATUS_FLIGHTMODE_AUTOTUNE:
437  custom_mode = CUSTOM_MODE_DRIFT;
438  break;
439  case FLIGHTSTATUS_FLIGHTMODE_ALTITUDEHOLD:
440  custom_mode = CUSTOM_MODE_ALTH;
441  break;
442  case FLIGHTSTATUS_FLIGHTMODE_RETURNTOHOME:
443  custom_mode = CUSTOM_MODE_RTL;
444  break;
445  case FLIGHTSTATUS_FLIGHTMODE_TABLETCONTROL:
446  case FLIGHTSTATUS_FLIGHTMODE_POSITIONHOLD:
447  custom_mode = CUSTOM_MODE_POSH;
448  break;
449  case FLIGHTSTATUS_FLIGHTMODE_FAILSAFE:
450  /* (make it clear we're in charge) */
451  case FLIGHTSTATUS_FLIGHTMODE_PATHPLANNER:
452  custom_mode = CUSTOM_MODE_AUTO;
453  break;
454  }
455 
456  mavlink_msg_heartbeat_pack(0, 200, mav_msg,
457  // type Type of the MAV (quadrotor, helicopter, etc., up to 15 types, defined in MAV_TYPE ENUM)
458  MAV_TYPE_GENERIC,
459  // autopilot Autopilot type / class. defined in MAV_AUTOPILOT ENUM
460  MAV_AUTOPILOT_GENERIC,
461  // base_mode System mode bitfield, see MAV_MODE_FLAGS ENUM in mavlink/include/mavlink_types.h
462  armed_mode,
463  // custom_mode A bitfield for use for autopilot-specific flags.
464  custom_mode,
465  // system_status System status flag, see MAV_STATE ENUM
466  0);
467 
468  send_message();
469  }
470  }
471 }
472 
473 static bool stream_trigger(enum MAV_DATA_STREAM stream_num) {
474  uint8_t rate = (uint8_t) mav_rates[stream_num];
475 
476  if (rate == 0) {
477  return false;
478  }
479 
480  if (stream_ticks[stream_num] == 0) {
481  // we're triggering now, setup the next trigger point
482  if (rate > TASK_RATE_HZ) {
483  rate = TASK_RATE_HZ;
484  }
485  stream_ticks[stream_num] = (TASK_RATE_HZ / rate);
486  return true;
487  }
488 
489  // count down at 50Hz
490  stream_ticks[stream_num]--;
491  return false;
492 }
493 
494 static void updateSettings()
495 {
496 
497  if (mavlink_port) {
498  // Retrieve settings
499  uint8_t speed;
500  ModuleSettingsMavlinkSpeedGet(&speed);
501 
503  }
504 }
uint16_t speed
Definition: msp_messages.h:101
uint32_t PIOS_Thread_Systime(void)
Definition: pios_thread.c:212
bool PIOS_Modules_IsEnabled(enum pios_modules module)
Definition: pios_modules.c:41
int16_t heading
Definition: msp_messages.h:98
void * PIOS_malloc(size_t size)
Definition: pios_heap.c:125
void * PIOS_malloc_no_dma(size_t size)
Definition: pios_heap.c:166
uint16_t altitude
Definition: msp_messages.h:100
void PIOS_HAL_ConfigureSerialSpeed(uintptr_t com_id, HwSharedSpeedBpsOptions speed)
Definition: pios_hal.c:1115
#define MODULE_INITCALL(ifn, sfn)
Definition: pios_initcall.h:67
#define PIOS_COM_MAVLINK
Definition: pios_board.h:117
struct pios_thread * PIOS_Thread_Create(void(*fp)(void *), const char *namep, size_t stack_bytes, void *argp, enum pios_thread_prio_e prio)
Definition: pios_thread.c:89
int32_t TaskMonitorAdd(TaskInfoRunningElem task, struct pios_thread *threadp)
Definition: taskmonitor.c:67
static HomeLocationData homeLocation
Definition: attitude.c:147
uint16_t current
void PIOS_Thread_Sleep_Until(uint32_t *previous_ms, uint32_t increment_ms)
Definition: pios_thread.c:255
PIOS_COM_SendBuffer(shub_global->frsky_port, shub_global->serial_buf, msg_length)
uint8_t rate
Definition: msp_messages.h:99
Includes PiOS and core architecture components.
uint16_t voltage
static uint32_t lastSysTime