Line data Source code
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 : 7 : This program is distributed in the hope that it will be useful, 8 : but WITHOUT ANY WARRANTY; without even the implied warranty of 9 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10 : GNU General Public License for more details. 11 : 12 : You should have received a copy of the GNU General Public License 13 : along with this program. If not, see <http://www.gnu.org/licenses/>. 14 : */ 15 : /* 16 : simple Gripper (OpenGrab EPM) simulation class 17 : */ 18 : 19 : #include "SIM_Gripper_EPM.h" 20 : #include "AP_HAL/AP_HAL.h" 21 : #include <stdio.h> 22 : #include <AP_Math/AP_Math.h> 23 : 24 : extern const AP_HAL::HAL& hal; 25 : 26 : using namespace SITL; 27 : 28 : // table of user settable parameters 29 : const AP_Param::GroupInfo Gripper_EPM::var_info[] = { 30 : 31 : // @Param: ENABLE 32 : // @DisplayName: Gripper servo Sim enable/disable 33 : // @Description: Allows you to enable (1) or disable (0) the gripper servo simulation 34 : // @Values: 0:Disabled,1:Enabled 35 : // @User: Advanced 36 : AP_GROUPINFO("ENABLE", 0, Gripper_EPM, gripper_emp_enable, 0), 37 : 38 : // @Param: PIN 39 : // @DisplayName: Gripper emp pin 40 : // @Description: The pin number that the gripper emp is connected to. (start at 1) 41 : // @Range: 0 15 42 : // @User: Advanced 43 : AP_GROUPINFO("PIN", 1, Gripper_EPM, gripper_emp_servo_pin, -1), 44 : 45 : AP_GROUPEND 46 : }; 47 : 48 : /* 49 : update gripper state 50 : */ 51 0 : void Gripper_EPM::update_servobased(int16_t gripper_pwm) 52 : { 53 0 : if (!servo_based) { 54 0 : return; 55 : } 56 0 : if (gripper_pwm >= 0) { 57 0 : demand = (gripper_pwm - 1000) * 0.001f; // 0.0 - 1.0 58 0 : if (is_negative(demand)) { // never updated 59 0 : demand = 0.0f; 60 : } 61 : } 62 : } 63 : 64 : 65 0 : void Gripper_EPM::update_from_demand() 66 : { 67 0 : const uint64_t now = AP_HAL::micros64(); 68 0 : const float dt = (now - last_update_us) * 1.0e-6f; 69 : 70 : // decay the field 71 0 : field_strength = field_strength * (100.0f - field_decay_rate * dt) * 0.01f; 72 : 73 : // note that "demand" here is just an on/off switch; we only care 74 : // about which range it falls into 75 0 : if (demand > 0.6f) { 76 : // we are instructed to grip harder 77 0 : field_strength = field_strength + (100.0f - field_strength) * field_strength_slew_rate * 0.01f * dt; 78 0 : } else if (demand < 0.4f) { 79 : // we are instructed to loosen grip 80 0 : field_strength = field_strength * (100.0f - field_degauss_rate * dt) * 0.01f; 81 : } else { 82 : // neutral; no demanded change 83 : } 84 : 85 0 : if (should_report()) { 86 0 : hal.console->printf("demand=%f\n", demand); 87 0 : hal.console->printf("Field strength: %f%%\n", field_strength); 88 0 : hal.console->printf("Field strength: %f Tesla\n", tesla()); 89 0 : last_report_us = now; 90 0 : reported_field_strength = field_strength; 91 : } 92 : 93 0 : last_update_us = now; 94 0 : } 95 : 96 0 : void Gripper_EPM::update(const struct sitl_input &input) 97 : { 98 0 : const int16_t gripper_pwm = gripper_emp_servo_pin >= 1 ? input.servos[gripper_emp_servo_pin-1] : -1; 99 : 100 0 : update_servobased(gripper_pwm); 101 : 102 0 : update_from_demand(); 103 0 : } 104 : 105 : 106 0 : bool Gripper_EPM::should_report() const 107 : { 108 0 : if (AP_HAL::micros64() - last_report_us < report_interval) { 109 0 : return false; 110 : } 111 : 112 0 : if (fabsf(reported_field_strength - field_strength) > 10.0) { 113 0 : return true; 114 : } 115 : 116 0 : return false; 117 : } 118 : 119 0 : float Gripper_EPM::tesla() const 120 : { 121 : // https://en.wikipedia.org/wiki/Orders_of_magnitude_(magnetic_field) 122 : // 200N lifting capacity ~= 2.5T 123 0 : const float percentage_to_tesla = 0.25f; 124 0 : return static_cast<float>(percentage_to_tesla * field_strength * 0.01f); 125 : }