/Silverware/src/stickvector.c

https://github.com/NotFastEnuf/NFE_Silverware · C · 169 lines · 107 code · 44 blank · 18 comment · 21 complexity · 7d1b7de702dd536ca2ff1fa0e7d1e35e MD5 · raw file

  1. #include "defines.h"
  2. #include "util.h"
  3. #include <math.h>
  4. #include <string.h>
  5. extern float GEstG[3];
  6. extern float Q_rsqrt( float number );
  7. extern char aux[];
  8. extern float aux_analog[];
  9. // error vector between stick position and quad orientation
  10. // this is the output of this function
  11. float errorvect[3];
  12. // cache the last result so it does not get calculated everytime
  13. float last_rx[2] = {13.13f , 12.12f};
  14. float stickvector[3] = { 0 , 0 , 1};
  15. void stick_vector( float rx_input[] , float maxangle)
  16. {
  17. // only compute stick rotation if values changed
  18. if ( last_rx[0] == rx_input[0] && last_rx[1] == rx_input[1] )
  19. {
  20. }
  21. else
  22. {
  23. last_rx[0] = rx_input[0];
  24. last_rx[1] = rx_input[1];
  25. // max angle
  26. #if (defined USE_ANALOG_AUX && defined ANALOG_MAX_ANGLE)
  27. float max_angle = aux_analog[ANALOG_MAX_ANGLE] * 90.0f;
  28. #else
  29. #define max_angle LEVEL_MAX_ANGLE
  30. #endif
  31. float pitch, roll;
  32. // rotate down vector to match stick position
  33. pitch = rx_input[1] * max_angle * DEGTORAD + (float) TRIM_PITCH * DEGTORAD;
  34. roll = rx_input[0] * max_angle * DEGTORAD + (float) TRIM_ROLL * DEGTORAD;
  35. stickvector[0] = fastsin( roll );
  36. stickvector[1] = fastsin( pitch );
  37. stickvector[2] = fastcos( roll ) * fastcos( pitch );
  38. float mag2 = (stickvector[0] * stickvector[0] + stickvector[1] * stickvector[1]);
  39. if ( mag2 > 0.001f )
  40. {
  41. mag2 = Q_rsqrt( mag2 / (1 - stickvector[2] * stickvector[2]) );
  42. }
  43. else mag2 = 0.707f;
  44. stickvector[0] *=mag2;
  45. stickvector[1] *=mag2;
  46. #ifdef INVERTED_ENABLE
  47. extern int pwmdir;
  48. if ( pwmdir==REVERSE )
  49. {
  50. stickvector[0] = - stickvector[0];
  51. stickvector[1] = - stickvector[1];
  52. stickvector[2] = - stickvector[2];
  53. }
  54. #endif
  55. }
  56. // find error between stick vector and quad orientation
  57. // vector cross product
  58. errorvect[1]= -((GEstG[1]*stickvector[2]) - (GEstG[2]*stickvector[1]));
  59. errorvect[0]= (GEstG[2]*stickvector[0]) - (GEstG[0]*stickvector[2]);
  60. // some limits just in case
  61. limitf( &errorvect[0] , 1.0);
  62. limitf( &errorvect[1] , 1.0);
  63. // fix to recover if triggered inverted
  64. // the vector cross product results in zero for opposite vectors, so it's bad at 180 error
  65. // without this the quad will not invert if angle difference = 180
  66. #ifdef INVERTED_ENABLE
  67. static int flip_active_once = 0;
  68. static int flipaxis = 0;
  69. static int flipdir = 0;
  70. int flip_active = 0;
  71. #define rollrate 2.0f
  72. #define g_treshold 0.125f
  73. #define roll_bias 0.25f
  74. if ( aux[FN_INVERTED] && (GEstG[2] > g_treshold) )
  75. {
  76. flip_active = 1;
  77. // rotate around axis with larger leaning angle
  78. if ( flipdir )
  79. {
  80. errorvect[flipaxis] = rollrate;
  81. }
  82. else
  83. {
  84. errorvect[flipaxis] = -rollrate;
  85. }
  86. }
  87. else if ( !aux[FN_INVERTED] && (GEstG[2] < -g_treshold) )
  88. {
  89. flip_active = 1;
  90. if ( flipdir )
  91. {
  92. errorvect[flipaxis] = -rollrate;
  93. }
  94. else
  95. {
  96. errorvect[flipaxis] = rollrate;
  97. }
  98. }
  99. else
  100. flip_active_once = 0;
  101. // set common things here to avoid duplication
  102. if ( flip_active )
  103. {
  104. if ( !flip_active_once )
  105. {
  106. // check which axis is further from center, with a bias towards roll
  107. // because a roll flip does not leave the quad facing the wrong way
  108. if( fabsf(GEstG[0])+ roll_bias > fabsf(GEstG[1]) )
  109. {
  110. // flip in roll axis
  111. flipaxis = 0;
  112. }
  113. else
  114. flipaxis = 1;
  115. if ( GEstG[flipaxis] > 0 )
  116. flipdir = 1;
  117. else
  118. flipdir = 0;
  119. flip_active_once = 1;
  120. }
  121. // set the error in other axis to return to zero
  122. errorvect[!flipaxis] = GEstG[!flipaxis];
  123. }
  124. #endif
  125. }