Initialisation du dépôt

This commit is contained in:
Samuel 2026-07-06 22:57:15 +02:00
commit e535b32caf
28 changed files with 1393 additions and 0 deletions

106
Asser_Moteurs.c Normal file
View File

@ -0,0 +1,106 @@
#include "config_robot.h"
#include "QEI.h"
#include "Moteurs.h"
#include "Asser_Moteurs.h"
// Paramètres pour PAMI
#ifdef ROBOT_TYPE_PAMI
#define ASSERMOTEUR_GAIN_P 30000.f
#define ASSERMOTEUR_GAIN_I 3000.f
#endif
// Paramètre Robot 2026
#ifdef ROBOT_PROPULSION_2026
#define ASSERMOTEUR_GAIN_P 150.f
#define ASSERMOTEUR_GAIN_I 1.f
#endif
float consigne_mm_s[3]; // Consigne de vitesse (en mm/s)
float commande_I[3]; // Terme integral
void AsserMoteur_Init(int id){
QEI_init(id);
Moteur_Init();
for(unsigned int i =0; i< 2; i ++){
commande_I[i]=0;
consigne_mm_s[i]=0;
}
}
/// @brief Défini une consigne de vitesse pour le moteur indiqué.
/// @param moteur : Moteur à asservir
/// @param _consigne_mm_s : consigne de vitesse en mm/s
void AsserMoteur_setConsigne_mm_s(enum t_moteur moteur, float _consigne_mm_s){
consigne_mm_s[moteur] = _consigne_mm_s;
}
/// @brief Envoie la consigne du moteur
/// @param moteur : Moteur à asservir
float AsserMoteur_getConsigne_mm_s(enum t_moteur moteur){
return consigne_mm_s[moteur];
}
float AsserMoteur_getVitesse_mm_s(enum t_moteur moteur, int step_ms){
enum QEI_name_t qei;
float distance, temps;
switch (moteur)
{
case MOTEUR_A: qei = QEI_A_NAME; break;
case MOTEUR_B: qei = QEI_B_NAME; break;
default: break;
}
distance = QEI_get_mm(qei);
temps = step_ms / 1000.0f;
return distance / temps;
}
/// @brief Indique si le robot est à l'arrêt
/// @param step_ms : pas de temps (utilisé pour déterminer les vitesses)
/// @return 1 si le robot est immobile, 0 s'il est en mouvement.
uint32_t AsserMoteur_RobotImmobile(int step_ms){
const float seuil_vitesse_immobile_mm_s = 0.1;
if(AsserMoteur_getVitesse_mm_s(MOTEUR_A, step_ms) < seuil_vitesse_immobile_mm_s &&
AsserMoteur_getVitesse_mm_s(MOTEUR_B, step_ms) < seuil_vitesse_immobile_mm_s ){
return 1;
}
return 0;
}
void AsserMoteurs_stop(void){
AsserMoteur_setConsigne_mm_s(MOTEUR_A, 0);
AsserMoteur_setConsigne_mm_s(MOTEUR_A, 0);
}
/// @brief Fonction d'asservissement des moteurs, à appeler périodiquement
/// @param step_ms
void AsserMoteur_Gestion(int step_ms){
// Pour chaque moteur
for(uint moteur=MOTEUR_A; moteur<MOTEUR_B+1; moteur++ ){
float erreur; // Erreur entre la consigne et la vitesse actuelle
float commande_P; // Terme proportionnel
float commande;
// Calcul de l'erreur
erreur = consigne_mm_s[moteur] - AsserMoteur_getVitesse_mm_s(moteur, step_ms);
// Calcul du terme propotionnel
commande_P = erreur * ASSERMOTEUR_GAIN_P;
// Calcul du terme integral
commande_I[moteur] = commande_I[moteur] + (erreur * ASSERMOTEUR_GAIN_I * step_ms);
commande = commande_P + commande_I[moteur];
//Saturation de la commande
if(commande > 32760) {commande = 32760;}
if(commande < -32760) {commande = -32760;}
Moteur_SetVitesse(moteur, commande);
}
}

9
Asser_Moteurs.h Normal file
View File

@ -0,0 +1,9 @@
#include "Moteurs.h"
uint32_t AsserMoteur_RobotImmobile(int step_ms);
void AsserMoteur_setConsigne_mm_s(enum t_moteur moteur, float consigne_mm_s);
float AsserMoteur_getConsigne_mm_s(enum t_moteur moteur);
float AsserMoteur_getVitesse_mm_s(enum t_moteur moteur, int step_ms);
void AsserMoteur_Gestion(int step_ms);
void AsserMoteur_Init(int);
void AsserMoteurs_stop(void);

78
Asser_Position.c Normal file
View File

@ -0,0 +1,78 @@
#include "Localisation.h"
#include "Commande_vitesse.h"
#include "math.h"
#define GAIN_P_POSITION 5
#define GAIN_P_ORIENTATION 5
#define MAX_ERREUR_ANGLE (30 * DEGRE_EN_RADIAN)
struct position_t position_maintien;
/// @brief Asservissement de la position du robot. Les gains sont déterminés pour des positions très proches du robot
/// C'est à la consigne d'être défini avant pour être atteignable.
/// Nécessite l'appel des fonctions QEI_update(); Localisation_gestion(); AsserMoteur_Gestion(_step_ms);
/// @param position_consigne : position à atteindre dans le référentiel de la table.
float delta_x_mm, delta_y_mm, delta_orientation_radian;
float delta_orientation_radian_tmp;
void Asser_Position(struct position_t position_consigne){
float delta_avance_mm;
float avance_mm_s, rotation_radian_s;
//float delta_x_mm, delta_y_mm, delta_orientation_radian;
struct position_t position_actuelle;
float delta_orientation_radian_tmp;
position_actuelle = Localisation_get();
// Calcul de l'erreur
delta_x_mm = position_consigne.x_mm - position_actuelle.x_mm;
delta_y_mm = position_consigne.y_mm - position_actuelle.y_mm;
delta_avance_mm = sqrtf(delta_x_mm * delta_x_mm + delta_y_mm * delta_y_mm);
delta_orientation_radian_tmp = atan2f(delta_y_mm, delta_x_mm) - position_actuelle.angle_radian;
delta_orientation_radian = Geometrie_get_angle_optimal(0. , delta_orientation_radian_tmp);
// On asservi sur +PI/2 / -PI/2
if(delta_orientation_radian > (M_PI/2)){
delta_orientation_radian -= M_PI;
delta_avance_mm = -delta_avance_mm;
}
if(delta_orientation_radian < -(M_PI/2)){
delta_orientation_radian += M_PI;
delta_avance_mm = -delta_avance_mm;
}
// Asservissement
avance_mm_s = delta_avance_mm * GAIN_P_POSITION;
rotation_radian_s = delta_orientation_radian * GAIN_P_ORIENTATION;
/*if(delta_avance_mm < 10){
rotation_radian_s=delta_avance_mm/10 * rotation_radian_s;
}*/
// Commande en vitesse
commande_vitesse(avance_mm_s, rotation_radian_s);
}
void Asser_Position_set_Pos_Maintien(struct position_t position){
position_maintien=position;
}
void Asser_Position_maintien(){
Asser_Position(position_maintien);
}
float Asser_Position_get_erreur_angle(){
return delta_orientation_radian;
}
/// @brief Renvoi 1 si l'erreur d'angle supérieur au seuil
/// @return 1 si panic, 0 si nominal
int Asser_Position_panic_angle(){
if(delta_orientation_radian > MAX_ERREUR_ANGLE){
return 1;
}
return 0;
}

6
Asser_Position.h Normal file
View File

@ -0,0 +1,6 @@
#include "Geometrie.h"
void Asser_Position(struct position_t position_consigne);
void Asser_Position_set_Pos_Maintien(struct position_t position);
void Asser_Position_maintien();
int Asser_Position_panic_angle();

29
CMakeLists.txt Normal file
View File

@ -0,0 +1,29 @@
project(Deplacement_Robot_differentiel C)
include(../pico_sdk_import.cmake)
add_library(Deplacement_Robot_differentiel
Asser_Position.c
Asser_Moteurs.c
Commande_vitesse.c
Evitement.c
Moteurs.c
Localisation.c
QEI.c
Rotation.c
Trajectoire_bezier.c
Trajectoire_circulaire.c
Trajectoire_composees.c
Trajectoire_droite.c
Trajectoire.c
Trajet.c
)
pico_generate_pio_header(Deplacement_Robot_differentiel ${CMAKE_CURRENT_LIST_DIR}/quadrature_encoder.pio)
target_link_libraries(Deplacement_Robot_differentiel
hardware_pio
hardware_pwm
pico_stdlib
)

36
Commande_vitesse.c Normal file
View File

@ -0,0 +1,36 @@
#include "Asser_Moteurs.h"
#include "Geometrie_robot.h"
#include "Commande_vitesse.h"
float avance_mm_s, orientation_radian_s;
float get_avance_mm_s(){
return avance_mm_s;
}
float get_orientation_radian_s(){
return orientation_radian_s;
}
/// @brief Commande de la vitesse dans le référentiel du robot
/// @param avance_mm_s : Vitesse d'avance
/// @param orientation_radian_s : Rotation en radian/s
void commande_vitesse(float _avance_mm_s, float _orientation_radian_s){
float vitesse_roue_gauche, vitesse_roue_droite;
avance_mm_s = _avance_mm_s;
orientation_radian_s = _orientation_radian_s;
vitesse_roue_gauche = avance_mm_s - (orientation_radian_s * DISTANCE_ROUES_CENTRE_MM);
vitesse_roue_droite = avance_mm_s + (orientation_radian_s * DISTANCE_ROUES_CENTRE_MM);
AsserMoteur_setConsigne_mm_s(MOTEUR_A, vitesse_roue_droite);
AsserMoteur_setConsigne_mm_s(MOTEUR_B, vitesse_roue_gauche);
}
/// @brief Arrête le robot.
void commande_vitesse_stop(){
AsserMoteur_setConsigne_mm_s(MOTEUR_A, 0);
AsserMoteur_setConsigne_mm_s(MOTEUR_B, 0);
}

4
Commande_vitesse.h Normal file
View File

@ -0,0 +1,4 @@
void commande_vitesse(float vitesse_avance_mm_s, float orientation_radian_s);
void commande_vitesse_stop(void);
float get_avance_mm_s();
float get_orientation_radian_s();

54
Localisation.c Normal file
View File

@ -0,0 +1,54 @@
#include "Localisation.h"
#include "Temps.h"
#include "QEI.h"
#include "math.h"
#include "Geometrie_robot.h"
struct position_t position;
void Localisation_init(int id){
Temps_init();
QEI_init(id);
position.x_mm = 0;
position.y_mm = 0;
position.angle_radian = 0;
}
void Localisation_set(float x_mm, float y_mm, float angle_radian){
position.x_mm = x_mm;
position.y_mm = y_mm;
position.angle_radian = angle_radian;
}
void Localisation_set_x(float x_mm){
position.x_mm = x_mm;
}
void Localisation_set_y(float y_mm){
position.y_mm = y_mm;
}
void Localisation_set_angle(float angle_radian){
position.angle_radian = angle_radian;
}
void Localisation_gestion(){
float distance_roue_gauche_mm = QEI_get_mm(QEI_B_NAME);
float distance_roue_droite_mm = QEI_get_mm(QEI_A_NAME);
float delta_avance_mm, delta_orientation_rad;
delta_avance_mm = (distance_roue_droite_mm + distance_roue_gauche_mm)/2;
delta_orientation_rad = (distance_roue_droite_mm - distance_roue_gauche_mm) / (DISTANCE_ROUES_CENTRE_MM*2);
position.angle_radian += delta_orientation_rad;
// Projection dans le référentiel de la table
position.x_mm += delta_avance_mm * cosf(position.angle_radian);
position.y_mm += delta_avance_mm * sinf(position.angle_radian);
}
struct position_t Localisation_get(void){
return position;
}

10
Localisation.h Normal file
View File

@ -0,0 +1,10 @@
#include "Geometrie.h"
struct position_t Localisation_get(void);
void Localisation_gestion();
void Localisation_init(int);
void Localisation_set(float x_mm, float y_mm, float angle_radian);
void Localisation_set_x(float x_mm);
void Localisation_set_y(float y_mm);
void Localisation_set_angle(float angle_radian);

141
Moteurs.c Normal file
View File

@ -0,0 +1,141 @@
#include "config_robot.h"
#include "hardware/pwm.h"
#include "Moteurs.h"
#define MOTEUR_A 0
#define MOTEUR_B 1
#define MOTEUR_C 2
#ifdef ROBOT_PROPULSION_2026
#define M1_VITESSE 2 //1A
#define M1_SENS1 3
#define M1_SENS2 4
#define M2_VITESSE 6 //3A
#define M2_SENS1 7
#define M2_SENS2 8
#else
#define M1_SENS1 7
#define M1_SENS2 13
#define M1_VITESSE 27 //5B
#define M2_SENS1 10
#define M2_SENS2 5
#define M2_VITESSE 9 //4B
#endif
uint slice_moteur_A, slice_moteur_B, slice_moteur_C;
int moteur_a_pwm, moteur_b_pwm;
/// @brief Initialisation les entrées / sorties requises pour les moteurs
void Moteur_Init(){
gpio_init(M1_SENS1);
gpio_init(M1_SENS2);
gpio_init(M2_SENS1);
gpio_init(M2_SENS2);
gpio_set_dir(M1_SENS1, GPIO_OUT);
gpio_set_dir(M1_SENS2, GPIO_OUT);
gpio_set_dir(M2_SENS1, GPIO_OUT);
gpio_set_dir(M2_SENS2, GPIO_OUT);
gpio_put(M1_SENS1, 0);
gpio_put(M1_SENS2, 0);
gpio_put(M2_SENS1, 0);
gpio_put(M2_SENS2, 0);
gpio_set_function(M1_VITESSE, GPIO_FUNC_PWM);
gpio_set_function(M2_VITESSE, GPIO_FUNC_PWM);
#ifdef ROBOT_PROPULSION_2026
pwm_set_wrap(1, (uint16_t)65535);
pwm_set_wrap(3, (uint16_t)65535);
pwm_set_chan_level(1, PWM_CHAN_A, 0);
pwm_set_chan_level(3, PWM_CHAN_A, 0);
pwm_set_enabled(1, true);
pwm_set_enabled(3, true);
#else
pwm_set_wrap(4, (uint16_t)65535);
pwm_set_wrap(5, (uint16_t)65535);
pwm_set_chan_level(4, PWM_CHAN_B, 0);
pwm_set_chan_level(5, PWM_CHAN_B, 0);
pwm_set_enabled(4, true);
pwm_set_enabled(5, true);
#endif
Moteur_SetVitesse(MOTEUR_A, 0);
Moteur_SetVitesse(MOTEUR_B, 0);
}
/// @brief Renvoie la commande signée sur 16 bits du PWM
/// @param moteur MOTEUR_A ou MOTEUR_B
/// @return
int16_t Moteur_GetVitesse(enum t_moteur moteur){
uint16_t u_vitesse;
switch (moteur)
{
case MOTEUR_A:
return moteur_a_pwm;
break;
case MOTEUR_B:
return moteur_b_pwm;
break;
default:
return 0;
break;
}
}
/// @brief Configure le PWM et la broche de sens en fonction de la vitesse et du moteur
/// @param moteur : Moteur (voir enum t_moteur)
/// @param vitesse : Vitesse entre -32767 et 32767
void Moteur_SetVitesse(enum t_moteur moteur, int16_t vitesse ){
uint16_t u_vitesse;
// Le PWM accepte 16 bits de résolution, on se remet sur 16 bits (et non sur 15 + signe)
if (vitesse < 0){
u_vitesse = -vitesse;
}else{
u_vitesse = vitesse;
}
u_vitesse = u_vitesse * 2;
switch(moteur){
case MOTEUR_A:
#ifdef ROBOT_PROPULSION_2026
pwm_set_chan_level(1, PWM_CHAN_A, u_vitesse);
if(vitesse > 0){
#else
pwm_set_chan_level(5, PWM_CHAN_B, u_vitesse);
if(vitesse < 0){
#endif
gpio_put(M1_SENS1, 1);
gpio_put(M1_SENS2, 0);
}else{
gpio_put(M1_SENS1, 0);
gpio_put(M1_SENS2, 1);
}
break;
case MOTEUR_B:
#ifdef ROBOT_PROPULSION_2026
pwm_set_chan_level(3, PWM_CHAN_A, u_vitesse);
if(vitesse < 0){
#else
pwm_set_chan_level(4, PWM_CHAN_B, u_vitesse);
if(vitesse > 0){
#endif
gpio_put(M2_SENS1, 1);
gpio_put(M2_SENS2, 0);
}else{
gpio_put(M2_SENS1, 0);
gpio_put(M2_SENS2, 1);
}
break;
}
}
void Moteur_Stop(void){
Moteur_SetVitesse(MOTEUR_A, 0);
Moteur_SetVitesse(MOTEUR_B, 0);
}

15
Moteurs.h Normal file
View File

@ -0,0 +1,15 @@
#include "pico/stdlib.h"
#ifndef MOTEURS_H
#define MOTEURS_H
enum t_moteur {
MOTEUR_A=0,
MOTEUR_B=1,
MOTEUR_C=2
};
#endif
void Moteur_Init(void);
void Moteur_SetVitesse(enum t_moteur moteur, int16_t vitesse );
int16_t Moteur_GetVitesse(enum t_moteur moteur);
void Moteur_Stop(void);

114
QEI.c Normal file
View File

@ -0,0 +1,114 @@
#include "config_robot.h"
#include <stdio.h>
#include "pico/stdlib.h"
#include "hardware/pio.h"
#include "hardware/timer.h"
#include "QEI.h"
#include "quadrature_encoder.pio.h"
/*** C'est ici que se fait la conversion en mm
* ***/
// Roues 60 mm de diamètre, 188,5 mm de circonférence
// Réduction Moteur 30:1
// Réduction poulie 16:12
// Nombre d'impulsions par tour moteur : 200
// Nombre d'impulsions par tour réducteur : 6000
// Nombre d'impulsions par tour de roue : 8000
// Impulsion / mm : 42,44
#define IMPULSION_PAR_MM_50_1 (12.45f)
#define IMPULSION_PAR_MM_30_1 (7.47f)
#define IMPULSION_PAR_MM_robot_2026 (7.57f)
float impulsion_par_mm;
struct QEI_t QEI_A, QEI_B;
bool QEI_est_init = false;
PIO pio_QEI = pio0;
void QEI_init(int identifiant){
// Initialisation des 3 modules QEI
// Chaque module QEI sera dans une machine à état du PIO 0
if(!QEI_est_init){
// Offset le début du programme
// Si ce n'est pas 0, le programme ne marchera pas
uint offset = pio_add_program(pio_QEI, &quadrature_encoder_program);
if(offset != 0){
printf("PIO init error: offset != 0");
}
// Initialisation des "machines à états" :
#ifdef ROBOT_PROPULSION_2026
// QEI1 : broche 11 et 12 - pio : pio0, sm : 0, Offset : 0, GPIO 10 et 11, clock div : 0 pour commencer
quadrature_encoder_program_init(pio_QEI, 1, offset, 10, 0);
// QEI2 : broche 2 et 3 - pio : pio0, sm : 1, Offset : 0, GPIO 14 et 15, clock div : 0 pour commencer
quadrature_encoder_program_init(pio_QEI, 0, offset, 14, 0);
#else
// QEI1 : broche 11 et 12 - pio : pio0, sm : 0, Offset : 0, GPIO 11 et 12, clock div : 0 pour commencer
quadrature_encoder_program_init(pio_QEI, 0, offset, 11, 0);
// QEI2 : broche 2 et 3 - pio : pio0, sm : 1, Offset : 0, GPIO 2 et 3, clock div : 0 pour commencer
quadrature_encoder_program_init(pio_QEI, 1, offset, 2, 0);
#endif
QEI_A.value=0;
QEI_B.value=0;
QEI_est_init=true;
}
#ifdef ROBOT_PROPULSION_2026
impulsion_par_mm = IMPULSION_PAR_MM_robot_2026;
#else
impulsion_par_mm = IMPULSION_PAR_MM_50_1;
if(identifiant == 0 || identifiant >= 4){
impulsion_par_mm = IMPULSION_PAR_MM_30_1;
}
#endif
}
/// @brief Lit les modules QEI et stock l'écart en cette lecture et la lecture précédente.
void QEI_update(void){
int old_value;
old_value = QEI_A.value;
QEI_A.value = quadrature_encoder_get_count(pio_QEI, 0);
QEI_A.delta = QEI_A.value - old_value;
old_value = QEI_B.value;
QEI_B.value = quadrature_encoder_get_count(pio_QEI, 1);
QEI_B.delta = QEI_B.value - old_value;
}
/// @brief Renvoi le nombre d'impulsion du module QEI depuis la lecture précédente
/// Les signe sont inversés (sauf A) car le reducteur inverse le sens de rotation.
/// Attention, le signe du QEI_A est inversé par rapport aux autres à cause d'un soucis sur la carte électornique
/// @param qei : Nom du module à lire (QEI_A_NAME, QEI_B_NAME ou QEI_C_NAME)
/// @return Nombre d'impulsion calculé lors du dernier appel de la function QEI_Update()
int QEI_get(enum QEI_name_t qei){
switch (qei)
{
case QEI_A_NAME:
return QEI_A.delta;
break;
case QEI_B_NAME:
return -QEI_B.delta;
break;
default:
break;
}
}
/// @brief Renvoi la distance parcourue en mm depuis la lecture précédente
/// @param qei : Nom du module à lire (QEI_A_NAME, QEI_B_NAME ou QEI_C_NAME)
/// @return la distance parcourue en mm calculée lors du dernier appel de la function QEI_Update()
float QEI_get_mm(enum QEI_name_t qei){
return ((float) QEI_get(qei)) / impulsion_par_mm;
}

16
QEI.h Normal file
View File

@ -0,0 +1,16 @@
struct QEI_t{
int value;
int delta;
};
enum QEI_name_t{
QEI_A_NAME=0,
QEI_B_NAME=1,
};
extern struct QEI_t QEI_A, QEI_B, QEI_C;
void QEI_update(void);
void QEI_init(int);
int QEI_get(enum QEI_name_t qei);
float QEI_get_mm(enum QEI_name_t qei);

65
Readme.md Normal file
View File

@ -0,0 +1,65 @@
Submodule Servomoteurs pour le RP2040
=====================================
Ceci est un submodule git pour intégrer facilement le support des servomoteurs à un projet.
On crée ce Submodule en se servant de la documentation disponible ici : https://git-scm.com/book/en/v2/Git-Tools-Submodules
Utilisation
===========
Ajout du sub-module
-------------------
Ajouter ce submodule à votre projet. Dans un terminal, dans le répertoire de votre projet, entrez :
git submodule add https://git.poivron-robotique.fr/Keuronde/Module_deplacement_robot_differentiel.git
Ajouter le fichier nouvellement créé .gitmodules à votre projet.
git add .gitmodules
Configuration de la compilation
-------------------------------
Dans le fichier CMakeLists.txt, ajouter le dossier du sub module:
add_subdirectory(RP2040_Servomoteurs)
Dans le fichier CMakeLists.txt, ajouter la bibliothèque RP2040_Servomoteur :
target_link_libraries(Modele_RPiPico
...
RP2040_Servomoteur
)
Intégration au code source
--------------------------
Ajout du fichier d'include :
#include "RP2040_Servomoteurs/Servomoteur.h"
Initilisation du module :
Servomoteur_Init();
Envoie d'une consigne au servomoteur :
Servomoteur_set(num_gpio, position);
Avec :
- num_gpio : le numéro de la GPIO du RP2040
- position : la position du servomoteur, qui correspond à un temps haut du signal compris généralement en 0,5 et 2,5 ms (en fonction des servomoteurs). le fichier _Servomoteur.h_ contient des valeurs d'exemple.
Cas où vous clonez un projet contenant des submodules
-----------------------------------------------------
Après avoir cloné le projet, initilisez les submodules:
git submodule init
git submodule update
Pour récupérer les dernières mise à jour des sub-modules :
git submodule update --remote

88
Rotation.c Normal file
View File

@ -0,0 +1,88 @@
#include "Strategie.h"
#include "Rotation.h"
#include "Localisation.h"
#include "Asser_Moteurs.h"
#include "Geometrie_robot.h"
#include "math.h"
float rotation_angle_cible;
float rotation_angle_sens;
float rotation_vitesse_rad_s;
float rotation_vitesse_max_rad_s;
float rotation_acceleration_rad_ss;
float Rotation_calcul_vitesse(float angle_actuel, float pas_de_temps_s);
void rotation_init(float angle_cible){
struct position_t position = Localisation_get();
rotation_angle_cible = Geometrie_get_angle_optimal(position.angle_radian, angle_cible);
rotation_vitesse_rad_s = 0;
rotation_vitesse_max_rad_s = 5;
rotation_acceleration_rad_ss = 25;
if(rotation_angle_cible - position.angle_radian > 0){
rotation_angle_sens = 1;
}else{
rotation_angle_sens = -1;
}
}
void rotation_set_vitesse(float vitesse_rad_s){
float vitesse_mm_s = vitesse_rad_s * DISTANCE_ROUES_CENTRE_MM;
if(rotation_angle_sens == 1){
AsserMoteur_setConsigne_mm_s(MOTEUR_A, vitesse_mm_s);
AsserMoteur_setConsigne_mm_s(MOTEUR_B, -vitesse_mm_s);
}else{
AsserMoteur_setConsigne_mm_s(MOTEUR_A, -vitesse_mm_s);
AsserMoteur_setConsigne_mm_s(MOTEUR_B, vitesse_mm_s);
}
}
enum etat_action_t rotation_gestion(float pas_de_temps_s){
struct position_t position = Localisation_get();
rotation_vitesse_rad_s = Rotation_calcul_vitesse(position.angle_radian, pas_de_temps_s);
if (rotation_angle_sens == 1 ){
rotation_set_vitesse(rotation_vitesse_rad_s);
if (position.angle_radian > rotation_angle_cible){
return ACTION_TERMINEE;
}
}else{
if (position.angle_radian < rotation_angle_cible){
return ACTION_TERMINEE;
}
}
return ACTION_EN_COURS;
}
float Rotation_calcul_vitesse(float angle_actuel, float pas_de_temps_s){
// Phase d'accélération
rotation_vitesse_rad_s = rotation_vitesse_rad_s + pas_de_temps_s * rotation_acceleration_rad_ss;
// Saturation par vitesse max
if(rotation_vitesse_rad_s > rotation_vitesse_max_rad_s){
rotation_vitesse_rad_s = rotation_vitesse_max_rad_s;
}
// Saturation par la courbe de décélération
float vitesse_décélération_rad_s;
// distance restante
float angle_restant;
if (rotation_angle_sens == 1){
angle_restant = rotation_angle_cible - angle_actuel;
}else{
angle_restant = angle_actuel - rotation_angle_cible;
}
if(angle_restant < 0){
vitesse_décélération_rad_s = 0;
}else{
vitesse_décélération_rad_s = sqrtf(2 * rotation_acceleration_rad_ss * angle_restant);
}
if(rotation_vitesse_rad_s > vitesse_décélération_rad_s){
rotation_vitesse_rad_s = vitesse_décélération_rad_s;
}
return rotation_vitesse_rad_s;
}

4
Rotation.h Normal file
View File

@ -0,0 +1,4 @@
extern float rotation_angle_cible, rotation_vitesse_rad_s;
void rotation_init(float angle_cible);
enum etat_action_t rotation_gestion(float pas_de_temps_s);

196
Trajectoire.c Normal file
View File

@ -0,0 +1,196 @@
#include "Trajectoire.h"
#include "Trajectoire_bezier.h"
#include "Trajectoire_circulaire.h"
#include "Trajectoire_droite.h"
#include "Trajectoire_composees.h"
#include "math.h"
#define PRECISION_ABSCISSE 0.001f
#define NB_MAX_ITERATIONS 3
void Trajectoire_circulaire(struct trajectoire_t * trajectoire, float centre_x, float centre_y, float angle_debut_rad,
float angle_fin_rad, float rayon, float orientation_debut_rad, float orientation_fin_rad){
trajectoire->type = TRAJECTOIRE_CIRCULAIRE;
trajectoire->p1.x = centre_x;
trajectoire->p1.y = centre_y;
trajectoire->angle_debut_rad = angle_debut_rad;
trajectoire->angle_fin_rad = angle_fin_rad;
trajectoire->rayon = rayon;
trajectoire->longueur = -1;
trajectoire->orientation_debut_rad = orientation_debut_rad;
trajectoire->orientation_fin_rad = orientation_fin_rad;
}
void Trajectoire_droite(struct trajectoire_t * trajectoire, float p1_x, float p1_y, float p2_x, float p2_y,
float orientation_debut_rad, float orientation_fin_rad){
trajectoire->type = TRAJECTOIRE_DROITE;
trajectoire->p1.x = p1_x;
trajectoire->p1.y = p1_y;
trajectoire->p2.x = p2_x;
trajectoire->p2.y = p2_y;
trajectoire->longueur = -1;
trajectoire->orientation_debut_rad = orientation_debut_rad;
trajectoire->orientation_fin_rad = orientation_fin_rad;
}
void Trajectoire_bezier(struct trajectoire_t * trajectoire, float p1_x, float p1_y, float p2_x, float p2_y, float p3_x, float p3_y,
float p4_x, float p4_y, float orientation_debut_rad, float orientation_fin_rad){
trajectoire->type = TRAJECTOIRE_BEZIER;
trajectoire->p1.x = p1_x;
trajectoire->p1.y = p1_y;
trajectoire->p2.x = p2_x;
trajectoire->p2.y = p2_y;
trajectoire->p3.x = p3_x;
trajectoire->p3.y = p3_y;
trajectoire->p4.x = p4_x;
trajectoire->p4.y = p4_y;
trajectoire->longueur = -1;
trajectoire->orientation_debut_rad = orientation_debut_rad;
trajectoire->orientation_fin_rad = orientation_fin_rad;
}
/// @brief Initialise une trajectoire composée
/// @param trajectoire : trajectoire à initialiser
void Trajectoire_composee_init(struct trajectoire_t * trajectoire){
trajectoire->type = TRAJECTOIRE_COMPOSEE;
trajectoire->longueur = -1;
trajectoire->nb_trajectoire = 0;
for (int index =0; index <NB_MAX_TRAJECTOIRE ; index++){
trajectoire->trajectoires[index] = NULL;
}
}
/// @brief Ajoute une trajectoire à une trajectoire composée déjà initialisée
/// @param trajectoire_composee
/// @param trajectoire
void Trajectoire_composee_ajout(struct trajectoire_t * trajectoire_composee, struct trajectoire_t * trajectoire){
if(trajectoire_composee->nb_trajectoire < NB_MAX_TRAJECTOIRE){
trajectoire_composee->trajectoires[trajectoire_composee->nb_trajectoire] = trajectoire;
trajectoire_composee->nb_trajectoire++;
}
}
void Trajectoire_inverse(struct trajectoire_t * trajectoire){
struct trajectoire_t old_trajectoire;
old_trajectoire = *trajectoire;
trajectoire->orientation_debut_rad = old_trajectoire.orientation_fin_rad;
trajectoire->orientation_fin_rad = old_trajectoire.orientation_debut_rad;
if(trajectoire->type == TRAJECTOIRE_CIRCULAIRE){
trajectoire->angle_debut_rad = old_trajectoire.angle_fin_rad;
trajectoire->angle_fin_rad = old_trajectoire.angle_debut_rad;
return;
}
if(trajectoire->type == TRAJECTOIRE_DROITE){
trajectoire->p1 = old_trajectoire.p2;
trajectoire->p2 = old_trajectoire.p1;
return;
}
if(trajectoire->type == TRAJECTOIRE_BEZIER){
trajectoire->p1 = old_trajectoire.p4;
trajectoire->p2 = old_trajectoire.p3;
trajectoire->p3 = old_trajectoire.p2;
trajectoire->p4 = old_trajectoire.p1;
}
}
/// @brief Renvoie la longueur de la trajectoire en mm, la calcule si besoin
/// @param trajectoire
/// @return Longueur de la trajectoire
float Trajectoire_get_longueur_mm(struct trajectoire_t * trajectoire){
if(trajectoire->longueur > 0){
// La longueur est déjà calculée
}else{
// Calculons la longueur de la trajectoire
switch(trajectoire->type){
case TRAJECTOIRE_DROITE:
Trajectoire_droite_get_longueur(trajectoire);
break;
case TRAJECTOIRE_CIRCULAIRE:
Trajectoire_circulaire_get_longueur(trajectoire);
break;
case TRAJECTOIRE_BEZIER:
Trajectoire_bezier_get_longueur(trajectoire);
break;
case TRAJECTOIRE_COMPOSEE:
Trajectoire_composee_get_longueur(trajectoire);
break;
}
}
return trajectoire->longueur;
}
/// @brief Renvoie le point d'une trajectoire à partir de son abscisse
/// @param abscisse : abscisse sur la trajectoire
/// @return point en coordonnées X/Y
struct point_xyo_t Trajectoire_get_point(struct trajectoire_t * trajectoire, double abscisse){
struct point_xyo_t point_xyo;
switch(trajectoire->type){
case TRAJECTOIRE_DROITE:
point_xyo.point_xy = Trajectoire_droite_get_point(trajectoire, abscisse);
break;
case TRAJECTOIRE_CIRCULAIRE:
point_xyo.point_xy = Trajectoire_circulaire_get_point(trajectoire, abscisse);
break;
case TRAJECTOIRE_BEZIER:
point_xyo.point_xy = Trajectoire_bezier_get_point(trajectoire, abscisse);
break;
case TRAJECTOIRE_COMPOSEE:
point_xyo = Trajectoire_composee_get_point(trajectoire, abscisse);
break;
}
return point_xyo;
}
float Trajectoire_get_orientation_rad(struct trajectoire_t * trajectoire, float abscisse){
return (float) trajectoire->orientation_debut_rad * (1-abscisse) + (float) trajectoire->orientation_fin_rad * abscisse;
}
/// @brief Calcul la nouvelle abscisse une fois avancé de la distance indiquée
/// @param abscisse : Valeur entre 0 et 1, position actuelle du robot sur sa trajectoire
/// @param distance_mm : Distance en mm de laquelle le robot doit avancer sur la trajectoire
/// @return nouvelle abscisse
float Trajectoire_avance(struct trajectoire_t * trajectoire, double abscisse, double distance_mm){
double delta_abscisse, delta_mm, erreur_relative;
if(distance_mm == 0){
return abscisse;
}
// Ceci permet d'avoir une abscisse exact sur les trajectoires droites, les trajectoires circulaires et les rotations
delta_abscisse = distance_mm / Trajectoire_get_longueur_mm(trajectoire);
if(trajectoire->type == TRAJECTOIRE_CIRCULAIRE || trajectoire->type == TRAJECTOIRE_DROITE){
return abscisse + delta_abscisse;
}
delta_mm = distance_points(Trajectoire_get_point(trajectoire, abscisse).point_xy, Trajectoire_get_point(trajectoire, abscisse + delta_abscisse).point_xy );
// Sur les trajectoires de bézier, il peut être nécessaire d'affiner
// Les cas où l'algorythme diverge ne devraient pas se produire car distance_cm << longeur_trajectoire.
erreur_relative = 1 - delta_mm / distance_mm;
int nb_iteration=0;
while(fabs(erreur_relative) > PRECISION_ABSCISSE && nb_iteration < NB_MAX_ITERATIONS){
delta_abscisse = delta_abscisse * distance_mm / delta_mm;
delta_mm = distance_points(Trajectoire_get_point(trajectoire, abscisse).point_xy, Trajectoire_get_point(trajectoire, abscisse + delta_abscisse).point_xy );
erreur_relative = 1 - delta_mm / distance_mm;
nb_iteration++;
}
return abscisse + delta_abscisse;
}
double distance_points(struct point_xy_t point, struct point_xy_t point_old){
return sqrt( pow(point.x - point_old.x, 2) + pow(point.y - point_old.y , 2));
}

48
Trajectoire.h Normal file
View File

@ -0,0 +1,48 @@
#ifndef TRAJECTOIRE_H
#define TRAJECTOIRE_H
#define NB_MAX_TRAJECTOIRE 10
enum trajectoire_type_t{
TRAJECTOIRE_DROITE=0,
TRAJECTOIRE_CIRCULAIRE=1,
TRAJECTOIRE_BEZIER=2,
TRAJECTOIRE_COMPOSEE=3
};
struct point_xy_t{
float x, y;
};
struct point_xyo_t{
struct point_xy_t point_xy;
};
struct trajectoire_t {
enum trajectoire_type_t type;
struct point_xy_t p1, p2, p3, p4;
float orientation_debut_rad, orientation_fin_rad;
float rayon, angle_debut_rad, angle_fin_rad;
float longueur;
// Pour les trajectoires composées
struct trajectoire_t * trajectoires[NB_MAX_TRAJECTOIRE];
int nb_trajectoire;
};
float Trajectoire_get_longueur_mm(struct trajectoire_t * trajectoire);
struct point_xyo_t Trajectoire_get_point(struct trajectoire_t * trajectoire, double abscisse);
float Trajectoire_get_orientation_rad(struct trajectoire_t * trajectoire, float abscisse);
float Trajectoire_avance(struct trajectoire_t * trajectoire, double abscisse, double distance_mm);
double distance_points(struct point_xy_t point, struct point_xy_t point_old);
void Trajectoire_circulaire(struct trajectoire_t * trajectoire, float centre_x, float centre_y, float angle_debut_rad, float angle_fin_rad,
float rayon, float orientation_debut_rad, float orientation_fin_rad);
void Trajectoire_droite(struct trajectoire_t * trajectoire, float p1_x, float p1_y, float p2_x, float p2_y, float orientation_debut_rad, float orientation_fin_rad);
void Trajectoire_bezier(struct trajectoire_t * trajectoire, float p1_x, float p1_y, float p2_x, float p2_y, float p3_x, float p3_y, float p4_x, float p4_y,
float orientation_debut_rad, float orientation_fin_rad);
void Trajectoire_rotation(struct trajectoire_t * trajectoire, float p1_x, float p1_y, float orientation_debut_rad, float orientation_fin_rad);
void Trajectoire_composee_init(struct trajectoire_t * trajectoire);
void Trajectoire_composee_ajout(struct trajectoire_t * trajectoire_composee, struct trajectoire_t * trajectoire);
void Trajectoire_inverse(struct trajectoire_t * trajectoire);
#endif

35
Trajectoire_bezier.c Normal file
View File

@ -0,0 +1,35 @@
#include "Trajectoire.h"
#include "Trajectoire_bezier.h"
void Trajectoire_bezier_get_longueur(struct trajectoire_t * trajectoire){
struct point_xy_t point, point_old;
float nb_pas=500;
trajectoire->longueur=0;
point_old = trajectoire->p1;
for(float abscisse=0; abscisse<=1; abscisse += 1./nb_pas){
point = Trajectoire_bezier_get_point(trajectoire, abscisse);
trajectoire->longueur += distance_points(point, point_old);
point_old = point;
}
}
/// @brief Retourne le point sur la trajectoire en fonction de l'abscisse
/// @param abscisse : compris entre 0 et 1
struct point_xy_t Trajectoire_bezier_get_point(struct trajectoire_t * trajectoire, double abscisse){
struct point_xy_t point;
point.x = (double) trajectoire->p1.x * (1-abscisse) * (1-abscisse) * (1-abscisse) +
3 * (double) trajectoire->p2.x * abscisse * (1-abscisse) * (1-abscisse) +
3 * (double) trajectoire->p3.x * abscisse * abscisse * (1-abscisse) +
(double) trajectoire->p4.x * abscisse * abscisse * abscisse;
point.y = (double) trajectoire->p1.y * (1-abscisse) * (1-abscisse) * (1-abscisse) +
3 * (double) trajectoire->p2.y * abscisse * (1-abscisse) * (1-abscisse) +
3 * (double) trajectoire->p3.y * abscisse * abscisse * (1-abscisse) +
(double) trajectoire->p4.y * abscisse * abscisse * abscisse;
return point;
}

5
Trajectoire_bezier.h Normal file
View File

@ -0,0 +1,5 @@
#include "Trajectoire.h"
void Trajectoire_bezier_get_longueur(struct trajectoire_t * trajectoire);
struct point_xy_t Trajectoire_bezier_get_point(struct trajectoire_t * trajectoire, double abscisse);

26
Trajectoire_circulaire.c Normal file
View File

@ -0,0 +1,26 @@
#include "math.h"
#include "Trajectoire.h"
void Trajectoire_circulaire_get_longueur(struct trajectoire_t * trajectoire){
float distance_angulaire;
if(trajectoire->angle_debut_rad > trajectoire->angle_fin_rad){
distance_angulaire = trajectoire->angle_debut_rad - trajectoire->angle_fin_rad;
}else{
distance_angulaire = trajectoire->angle_fin_rad - trajectoire->angle_debut_rad;
}
trajectoire->longueur = trajectoire->rayon * distance_angulaire;
}
/// @brief Retourne le point sur la trajectoire en fonction de l'abscisse
/// @param abscisse : compris entre 0 et 1
struct point_xy_t Trajectoire_circulaire_get_point(struct trajectoire_t * trajectoire, float abscisse){
struct point_xy_t point;
float angle_rad;
angle_rad = (float) trajectoire->angle_debut_rad * (1-abscisse) + (float) trajectoire->angle_fin_rad * abscisse;
point.x = trajectoire->p1.x + cos(angle_rad) * trajectoire->rayon;
point.y = trajectoire->p1.y + sin(angle_rad) * trajectoire->rayon;
return point;
}

4
Trajectoire_circulaire.h Normal file
View File

@ -0,0 +1,4 @@
#include "math.h"
void Trajectoire_circulaire_get_longueur(struct trajectoire_t * trajectoire);
struct point_xy_t Trajectoire_circulaire_get_point(struct trajectoire_t * trajectoire, float avancement);

24
Trajectoire_composees.c Normal file
View File

@ -0,0 +1,24 @@
#include <math.h>
#include "Trajectoire.h"
#include "Trajectoire_composees.h"
void Trajectoire_composee_get_longueur(struct trajectoire_t * trajectoire_composee){
trajectoire_composee->longueur = 0;
for(unsigned int i = 0 ; i<trajectoire_composee->nb_trajectoire ; i++) {
trajectoire_composee->longueur += Trajectoire_get_longueur_mm(trajectoire_composee->trajectoires[i]);
}
}
struct point_xyo_t Trajectoire_composee_get_point(struct trajectoire_t * trajectoire_composee, double abscisse){
// Obtenir la trajectoire sur laquelle nous sommes...
int index_trajectoire;
double abscisse_etendue, abscisse_locale;
abscisse_etendue = abscisse * trajectoire_composee->nb_trajectoire;
index_trajectoire = (int) floor(abscisse_etendue);
abscisse_locale = abscisse_etendue - floor(abscisse_etendue);
return Trajectoire_get_point(trajectoire_composee->trajectoires[index_trajectoire], abscisse_locale);
}

3
Trajectoire_composees.h Normal file
View File

@ -0,0 +1,3 @@
struct point_xyo_t Trajectoire_composee_get_point(struct trajectoire_t * trajectoire_composee, double abscisse);
void Trajectoire_composee_get_longueur(struct trajectoire_t * trajectoire_composee);

17
Trajectoire_droite.c Normal file
View File

@ -0,0 +1,17 @@
#include "Trajectoire.h"
void Trajectoire_droite_get_longueur(struct trajectoire_t * trajectoire){
trajectoire->longueur = distance_points(trajectoire->p1, trajectoire->p2);
}
/// @brief Retourne le point sur la trajectoire en fonction de l'abscisse
/// @param abscisse : compris entre 0 et 1
struct point_xy_t Trajectoire_droite_get_point(struct trajectoire_t * trajectoire, float abscisse){
struct point_xy_t point;
point.x = (float) trajectoire->p1.x * (1. - abscisse) + (float) trajectoire->p2.x * abscisse;
point.y = (float) trajectoire->p1.y * (1. - abscisse) + (float) trajectoire->p2.y * abscisse;
return point;
}

4
Trajectoire_droite.h Normal file
View File

@ -0,0 +1,4 @@
#include "Trajectoire.h"
void Trajectoire_droite_get_longueur(struct trajectoire_t * trajectoire);
struct point_xy_t Trajectoire_droite_get_point(struct trajectoire_t * trajectoire, float abscisse);

219
Trajet.c Normal file
View File

@ -0,0 +1,219 @@
#include <math.h>
#include "Geometrie.h"
#include "Trajectoire.h"
#include "Trajet.h"
#include "Asser_Position.h"
#include "Asser_Moteurs.h"
#include "Temps.h"
float Trajet_calcul_vitesse(float temps_s);
int Trajet_terminee(float abscisse);
float abscisse; // Position entre 0 et 1 sur la trajectoire
float position_mm; // Position en mm sur la trajectoire
float vitesse_mm_s;
float vitesse_max_trajet_mm_s;
float acceleration_mm_ss;
const float acceleration_mm_ss_obstacle = 500;
struct trajectoire_t trajet_trajectoire;
struct position_t position_consigne;
float distance_obstacle_mm;
float distance_fin_trajectoire_mm;
const float distance_pas_obstacle = 2000;
float vitesse_max_contrainte_obstacle;
/// @brief Initialise le module Trajet. A appeler en phase d'initialisation
void Trajet_init(int id){
Temps_init();
AsserMoteur_Init(id);
abscisse = 0;
vitesse_mm_s = 0;
position_mm = 0;
Trajet_config(TRAJECT_CONFIG_STD);
}
/// @brief Configure la vitesse maximale et l'acceleration pour les futurs trajets
/// @param _vitesse_max_trajet_mm_s
/// @param _acceleration_mm_ss
void Trajet_config(float _vitesse_max_trajet_mm_s, float _acceleration_mm_ss){
vitesse_max_trajet_mm_s = _vitesse_max_trajet_mm_s;
acceleration_mm_ss = _acceleration_mm_ss;
}
void Trajet_debut_trajectoire(struct trajectoire_t trajectoire){
abscisse = 0;
vitesse_mm_s = 0;
position_mm = 0;
trajet_trajectoire = trajectoire;
Trajet_set_obstacle_mm(DISTANCE_INVALIDE);
}
/// @brief Avance la consigne de position sur la trajectoire
/// @param pas_de_temps_s : temps écoulé depuis le dernier appel en seconde
/// @return TRAJET_EN_COURS ou TRAJET_TERMINE
struct point_xyo_t point;
enum etat_trajet_t Trajet_avance(float pas_de_temps_s){
float distance_mm;
enum etat_trajet_t trajet_etat = TRAJET_EN_COURS;
struct position_t position;
// Calcul de la vitesse
vitesse_mm_s = Trajet_calcul_vitesse(pas_de_temps_s);
// Calcul de l'avancement en mm
distance_mm = vitesse_mm_s * pas_de_temps_s;
position_mm += distance_mm;
// Calcul de l'abscisse sur la trajectoire
abscisse = Trajectoire_avance(&trajet_trajectoire, abscisse, distance_mm);
//set_debug_varf(abscisse);
// Obtention du point consigne
point = Trajectoire_get_point(&trajet_trajectoire, abscisse);
position.x_mm = point.point_xy.x;
position.y_mm = point.point_xy.y;
position_consigne=position;
Asser_Position(position);
if(Trajet_terminee(abscisse)){
Asser_Position_set_Pos_Maintien(position);
trajet_etat = TRAJET_TERMINE;
}
return trajet_etat;
}
void Trajet_stop(float pas_de_temps_s){
vitesse_mm_s = 0;
Trajet_avance(pas_de_temps_s);
}
/// @brief Savoir si un trajet est terminé est trivial sauf pour les courbes de Bézier
/// où les approximations font que l'abscisse peut ne pas atteindre 1.
/// @param abscisse : abscisse sur la trajectoire
/// @return 1 si le trajet est terminé, 0 sinon
int Trajet_terminee(float abscisse){
/*if(abscisse >= 0.99 ){
return 1;
}*/
if(trajet_trajectoire.type != TRAJECTOIRE_BEZIER){
if(abscisse >= 1 || distance_fin_trajectoire_mm < 0.1){
return 1;
}
}else{
if(abscisse >= 0.99 ){
return 1;
}
}
return 0;
}
/// @brief Envoie la consigne de position calculée par le module trajet. Principalement pour le débug/réglage asservissement.
struct position_t Trajet_get_consigne(){
return position_consigne;
}
/// @brief Calcule la vitesse à partir de laccélération du robot, de la vitesse maximale et de la contrainte en fin de trajectoire
/// @param pas_de_temps_s : temps écoulé en ms
/// @return vitesse déterminée en m/s
float Trajet_calcul_vitesse(float pas_de_temps_s){
float vitesse_max_contrainte;
float distance_contrainte,distance_contrainte_obstacle;
float vitesse;
// Calcul de la vitesse avec acceleration
vitesse = vitesse_mm_s + acceleration_mm_ss * pas_de_temps_s;
// Calcul de la vitesse maximale due à la contrainte en fin de trajectoire (0 mm/s)
// https://poivron-robotique.fr/Consigne-de-vitesse.html
distance_contrainte = Trajectoire_get_longueur_mm(&trajet_trajectoire) - position_mm;
distance_fin_trajectoire_mm=distance_contrainte;
// En cas de dépassement, on veut garder la contrainte, pour l'instant
if(distance_contrainte > 0){
vitesse_max_contrainte = sqrtf(2 * acceleration_mm_ss * distance_contrainte);
}else{
vitesse_max_contrainte = 0;
}
distance_contrainte_obstacle = Trajet_get_obstacle_mm();
if(distance_contrainte_obstacle != DISTANCE_INVALIDE){
vitesse_max_contrainte_obstacle = sqrtf(2 * acceleration_mm_ss_obstacle * distance_contrainte_obstacle);
if(vitesse_max_contrainte_obstacle < vitesse_max_contrainte){
vitesse_max_contrainte = vitesse_max_contrainte_obstacle;
}
}/*
if((Trajet_get_obstacle_mm() != DISTANCE_INVALIDE) && (Trajet_get_obstacle_mm() < 50)){
vitesse = 0;
}*/
// Selection de la vitesse la plus faible
if(vitesse > vitesse_max_contrainte){
vitesse = vitesse_max_contrainte;
}
if(vitesse > vitesse_max_trajet_mm_s){
vitesse = vitesse_max_trajet_mm_s;
}
return vitesse;
}
float Trajet_get_obstacle_mm(void){
return distance_obstacle_mm;
}
void Trajet_set_obstacle_mm(float distance_mm){
distance_obstacle_mm = distance_mm;
}
/// @brief Renvoi l'angle d'avancement du robot dans le référentiel du terrain
/// @return angle en radian.
float Trajet_get_orientation_avance(){
struct point_xyo_t point, point_suivant;
float avance_abscisse = 0.01;
float angle;
if(abscisse >= 1){
return 0;
}
if(abscisse + avance_abscisse >= 1){
avance_abscisse = 1 - abscisse;
}
point = Trajectoire_get_point(&trajet_trajectoire, abscisse);
point_suivant = Trajectoire_get_point(&trajet_trajectoire, abscisse + avance_abscisse);
angle = atan2f(point_suivant.point_xy.y - point.point_xy.y, point_suivant.point_xy.x - point.point_xy.x);
return angle;
}
void Trajet_inverse(){
float old_abscisse = abscisse;
float old_position_mm = position_mm;
Trajectoire_inverse(&trajet_trajectoire);
Trajet_debut_trajectoire(trajet_trajectoire);
abscisse = 1 - old_abscisse;
position_mm = Trajectoire_get_longueur_mm(&trajet_trajectoire) - old_position_mm;
}
float Trajet_get_abscisse(){
return abscisse;
}
/// @brief Indique si le robot est bloqué sur le trajet
/// @return 0 si le robot n'est pas bloqué, 1 s'il est bloqué
uint32_t Trajet_get_bloque(){
if(Trajet_get_obstacle_mm() == DISTANCE_INVALIDE){
return 0;
}
if (vitesse_max_contrainte_obstacle == 0){
return 1;
}
return 0;
}

37
Trajet.h Normal file
View File

@ -0,0 +1,37 @@
#include "pico/stdlib.h"
#include "Trajectoire.h"
#ifndef TRAJET_H
#define TRAJET_H
enum etat_trajet_t{
TRAJET_EN_COURS,
TRAJET_TERMINE
};
// Vitesse et acceleration pour translation pure (en mm/s et mm/s²)
#define TRAJECT_CONFIG_RAPIDE 300, 1200
#define TRAJECT_CONFIG_RAPIDE_ROUGE 500, 1200
// Vitesse et acceleration pour un mouvement complexe (en mm et mm/s²)
#define TRAJECT_CONFIG_AVANCE_ET_TOURNE 300, 500
// Vitesse et acceleration - standard (en mm/s et mm/s²)
#define TRAJECT_CONFIG_STD 300, 300
// Vitesse et acceleration pour une rotation (rad/s et rad/s²)
#define TRAJECT_CONFIG_ROTATION_PURE 2, 2
extern const float distance_pas_obstacle;
void Trajet_init(int);
void Trajet_config(float _vitesse_max_trajet_mm_s, float _acceleration_mm_ss);
void Trajet_debut_trajectoire(struct trajectoire_t trajectoire);
enum etat_trajet_t Trajet_avance(float temps_s);
struct position_t Trajet_get_consigne(void);
float Trajet_get_obstacle_mm(void);
void Trajet_set_obstacle_mm(float distance_mm);
void Trajet_stop(float);
float Trajet_get_orientation_avance(void);
float Trajet_get_abscisse();
uint32_t Trajet_get_bloque();
void Trajet_inverse();
#endif