/* * This file is part of the stmbl project. * * Copyright (C) 2013-2017 Rene Hopf * Copyright (C) 2013-2017 Nico Stute * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ // #include "commands.h" #include "hal.h" #include "math.h" #include "defines.h" #include "angle.h" HAL_COMP(ypid); HAL_PIN(pos_ext_cmd); // cmd in (rad) HAL_PIN(pos_fb); // feedback in (rad) HAL_PIN(pos_error); // error out (rad) HAL_PIN(vel_ext_cmd); // cmd in (rad/s) HAL_PIN(vel_fb); // feedback in (rad/s) HAL_PIN(vel_cmd); // cmd out (rad/s) HAL_PIN(vel_error); // error out (rad/s) HAL_PIN(vel_min); // minimum velocity error 0.3 HAL_PIN(enable); HAL_PIN(out); HAL_PIN(pos_p); //10 HAL_PIN(vel_p); //0.5 HAL_PIN(vel_i); //0.005 HAL_PIN(vel_ff); //1.0 // system limits HAL_PIN(max_vel); HAL_PIN(max_acc); HAL_PIN(max_out); HAL_PIN(vel_sat); HAL_PIN(out_sat); HAL_PIN(saturated); struct ypid_ctx_t { float sat; float vel_error_sum; }; static void rt_func(float period, volatile void *ctx_ptr, volatile hal_pin_inst_t *pin_ptr) { struct ypid_ctx_t *ctx = (struct ypid_ctx_t *)ctx_ptr; struct ypid_pin_ctx_t *pins = (struct ypid_pin_ctx_t *)pin_ptr; float vel_cmd; float vel_fb = PIN(vel_fb); float vel_error; float vel_sat; float out_sat; float pos_error = minus(PIN(pos_ext_cmd), PIN(pos_fb)); float pos_p = MAX(PIN(pos_p), 0.0); float vel_p = MAX(PIN(vel_p), 0.0); float vel_i = MAX(PIN(vel_i), 0.0); float velmin = MAX(-PIN(max_vel), vel_fb - PIN(max_acc) * period); float velmax = MIN(PIN(max_vel), vel_fb + PIN(max_acc) * period); float out; if(PIN(enable) > 0.0) { // pos -> vel vel_cmd = pos_p * pos_error + PIN(vel_ff) * PIN(vel_ext_cmd); vel_sat = SAT(vel_cmd, PIN(max_vel)); vel_cmd = CLAMP(vel_cmd, velmin, velmax); // min/max clamping // vel -> out vel_error = vel_cmd - vel_fb; if(ABS(vel_error) < PIN(vel_min)) { vel_error = 0; } ctx->vel_error_sum += vel_error; out = LIMIT(vel_error * vel_p, PIN(max_out)); if(vel_i * vel_p > 0.0f) { ctx->vel_error_sum = CLAMP(ctx->vel_error_sum, (-PIN(max_out) - out) / (vel_i * vel_p), (PIN(max_out) - out) / (vel_i * vel_p)); } else { ctx->vel_error_sum = 0; } out += ctx->vel_error_sum * vel_i * vel_p; out_sat = SAT(out, PIN(max_out) * 0.99); out = LIMIT(out, PIN(max_out)); // sat if(ABS(vel_sat) + ABS(out_sat) > 0.0) { ctx->sat += period; } else { ctx->sat = 0.0; } } else { ctx->vel_error_sum = 0.0; vel_cmd = 0.0; vel_error = 0.0; vel_sat = 0.0; out_sat = 0.0; ctx->sat = 0.0; out = 0.0; } PIN(pos_error) = pos_error; PIN(vel_cmd) = vel_cmd; PIN(vel_error) = vel_error; PIN(out) = out; PIN(vel_sat) = vel_sat; PIN(out_sat) = out_sat; PIN(saturated) = ctx->sat; } hal_comp_t ypid_comp_struct = { .name = "ypid", .nrt = 0, .rt = rt_func, .frt = 0, .nrt_init = 0, .rt_start = 0, .frt_start = 0, .rt_stop = 0, .frt_stop = 0, .ctx_size = sizeof(struct ypid_ctx_t), .pin_count = sizeof(struct ypid_pin_ctx_t) / sizeof(struct hal_pin_inst_t), };