SIM_Helicopter.cpp 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173
  1. /*
  2. This program is free software: you can redistribute it and/or modify
  3. it under the terms of the GNU General Public License as published by
  4. the Free Software Foundation, either version 3 of the License, or
  5. (at your option) any later version.
  6. This program is distributed in the hope that it will be useful,
  7. but WITHOUT ANY WARRANTY; without even the implied warranty of
  8. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  9. GNU General Public License for more details.
  10. You should have received a copy of the GNU General Public License
  11. along with this program. If not, see <http://www.gnu.org/licenses/>.
  12. */
  13. /*
  14. helicopter simulator class
  15. */
  16. #include "SIM_Helicopter.h"
  17. #include <stdio.h>
  18. namespace SITL {
  19. Helicopter::Helicopter(const char *frame_str) :
  20. Aircraft(frame_str)
  21. {
  22. mass = 2.13f;
  23. /*
  24. scaling from motor power to Newtons. Allows the copter
  25. to hover against gravity when the motor is at hover_throttle
  26. */
  27. thrust_scale = (mass * GRAVITY_MSS) / hover_throttle;
  28. // calculate lateral thrust ratio for tail rotor
  29. tail_thrust_scale = sinf(radians(hover_lean)) * thrust_scale / yaw_zero;
  30. frame_height = 0.1;
  31. if (strstr(frame_str, "-dual")) {
  32. frame_type = HELI_FRAME_DUAL;
  33. } else if (strstr(frame_str, "-compound")) {
  34. frame_type = HELI_FRAME_COMPOUND;
  35. } else {
  36. frame_type = HELI_FRAME_CONVENTIONAL;
  37. }
  38. gas_heli = (strstr(frame_str, "-gas") != nullptr);
  39. ground_behavior = GROUND_BEHAVIOR_NO_MOVEMENT;
  40. }
  41. /*
  42. update the helicopter simulation by one time step
  43. */
  44. void Helicopter::update(const struct sitl_input &input)
  45. {
  46. // get wind vector setup
  47. update_wind(input);
  48. float rsc = constrain_float((input.servos[7]-1000) / 1000.0f, 0, 1);
  49. // ignition only for gas helis
  50. bool ignition_enabled = gas_heli?(input.servos[5] > 1500):true;
  51. float thrust = 0;
  52. float roll_rate = 0;
  53. float pitch_rate = 0;
  54. float yaw_rate = 0;
  55. float torque_effect_accel = 0;
  56. float lateral_x_thrust = 0;
  57. float lateral_y_thrust = 0;
  58. float swash1 = (input.servos[0]-1000) / 1000.0f;
  59. float swash2 = (input.servos[1]-1000) / 1000.0f;
  60. float swash3 = (input.servos[2]-1000) / 1000.0f;
  61. if (!ignition_enabled) {
  62. rsc = 0;
  63. }
  64. float rsc_scale = rsc/rsc_setpoint;
  65. switch (frame_type) {
  66. case HELI_FRAME_CONVENTIONAL: {
  67. // simulate a traditional helicopter
  68. float tail_rotor = (input.servos[3]-1000) / 1000.0f;
  69. thrust = (rsc/rsc_setpoint) * (swash1+swash2+swash3) / 3.0f;
  70. torque_effect_accel = (rsc_scale+thrust) * rotor_rot_accel;
  71. roll_rate = swash1 - swash2;
  72. pitch_rate = (swash1+swash2) / 2.0f - swash3;
  73. yaw_rate = tail_rotor - 0.5f;
  74. lateral_y_thrust = yaw_rate * rsc_scale * tail_thrust_scale;
  75. break;
  76. }
  77. case HELI_FRAME_DUAL: {
  78. // simulate a tandem helicopter
  79. float swash4 = (input.servos[3]-1000) / 1000.0f;
  80. float swash5 = (input.servos[4]-1000) / 1000.0f;
  81. float swash6 = (input.servos[5]-1000) / 1000.0f;
  82. thrust = (rsc / rsc_setpoint) * (swash1+swash2+swash3+swash4+swash5+swash6) / 6.0f;
  83. torque_effect_accel = (rsc_scale + rsc / rsc_setpoint) * rotor_rot_accel * ((swash1+swash2+swash3) - (swash4+swash5+swash6));
  84. roll_rate = (swash1-swash2) + (swash4-swash5);
  85. pitch_rate = (swash1+swash2+swash3) - (swash4+swash5+swash6);
  86. yaw_rate = (swash1-swash2) + (swash5-swash4);
  87. break;
  88. }
  89. case HELI_FRAME_COMPOUND: {
  90. // simulate a compound helicopter
  91. float right_rotor = (input.servos[3]-1000) / 1000.0f;
  92. float left_rotor = (input.servos[4]-1000) / 1000.0f;
  93. thrust = (rsc/rsc_setpoint) * (swash1+swash2+swash3) / 3.0f;
  94. torque_effect_accel = (rsc_scale+thrust) * rotor_rot_accel;
  95. roll_rate = swash1 - swash2;
  96. pitch_rate = (swash1+swash2) / 2.0f - swash3;
  97. yaw_rate = right_rotor - left_rotor;
  98. lateral_x_thrust = (left_rotor+right_rotor-1) * rsc_scale * tail_thrust_scale;
  99. break;
  100. }
  101. }
  102. roll_rate *= rsc_scale;
  103. pitch_rate *= rsc_scale;
  104. yaw_rate *= rsc_scale;
  105. // rotational acceleration, in rad/s/s, in body frame
  106. Vector3f rot_accel;
  107. rot_accel.x = roll_rate * roll_rate_max;
  108. rot_accel.y = pitch_rate * pitch_rate_max;
  109. rot_accel.z = yaw_rate * yaw_rate_max;
  110. // rotational air resistance
  111. rot_accel.x -= gyro.x * radians(5000.0) / terminal_rotation_rate;
  112. rot_accel.y -= gyro.y * radians(5000.0) / terminal_rotation_rate;
  113. rot_accel.z -= gyro.z * radians(400.0) / terminal_rotation_rate;
  114. // torque effect on tail
  115. rot_accel.z += torque_effect_accel;
  116. // air resistance
  117. Vector3f air_resistance = -velocity_air_ef * (GRAVITY_MSS/terminal_velocity);
  118. // simulate rotor speed
  119. rpm1 = thrust * 1300;
  120. // scale thrust to newtons
  121. thrust *= thrust_scale;
  122. accel_body = Vector3f(lateral_x_thrust, lateral_y_thrust, -thrust / mass);
  123. accel_body += dcm.transposed() * air_resistance;
  124. update_dynamics(rot_accel);
  125. // update lat/lon/altitude
  126. update_position();
  127. time_advance();
  128. // update magnetic field
  129. update_mag_field_bf();
  130. }
  131. } // namespace SITL