SIM_Gripper_EPM.cpp 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123
  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. simple Gripper (OpenGrab EPM) simulation class
  15. */
  16. #include "SIM_Gripper_EPM.h"
  17. #include "AP_HAL/AP_HAL.h"
  18. #include <stdio.h>
  19. #include <AP_Math/AP_Math.h>
  20. using namespace SITL;
  21. // table of user settable parameters
  22. const AP_Param::GroupInfo Gripper_EPM::var_info[] = {
  23. // @Param: ENABLE
  24. // @DisplayName: Gripper servo Sim enable/disable
  25. // @Description: Allows you to enable (1) or disable (0) the gripper servo simulation
  26. // @Values: 0:Disabled,1:Enabled
  27. // @User: Advanced
  28. AP_GROUPINFO("ENABLE", 0, Gripper_EPM, gripper_emp_enable, 0),
  29. // @Param: PIN
  30. // @DisplayName: Gripper emp pin
  31. // @Description: The pin number that the gripper emp is connected to. (start at 1)
  32. // @Range: 0 15
  33. // @User: Advanced
  34. AP_GROUPINFO("PIN", 1, Gripper_EPM, gripper_emp_servo_pin, -1),
  35. AP_GROUPEND
  36. };
  37. /*
  38. update gripper state
  39. */
  40. void Gripper_EPM::update_servobased(int16_t gripper_pwm)
  41. {
  42. if (!servo_based) {
  43. return;
  44. }
  45. if (gripper_pwm >= 0) {
  46. demand = (gripper_pwm - 1000) * 0.001f; // 0.0 - 1.0
  47. if (is_negative(demand)) { // never updated
  48. demand = 0.0f;
  49. }
  50. }
  51. }
  52. void Gripper_EPM::update_from_demand()
  53. {
  54. const uint64_t now = AP_HAL::micros64();
  55. const float dt = (now - last_update_us) * 1.0e-6f;
  56. // decay the field
  57. field_strength = field_strength * (100.0f - field_decay_rate * dt) / 100.0f;
  58. // note that "demand" here is just an on/off switch; we only care
  59. // about which range it falls into
  60. if (demand > 0.6f) {
  61. // we are instructed to grip harder
  62. field_strength = field_strength + (100.0f - field_strength) * field_strength_slew_rate / 100.0f * dt;
  63. } else if (demand < 0.4f) {
  64. // we are instructed to loosen grip
  65. field_strength = field_strength * (100.0f - field_degauss_rate * dt) / 100.0f;
  66. } else {
  67. // neutral; no demanded change
  68. }
  69. if (should_report()) {
  70. ::fprintf(stderr, "demand=%f\n", demand);
  71. printf("Field strength: %f%%\n", field_strength);
  72. printf("Field strength: %f Tesla\n", tesla());
  73. last_report_us = now;
  74. reported_field_strength = field_strength;
  75. }
  76. last_update_us = now;
  77. }
  78. void Gripper_EPM::update(const struct sitl_input &input)
  79. {
  80. const int16_t gripper_pwm = gripper_emp_servo_pin >= 1 ? input.servos[gripper_emp_servo_pin-1] : -1;
  81. update_servobased(gripper_pwm);
  82. update_from_demand();
  83. }
  84. bool Gripper_EPM::should_report()
  85. {
  86. if (AP_HAL::micros64() - last_report_us < report_interval) {
  87. return false;
  88. }
  89. if (fabsf(reported_field_strength - field_strength) > 10.0) {
  90. return true;
  91. }
  92. return false;
  93. }
  94. float Gripper_EPM::tesla()
  95. {
  96. // https://en.wikipedia.org/wiki/Orders_of_magnitude_(magnetic_field)
  97. // 200N lifting capacity ~= 2.5T
  98. const float percentage_to_tesla = 0.25f;
  99. return static_cast<float>(percentage_to_tesla * field_strength / 100.0f);
  100. }