SIM_BalanceBot.cpp 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166
  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. Balance Bot simulator class
  15. */
  16. #include "SIM_BalanceBot.h"
  17. #include <stdio.h>
  18. extern const AP_HAL::HAL& hal;
  19. namespace SITL {
  20. BalanceBot::BalanceBot(const char *frame_str) :
  21. Aircraft(frame_str),
  22. skid_turn_rate(140) // degrees/sec
  23. {
  24. dcm.from_euler(0,0,0); // initial yaw, pitch and roll in radians
  25. printf("Balance Bot Simulation Started\n");
  26. }
  27. /*
  28. return yaw rate in degrees/second given steering_angle
  29. */
  30. float BalanceBot::calc_yaw_rate(float steering)
  31. {
  32. return steering * skid_turn_rate;
  33. }
  34. /*
  35. update the Balance Bot simulation by one time step
  36. */
  37. /*
  38. * The balance bot is physically modeled as an inverted pendulum(cuboid) on wheels
  39. * Further details on the equations used can be found here:
  40. * 1) http://robotics.ee.uwa.edu.au/theses/2003-Balance-Ooi.pdf page 33 onwards
  41. * 2) http://journals.sagepub.com/doi/pdf/10.5772/63933
  42. */
  43. void BalanceBot::update(const struct sitl_input &input)
  44. {
  45. // pendulum/chassis constants
  46. const float m_p = 3.060f; //pendulum mass(kg)
  47. const float width = 0.0650f; //width(m)
  48. const float height = 0.240f; //height(m)
  49. const float l = 0.120f; //height of center of mass from base(m)
  50. const float i_p = (1/12.0f)*m_p*(width*width + height*height); //Moment of inertia about pitch axis(SI units)
  51. // wheel constants
  52. const float r_w = 0.10f; //wheel radius(m)
  53. const float m_w = 0.120f; //wheel mass(kg)
  54. const float i_w = 0.5f*m_w*r_w*r_w; // moment of inertia of wheel(SI units)
  55. // motor constants
  56. const float R = 1.0f; //Winding resistance(ohm)
  57. const float k_e = 0.13f; //back-emf constant(SI units)
  58. const float k_t = 0.242f; //torque constant(SI units)
  59. const float v_max = 12.0f; //max input voltage(V)
  60. // balance bot uses skid steering
  61. const float motor1 = 2*((input.servos[0]-1000)/1000.0f - 0.5f);
  62. const float motor2 = 2*((input.servos[2]-1000)/1000.0f - 0.5f);
  63. const float steering = motor1 - motor2;
  64. const float throttle = 0.5 * (motor1 + motor2);
  65. // motor input voltage: (throttle/max_throttle)*v_max
  66. const float v = throttle*v_max;
  67. // how much time has passed?
  68. const float delta_time = frame_time_us * 1.0e-6f;
  69. // yaw rate in degrees/s
  70. const float yaw_rate = calc_yaw_rate(steering);
  71. // obtain roll, pitch, yaw from dcm
  72. float r, p, y;
  73. dcm.to_euler(&r, &p, &y);
  74. float theta = p; //radians
  75. float ang_vel = gyro.y; //radians/s
  76. // t1,t2,t3 are terms in the equation to find vehicle frame x acceleration
  77. const float t1 = ((2.0f*k_t*v/(R*r_w)) - (2.0f*k_t*k_e*velocity_vf_x/(R*r_w*r_w)) - (m_p*l*ang_vel*ang_vel*sin(theta))) * (i_p + m_p*l*l);
  78. const float t2 = -m_p*l*cos(theta)*((2.0f*k_t*k_e*velocity_vf_x/(R*r_w)) - (2.0f*k_t*v/(R)) + (m_p*GRAVITY_MSS*l*sin(theta)));
  79. const float t3 = ( ((2.0f*m_w + 2.0f*i_w/(r_w*r_w) + m_p) * (i_p + m_p*l*l)) - (m_p*m_p*l*l*cos(theta)*cos(theta)) );
  80. //vehicle frame x acceleration
  81. const float accel_vf_x = (t1-t2)/t3;
  82. const float angular_accel_bf_y = ((2.0f*k_t*k_e*velocity_vf_x/(R*r_w)) - (2.0f*k_t*v/(R)) + m_p*l*accel_vf_x*cos(theta) + m_p*GRAVITY_MSS*l*sin(theta))
  83. / (i_p + m_p*l*l);
  84. // update theta and angular velocity
  85. ang_vel += angular_accel_bf_y * delta_time;
  86. theta += ang_vel * delta_time;
  87. theta = fmod(theta, radians(360));
  88. // update x velocity in vehicle frame
  89. velocity_vf_x += accel_vf_x * delta_time;
  90. gyro = Vector3f(0, ang_vel, radians(yaw_rate));
  91. // update attitude
  92. dcm.rotate(gyro * delta_time);
  93. dcm.normalize();
  94. // accel in body frame due to motor
  95. accel_body = Vector3f(accel_vf_x*cos(theta), 0, -accel_vf_x*sin(theta));
  96. // add in accel due to direction change
  97. accel_body.y += radians(yaw_rate) * velocity_vf_x;
  98. // now in earth frame
  99. Vector3f accel_earth = dcm * accel_body;
  100. accel_earth += Vector3f(0, 0, GRAVITY_MSS);
  101. // we are on the ground, so our vertical accel is zero
  102. accel_earth.z = 0;
  103. if (!hal.util->get_soft_armed()) {
  104. // reset to vertical when not armed for faster testing
  105. accel_earth.zero();
  106. velocity_ef.zero();
  107. dcm.identity();
  108. gyro.zero();
  109. velocity_vf_x =0;
  110. theta = radians(0);
  111. ang_vel = 0;
  112. }
  113. // work out acceleration as seen by the accelerometers. It sees the kinematic
  114. // acceleration (ie. real movement), plus gravity
  115. accel_body += dcm.transposed() * (Vector3f(0, 0, -GRAVITY_MSS));
  116. // new velocity vector
  117. velocity_ef += accel_earth * delta_time;
  118. // new position vector
  119. position += (velocity_ef * delta_time);
  120. // neglect roll
  121. dcm.to_euler(&r, &p, &y);
  122. dcm.from_euler(0.0f, p, y);
  123. use_smoothing = true;
  124. // update lat/lon/altitude
  125. update_position();
  126. time_advance();
  127. // update magnetic field
  128. update_mag_field_bf();
  129. }
  130. }// namespace SITL