dRonin  adbada4
dRonin firmware
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
camerastab.c
Go to the documentation of this file.
1 
17 /*
18  * This program is free software; you can redistribute it and/or modify
19  * it under the terms of the GNU General Public License as published by
20  * the Free Software Foundation; either version 3 of the License, or
21  * (at your option) any later version.
22  *
23  * This program is distributed in the hope that it will be useful, but
24  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
25  * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
26  * for more details.
27  *
28  * You should have received a copy of the GNU General Public License along
29  * with this program; if not, see <http://www.gnu.org/licenses/>
30  */
31 
44 #include "openpilot.h"
45 #include <eventdispatcher.h>
46 #include "misc_math.h"
47 #include "physical_constants.h"
48 #include "pios_thread.h"
49 #include "pios_can.h"
50 
51 #include "attitudeactual.h"
52 #include "camerastabsettings.h"
53 #include "cameradesired.h"
54 #include "homelocation.h"
55 #include "manualcontrolcommand.h"
56 #include "modulesettings.h"
57 #include "misc_math.h"
58 #include "poilocation.h"
59 #include "positionactual.h"
60 #include "tabletinfo.h"
61 
62 //
63 // Configuration
64 //
65 #define SAMPLE_PERIOD_MS 10
66 #define LOAD_DELAY 7000
67 
68 // Private types
70 
71 // Private variables
72 static struct CameraStab_data {
73  uint32_t lastSysTime;
74  uint8_t AttitudeFilter;
76  float inputs[CAMERASTABSETTINGS_INPUT_NUMELEM];
80  CameraStabSettingsData settings;
81 } *csd;
82 
83 // Private functions
84 static void attitudeUpdated(const UAVObjEvent *ev,
85  void *ctx, void *obj, int len);
86 static void settings_updated_cb(const UAVObjEvent *ev,
87  void *ctx, void *obj, int len);
88 static void applyFF(uint8_t index, float dT_ms, float *attitude, CameraStabSettingsData* cameraStab);
89 static void gimbal_can_message();
90 
91 #if defined(CAMERASTAB_POI_MODE)
92 static void tablet_info_flag_update(const UAVObjEvent *ev,
93  void *ctx, void *obj, int len);
94 static void tablet_info_process();
95 static bool tablet_info_updated = false;
96 #endif /* CAMERASTAB_POI_MODE */
97 
98 // Private variables
99 
104 int32_t CameraStabInitialize(void)
105 {
106  bool module_enabled = false;
107 
108 #ifdef MODULE_CameraStab_BUILTIN
109  module_enabled = true;
110 #else
111  uint8_t module_state[MODULESETTINGS_ADMINSTATE_NUMELEM];
112  ModuleSettingsAdminStateGet(module_state);
113  if (module_state[MODULESETTINGS_ADMINSTATE_CAMERASTAB] == MODULESETTINGS_ADMINSTATE_ENABLED) {
114  module_enabled = true;
115  } else {
116  module_enabled = false;
117  }
118 #endif
119 
120  if (CameraStabSettingsInitialize() == -1) {
121  module_enabled = false;
122  return -1;
123  }
124 
125  if (module_enabled) {
126 
127  // allocate and initialize the static data storage only if module is enabled
128  csd = (struct CameraStab_data *) PIOS_malloc(sizeof(struct CameraStab_data));
129  if (csd == NULL) {
130  module_enabled = false;
131  return -1;
132  }
133 
134  // make sure that all inputs[] are zeroed
135  memset(csd, 0, sizeof(struct CameraStab_data));
137 
138  if (AttitudeActualInitialize() == -1 || CameraDesiredInitialize() == -1) {
139  module_enabled = false;
140  return -1;
141  }
142 
143  CameraStabSettingsConnectCallback(settings_updated_cb);
144  settings_updated_cb(NULL, NULL, NULL, 0);
145 #if defined(CAMERASTAB_POI_MODE)
146  if (PoiLocationInitialize() == -1 || TabletInfoInitialize() == -1) {
147  module_enabled = false;
148  return -1;
149  }
150  TabletInfoConnectCallback(tablet_info_flag_update);
151 #endif /* CAMERASTAB_POI_MODE */
152 
153  return 0;
154  }
155 
156  return -1;
157 }
158 
159 /* stub: module has no module thread */
160 int32_t CameraStabStart(void)
161 {
162  if (csd == NULL) {
163  return -1;
164  }
165 
166  // Schedule periodic task to process attitude
167  UAVObjEvent ev = {
168  .obj = AttitudeActualHandle(),
169  .instId = 0,
170  .event = 0,
171  };
173 
174  return 0;
175 }
176 
178 
179 
183 static void attitudeUpdated(const UAVObjEvent *ev,
184  void *ctx, void *obj, int len)
185 {
186  (void) ev; (void) ctx; (void) obj; (void) len;
187  if (ev->obj != AttitudeActualHandle())
188  return;
189 
190  float accessories[MANUALCONTROLCOMMAND_ACCESSORY_NUMELEM];
191 
192  ManualControlCommandAccessoryGet(accessories);
193 
194  CameraStabSettingsData *settings = &csd->settings;
195 
196  // Check how long since last update, time delta between calls in ms
197  uint32_t thisSysTime = PIOS_Thread_Systime();
198  float dT_ms = thisSysTime - csd->lastSysTime;
199  csd->lastSysTime = thisSysTime;
200 
201  if (dT_ms <= 0)
202  return;
203 
204  float attitude;
205  float output;
206 
207  for (uint8_t i = 0; i < MAX_AXES; i++) {
208 
209  // Get the current attitude from the selected axis
210  switch (i) {
211  case ROLL:
212  AttitudeActualRollGet(&attitude);
213  break;
214  case PITCH:
215  AttitudeActualPitchGet(&attitude);
216  break;
217  case YAW:
218  AttitudeActualYawGet(&attitude);
219  break;
220  }
221  float rt_ms = (float)settings->AttitudeFilter;
222  csd->attitude_filtered[i] = (rt_ms / (rt_ms + dT_ms)) * csd->attitude_filtered[i] + (dT_ms / (rt_ms + dT_ms)) * attitude;
223  attitude = csd->attitude_filtered[i];
224 
225  // Compute new smoothed setpoint
226  if (settings->Input[i] != CAMERASTABSETTINGS_INPUT_NONE && settings->Input[i] != CAMERASTABSETTINGS_INPUT_POI) {
227  int idx = settings->Input[i] - CAMERASTABSETTINGS_INPUT_ACCESSORY0;
228 
229  if ((idx >= 0) && (idx < MANUALCONTROLCOMMAND_ACCESSORY_NUMELEM)) {
230  float input;
231  float input_rate;
232  rt_ms = (float) settings->InputFilter;
233  switch (settings->StabilizationMode[i]) {
234  case CAMERASTABSETTINGS_STABILIZATIONMODE_ATTITUDE:
235  input = accessories[idx] * settings->InputRange[i];
236  csd->inputs[i] = (rt_ms / (rt_ms + dT_ms)) * csd->inputs[i] + (dT_ms / (rt_ms + dT_ms)) * input;
237  break;
238  case CAMERASTABSETTINGS_STABILIZATIONMODE_AXISLOCK:
239  input_rate = accessories[idx] * settings->InputRate[i];
240  if (fabsf(input_rate) > settings->MaxAxisLockRate)
241  csd->inputs[i] = bound_sym(csd->inputs[i] + input_rate * dT_ms / 1000.0f, settings->InputRange[i]);
242  break;
243  default:
244  input = 0;
245  }
246  }
247  switch(i) {
248  case PITCH:
249  CameraDesiredDeclinationSet(&csd->inputs[i]);
250  break;
251  case YAW:
252  CameraDesiredBearingSet(&csd->inputs[i]);
253  break;
254  default:
255  break;
256  }
257  }
258 #if defined(CAMERASTAB_POI_MODE)
259  else if (settings->Input[i] == CAMERASTABSETTINGS_INPUT_POI) {
260  // Process any updates of the tablet location if it wants to
261  // be the POI
262  tablet_info_process();
263 
264  PositionActualData positionActual;
265  PositionActualGet(&positionActual);
266  PoiLocationData poi;
267  PoiLocationGet(&poi);
268 
269  float dLoc[3];
270 
271  dLoc[0] = poi.North - positionActual.North;
272  dLoc[1] = poi.East - positionActual.East;
273  dLoc[2] = poi.Down - positionActual.Down;
274 
275  // Compute the pitch and yaw to the POI location, assuming UAVO is level facing north
276  float distance = sqrtf(powf(dLoc[0], 2) + powf(dLoc[1], 2));
277  float pitch = atan2f(-dLoc[2], distance) * RAD2DEG;
278  float yaw = atan2f(dLoc[1], dLoc[0]) * RAD2DEG;
279  if (yaw < 0.0f)
280  yaw += 360.0f;
281 
282  // Only try and track objects more than 2 m away
283  if (distance > 2) {
284  switch (i) {
285  case CAMERASTABSETTINGS_INPUT_ROLL:
286  // Does not make sense to use position to control yaw
287  break;
288  case CAMERASTABSETTINGS_INPUT_PITCH:
289  // Store the absolute declination relative to UAV
290  CameraDesiredDeclinationSet(&pitch);
291  csd->inputs[CAMERASTABSETTINGS_INPUT_PITCH] = -pitch;
292  break;
293  case CAMERASTABSETTINGS_INPUT_YAW:
294  CameraDesiredBearingSet(&yaw);
295  csd->inputs[CAMERASTABSETTINGS_INPUT_YAW] = yaw;
296  break;
297  }
298  }
299  }
300 #endif /* CAMERASTAB_POI_MODE */
301 
302  // Add Servo FeedForward
303  applyFF(i, dT_ms, &attitude, settings);
304 
305  // Set output channels
306  output = bound_sym((attitude + csd->inputs[i]) / settings->OutputRange[i], 1.0f);
307  if (thisSysTime > LOAD_DELAY) {
308  switch (i) {
309  case ROLL:
310  CameraDesiredRollSet(&output);
311  break;
312  case PITCH:
313  CameraDesiredPitchSet(&output);
314  break;
315  case YAW:
316  CameraDesiredYawSet(&output);
317  break;
318  }
319  }
320  }
321 
322  // Send a message over CAN, if include
324 }
325 
333 static void applyFF(uint8_t index, float dT_ms, float *attitude, CameraStabSettingsData* cameraStab)
334 {
335  float accumulator = csd->FFfilterAccumulator[index];
336 
337  accumulator += (*attitude - csd->FFlastAttitude[index]) * cameraStab->FeedForward[index];
338  csd->FFlastAttitude[index] = *attitude;
339  *attitude += accumulator;
340 
341  float filter = (float) cameraStab->FeedForwardTime / dT_ms;
342  if (filter > 1)
343  accumulator -= accumulator / filter;
344  else
345  accumulator = 0;
346 
347  // For non-zero filter times store accumulation
348  csd->FFfilterAccumulator[index] = accumulator;
349  *attitude += accumulator;
350 
351  //acceleration and deceleration limit
352  float delta = *attitude - csd->FFlastFilteredAttitude[index];
353  float maxDelta = cameraStab->MaxAccel * dT_ms / 1000.0f;
354  if(fabsf(delta) > maxDelta) //we are accelerating too hard
355  {
356  *attitude = csd->FFlastFilteredAttitude[index] + (delta > 0 ? maxDelta : - maxDelta);
357  }
358  csd->FFlastFilteredAttitude[index] = *attitude;
359 }
360 
365 static void settings_updated_cb(const UAVObjEvent *ev,
366  void *ctx, void *obj, int len)
367 {
368  (void) ev; (void) ctx; (void) obj; (void) len;
369 
370  CameraStabSettingsGet(&csd->settings);
371 }
372 
373 #if defined(CAMERASTAB_POI_MODE)
374 
378 static void tablet_info_flag_update(const UAVObjEvent *ev,
379  void *ctx, void *obj, int len)
380 {
381  (void) ev; (void) ctx; (void) obj; (void) len;
382 
383  if (ev->obj == NULL || ev->obj != TabletInfoHandle())
384  return;
385 
386  tablet_info_updated = true;
387 }
388 
392 static void tablet_info_process() {
393 
394  // Only process new information
395  if (tablet_info_updated == false)
396  return;
397  tablet_info_updated = false;
398 
399  TabletInfoData tablet;
400  TabletInfoGet(&tablet);
401  if (tablet.Connected == TABLETINFO_CONNECTED_TRUE && tablet.POI == TABLETINFO_POI_TRUE)
402  {
403  HomeLocationData homeLocation;
404  HomeLocationGet(&homeLocation);
405 
406  PoiLocationData poi;
407 
408  float lat, alt;
409  lat = homeLocation.Latitude / 10.0e6f * DEG2RAD;
410  alt = homeLocation.Altitude;
411 
412  float T[3];
413  T[0] = alt+6.378137E6f;
414  T[1] = cosf(lat)*(alt+6.378137E6f);
415  T[2] = -1.0f;
416 
417  float dL[3] = {(tablet.Latitude - homeLocation.Latitude) / 10.0e6f * DEG2RAD,
418  (tablet.Longitude - homeLocation.Longitude) / 10.0e6f * DEG2RAD,
419  (tablet.Altitude)};
420 
421  poi.North = T[0] * dL[0];
422  poi.East = T[1] * dL[1];
423  poi.Down = T[2] * dL[2];
424  PoiLocationSet(&poi);
425  }
426 }
427 
428 #endif /* CAMERASTAB_POI_MODE */
429 
430 
431 #if defined(PIOS_INCLUDE_CAN)
432 extern uintptr_t pios_can_id;
433 #endif /* PIOS_INCLUDE_CAN */
434 
438 static void gimbal_can_message()
439 {
440 #if defined(PIOS_INCLUDE_CAN)
441  AttitudeActualData attitude;
442  AttitudeActualGet(&attitude);
443 
444  CameraDesiredData cameraDesired;
445  CameraDesiredGet(&cameraDesired);
446 
447  struct pios_can_gimbal_message bgc_message = {
448  .fc_roll = attitude.Roll,
449  .fc_pitch = attitude.Pitch,
450  .fc_yaw = attitude.Yaw,
451  .setpoint_roll = 0,
452  .setpoint_pitch = cameraDesired.Declination,
453  .setpoint_yaw = cameraDesired.Bearing
454  };
455 
456  PIOS_CAN_TxData(pios_can_id, PIOS_CAN_GIMBAL, (uint8_t *) &bgc_message);
457 #endif /* PIOS_INCLUDE_CAN */
458 }
459 
460 
uint32_t PIOS_Thread_Systime(void)
Definition: pios_thread.c:212
#define SAMPLE_PERIOD_MS
Definition: camerastab.c:65
static struct CameraStab_data * csd
CameraStabSettingsData settings
Definition: camerastab.c:80
struct _msp_pid_item pitch
Definition: msp_messages.h:97
static void settings_updated_cb(const UAVObjEvent *ev, void *ctx, void *obj, int len)
Definition: camerastab.c:365
float FFfilterAccumulator[MAX_AXES]
Definition: camerastab.c:79
void * PIOS_malloc(size_t size)
Definition: pios_heap.c:125
uint32_t lat
Definition: msp_messages.h:97
bool module_enabled
int32_t CameraStabInitialize(void)
Definition: camerastab.c:104
UAVObjHandle obj
static float T[3]
Scales used in NED transform (local tangent plane approx).
Definition: attitude.c:210
float FFlastFilteredAttitude[MAX_AXES]
Definition: camerastab.c:78
int32_t EventPeriodicCallbackCreate(UAVObjEvent *ev, UAVObjEventCallback cb, uint16_t periodMs)
Definition: systemmod.c:884
uintptr_t pios_can_id
Definition: pios_board.c:61
float attitude_filtered[MAX_AXES]
Definition: camerastab.c:75
float inputs[CAMERASTABSETTINGS_INPUT_NUMELEM]
Definition: camerastab.c:76
static void gimbal_can_message()
Definition: camerastab.c:438
struct _msp_pid_item alt
Definition: msp_messages.h:99
#define MODULE_INITCALL(ifn, sfn)
Definition: pios_initcall.h:67
float FFlastAttitude[MAX_AXES]
Definition: camerastab.c:77
static volatile FlightStatsSettingsData settings
int32_t CameraStabStart(void)
Definition: camerastab.c:160
Event dispatcher, distributes object events as callbacks. Alternative to using tasks and queues...
int32_t PIOS_CAN_TxData(uintptr_t id, enum pios_can_messages, uint8_t *data)
Transmit a data message with a particular message ID.
uint8_t i
Definition: msp_messages.h:97
struct _msp_pid_item yaw
Definition: msp_messages.h:98
static HomeLocationData homeLocation
Definition: attitude.c:147
float bound_sym(float val, float range)
Bound input value within range (plus or minus)
Definition: misc_math.c:50
static void attitudeUpdated(const UAVObjEvent *ev, void *ctx, void *obj, int len)
Definition: camerastab.c:183
tuple f
Definition: px_mkfw.py:81
Message to tell gimbal the desired setpoint and FC state.
Definition: pios_can.h:42
Includes PiOS and core architecture components.
uint8_t AttitudeFilter
Definition: camerastab.c:74
uint32_t lastSysTime
Definition: camerastab.c:73
PiOS CAN interface header.
#define LOAD_DELAY
Definition: camerastab.c:66
static void applyFF(uint8_t index, float dT_ms, float *attitude, CameraStabSettingsData *cameraStab)
Definition: camerastab.c:333
Definition: camerastab.c:69