J'essaie de ralentir lentement en fonction d'un pourcentage.
En gros: si le pourcentage est égal à 0, la vitesse doit être speed_max , si le pourcentage atteint 85, la vitesse doit être speed_min , en continuant avec speed_min jusqu'à ce que le pourcentage atteigne 100%. À des pourcentages compris entre 0% et 85%, la vitesse doit être calculée avec le pourcentage.
J'ai déjà commencé à écrire le code, même si je ne sais pas comment continuer:
// Target
int degrees = 90;
// Making sure we're at 0
resetGyro(0);
int speed_max = 450;
int speed_min = 150;
float currentDeg = 0;
float percentage = 0;
while(percentage < 100)
{
//??
getGyroDeg(¤tDeg);
percentage = (degrees/100)*currentDeg;
}
killMotors(1);
3 Réponses :
En supposant que la vitesse est calculée linéairement sur la base de pourcentages de 0 à 85 (et reste à speed_min avec un pourcentage gt 85), voici votre formule pour calculer la vitesse:
if (percentage >= 85)
{
speed = speed_min;
}
else
{
speed = speed_max - (((speed_max - speed_min)*percentage)/85);
}
L'interpolation linéaire est assez simple.
pourcentage 0, la vitesse doit être speed_max . pourcentage 85, la vitesse doit être de speed_min . pourcentage supérieures à 85, la vitesse doit toujours être de speed_min . speed_max et speed_min , donc pourcentage est un 'montant de chute par rapport au maximum vitesse ». En supposant que pourcentage est de type float:
return speed_max - (speed_max - speed_min) * percentage / 85.0;
Vous pouvez également remplacer le retour final avec l'équivalent:
float speed_from_percentage(float percent)
{
if (percent <= 0.0)
return speed_max;
if (percent >= 85.0)
return speed_min;
return speed_min + (speed_max - speed_min) * (85.0 - percentage) / 85.0;
}
Si vous êtes vraiment pédant, toutes les constantes doivent être suffixées avec F pour indiquer float code > et donc utiliser l'arithmétique float au lieu de l'arithmétique double . Et par conséquent, vous devriez probablement également utiliser float pour speed_min et speed_max . Si tout est censé être de l'arithmétique entière, vous pouvez changer float en int et supprimer le .0 des expressions.
En supposant que getGyroDeg est entré par le contrôleur, ce que vous décrivez est un contrôle proportionnel. Une courbe de réponse constante, ie , 0 à 85 a une sortie de 450 à 150, et 150 après cela, est une approche ad-hoc , basée sur l'expérience. Cependant, un contrôleur PID correctement initialisé atteint généralement un temps de consigne plus rapide et une plus grande stabilité.
#include <stdio.h>
#include <time.h>
#include <assert.h>
#include <stdlib.h>
static float sim_current = 0.0f;
static float sim_dt = 0.01f;
static float sim_speed = 0.0f /* 150.0f */;
static void getGyroDeg(float *const current) {
assert(current);
sim_current += sim_speed * sim_dt;
/* Simulate measurement error. */
*current = sim_current + 3.0 * ((2.0 * rand() / RAND_MAX) - 1.0);
}
static void setGyroSpeed(const float speed) {
assert(speed >= /*150.0f*/-450.0f && speed <= 450.0f);
sim_speed = speed;
}
int main(void) {
/* https://en.wikipedia.org/wiki/PID_controller
u(t) = K_p e(t) + K_i \int_0^t e(\theta)d\theta + K_d de(t)/dt */
const float setpoint = 90.0f;
const float max = 450.0f;
const float min = -450.0f/* 150.0f */;
/* Random value; actually get this number. */
const float dt = 1.0f;
/* Tune these. */
const float kp = 30.0f, ki = 4.0f, kd = 2.0f;
float current, last = 0.0f, integral = 0.0f;
float t = 0.0f;
float e, p, i, d, pid;
size_t count;
for(count = 0; count < 40; count++) {
getGyroDeg(¤t);
e = setpoint - current;
p = kp * e;
i = ki * integral * dt;
d = kd * (e - last) / dt;
last = e;
pid = p + i + d;
if(pid > max) {
pid = max;
} else if(pid < min) {
pid = min;
} else {
integral += e;
}
setGyroSpeed(pid);
printf("%f\t%f\t%f\n", t, sim_current, pid);
t += dt;
}
return EXIT_SUCCESS;
}
Ici, au lieu que la vitesse diminue linéairement, il calcule la vitesse dans une boucle de contrôle. Cependant, si le minimum est de 150, cela n'atteindra pas une plus grande stabilité; si vous dépassez 90, vous n'avez aucun moyen de revenir en arrière.
Si les contrôles sont [-450, 450] , ça passe par zéro et c'est beaucoup plus agréable; Je pense que c'est peut-être ce que vous recherchez. Il corrige activement les erreurs.
Vous dites «lerp d'une vitesse»; Malheureusement, «lerp» n'est pas un verbe en anglais, donc ce que vous demandez du titre n'est pas clair. Vouliez-vous dire «bondir»?
C'est l'abréviation de l'interpolation linéaire.
Oh… eh bien, ce serait peut-être une bonne idée de dire cela dans la question; ce n'est pas un terme que j'ai rencontré (mais je ne travaille pas avec des gyroscopes sous contrôle informatique). Je vois que Wikipédia mentionne «lerp» dans son article sur interpolation linéaire .
Je ne comprends pas "si le pourcentage est égal à 0, la vitesse doit être speed_max" - cela n’a pas de sens
@barny: La valeur du
pourcentagecorrespond au ralentissement par rapport à la vitesse maximale, 85 étant le nombre auquel vous atteignez la vitesse minimale.Utiliser «puissance» (c'est-à-dire quelque chose que le code peut contrôler) au lieu de «vitesse» (quelque chose que le code ne peut que mesurer) a plus de sens pour moi.
Si vous souhaitez utiliser
int, en.wikipedia.org/wiki/ Bresenham% 27s_line_algorithm utilise tous lesints pour interpoler, donnant les réponses exactes. Cela peut être intéressant surtout si vous travaillez sur du matériel limité (sans FPU?)