#include "stdio.h" #include "Strategie_prise_cerises.h" #include "Commande_vitesse.h" #include "Geometrie.h" #include "Geometrie_robot.h" #include "Localisation.h" #include "math.h" #include "i2c_annexe.h" // Rotation en rad/s pour accoster les cerises #define ROTATION_CERISE 0.5f // Distance la plus éloignée du bord où le robot est capable d'aspirer les cerises en longeant la bodure. #define MAX_LONGE_MM 240 // Translation en mm/s pour aspirer les cerises #define TRANSLATION_CERISE 70 void commande_rotation_contacteur_longer_A(); void commande_rotation_contacteur_longer_C(); void commande_translation_longer_vers_A(); void commande_translation_longer_vers_C(); enum longer_direction_t inverser_longe_direction(enum longer_direction_t direction); double vitesse_accostage_mm_s=100; /// @brief Fonction pour attraper les cerises sur les supports perpendiculaires à la bordure. /// Le robot accoste, longe le support cerise vers la bordure, active la turbine, puis longe le support cerise jusqu'à son bout. /// @param longer_direction : direction dans laquelle se trouve la bordure /// @return ACTION_EN_COURS ou ACTION_TERMINEE enum etat_action_t cerise_attraper_bordure(enum longer_direction_t longer_direction, uint32_t step_ms){ enum etat_action_t etat_action = ACTION_EN_COURS; enum longer_direction_t longer_direction_aspire; static uint32_t tempo_ms = 0; static enum { ATTRAPE_INIT, ATTRAPE_VERS_BORDURE, TURBINE_DEMARRAGE, TURBINE_DEMARRAGE_TEMPO, ASPIRE_LONGE, ASPIRE_LIBRE } etat_attrape=ATTRAPE_INIT; switch(etat_attrape){ case ATTRAPE_INIT: etat_attrape=ATTRAPE_VERS_BORDURE; break; case ATTRAPE_VERS_BORDURE: avance_puis_longe_bordure(longer_direction); if( (longer_direction == LONGER_VERS_A) && (i2c_annexe_get_contacteur_butee_A() == CONTACTEUR_ACTIF) || (longer_direction == LONGER_VERS_C) && (i2c_annexe_get_contacteur_butee_C() == CONTACTEUR_ACTIF) ){ etat_attrape = TURBINE_DEMARRAGE; } break; case TURBINE_DEMARRAGE: i2c_annexe_ferme_porte(); i2c_annexe_active_turbine(); commande_vitesse_stop(); tempo_ms = 1000; etat_attrape = TURBINE_DEMARRAGE_TEMPO; break; case TURBINE_DEMARRAGE_TEMPO: if(tempo_ms < step_ms){ etat_attrape = ASPIRE_LONGE; printf(">e:ASPIRE_LONGE|t\n"); }else{ tempo_ms -= step_ms; } break; case ASPIRE_LONGE: longer_direction_aspire = inverser_longe_direction(longer_direction); avance_puis_longe_bordure(LONGER_VERS_A); // La fonction cerise_longer_bord n'est efficace que tant que le robot a ses deux contacteur sur le support // Le robot n'a les deux contacteurs sur le support que tant qu'il est à moins de 240mm (MAX_LONGE_MM) de la bordure // En fonction du demi-terrain sur lequel se trouve le robot, on surveille la position en Z pour respecter cette condition if( ((Localisation_get().y_mm > 1500) && (Localisation_get().y_mm < (3000 - MAX_LONGE_MM) )) || ((Localisation_get().y_mm < 1500) && (Localisation_get().y_mm > (MAX_LONGE_MM))) ){ etat_attrape = ASPIRE_LIBRE; printf(">e:ASPIRE_LIBRE|t\n"); } break; case ASPIRE_LIBRE: commande_vitesse_stop(); i2c_annexe_desactive_turbine(); etat_action = ACTION_TERMINEE; break; } return etat_action; } /// @brief Fonction pour accoster et longer une bordure /// @param longer_direction : direction dans laquelle le robot va aller une fois le long de la bordure /// @return ACTION_EN_COURS enum etat_action_t avance_puis_longe_bordure(enum longer_direction_t longer_direction){ static enum { LONGE_INIT, LONGE_NORMAL, LONGE_COLLE } etat_longer_bord=LONGE_INIT; switch (etat_longer_bord){ case LONGE_INIT: etat_longer_bord=LONGE_NORMAL; break; case LONGE_NORMAL: if(longer_direction==LONGER_VERS_A){ commande_translation_longer_vers_A(); if( (i2c_annexe_get_contacteur_longer_A() == CONTACTEUR_INACTIF) || (i2c_annexe_get_contacteur_longer_C() == CONTACTEUR_INACTIF) ){ etat_longer_bord = LONGE_COLLE; } }else{ commande_translation_longer_vers_C(); if( (i2c_annexe_get_contacteur_longer_A() == CONTACTEUR_INACTIF) || (i2c_annexe_get_contacteur_longer_C() == CONTACTEUR_INACTIF) ){ etat_longer_bord = LONGE_COLLE; } } break; case LONGE_COLLE: if(cerise_accostage() == ACTION_TERMINEE){ etat_longer_bord = LONGE_NORMAL; } } return ACTION_EN_COURS; } enum etat_action_t cerise_accostage(void){ enum etat_action_t etat_action = ACTION_EN_COURS; double rotation; static enum { CERISE_AVANCE_DROIT, CERISE_TOURNE_CONTACTEUR_LONGER_A, CERISE_TOURNE_CONTACTEUR_LONGER_C, CERISE_ACCOSTE } etat_accostage=CERISE_AVANCE_DROIT; switch (etat_accostage) { case CERISE_AVANCE_DROIT: commande_vitesse(vitesse_accostage_mm_s * cos(-M_PI/6), vitesse_accostage_mm_s * sin(-M_PI/6), 0); if(i2c_annexe_get_contacteur_longer_A() == CONTACTEUR_ACTIF){ etat_accostage=CERISE_TOURNE_CONTACTEUR_LONGER_A; printf("D ACCOSTE_TOURNE_A\n"); } if(i2c_annexe_get_contacteur_longer_C() == CONTACTEUR_ACTIF){ etat_accostage=CERISE_TOURNE_CONTACTEUR_LONGER_C; printf("D ACCOSTE_TOURNE_C\n"); } if (i2c_annexe_get_contacteur_longer_A() == CONTACTEUR_ACTIF && i2c_annexe_get_contacteur_longer_C() == CONTACTEUR_ACTIF){ etat_accostage=CERISE_ACCOSTE; printf("D ACCOSTE\n"); } break; case CERISE_TOURNE_CONTACTEUR_LONGER_A: commande_rotation_contacteur_longer_A(); if(i2c_annexe_get_contacteur_longer_A() == CONTACTEUR_INACTIF){ if(i2c_annexe_get_contacteur_longer_C() == CONTACTEUR_INACTIF){ etat_accostage = CERISE_AVANCE_DROIT; printf("A ACCOSTE_AVANCE\n"); }else{ etat_accostage = CERISE_TOURNE_CONTACTEUR_LONGER_A; printf("A ACCOSTE_TOURNE_A\n"); } }else if(i2c_annexe_get_contacteur_longer_C() == CONTACTEUR_ACTIF){ etat_accostage = CERISE_ACCOSTE; printf("A ACCOSTE\n"); } break; case CERISE_TOURNE_CONTACTEUR_LONGER_C: commande_rotation_contacteur_longer_C(); if(i2c_annexe_get_contacteur_longer_C() == CONTACTEUR_INACTIF){ if(i2c_annexe_get_contacteur_longer_A() == CONTACTEUR_INACTIF){ etat_accostage = CERISE_AVANCE_DROIT; printf("C ACCOSTE_AVANCE\n"); }else{ etat_accostage = CERISE_TOURNE_CONTACTEUR_LONGER_C; printf("C ACCOSTE_TOURNE_C\n"); } }else if(i2c_annexe_get_contacteur_longer_A() == CONTACTEUR_ACTIF){ etat_accostage = CERISE_ACCOSTE; printf("C ACCOSTE\n"); } break; case CERISE_ACCOSTE: commande_vitesse_stop(); etat_accostage = CERISE_AVANCE_DROIT; etat_action = ACTION_TERMINEE; break; default: break; } return etat_action; } void commande_rotation_contacteur_longer_A(){ commande_rotation(ROTATION_CERISE, RAYON_ROBOT, 0); } void commande_rotation_contacteur_longer_C(){ commande_rotation(-ROTATION_CERISE, RAYON_ROBOT/2.0, -RAYON_ROBOT* RACINE_DE_3/2.0); } void commande_translation_longer_vers_A(){ // V_x : V * cos (60°) = V / 2 // V_y : V * sin (60°) = V * RACINE(3) / 2 commande_vitesse(TRANSLATION_CERISE/2., TRANSLATION_CERISE / 2. * RACINE_DE_3, 0); } void commande_translation_longer_vers_C(){ // V_x : -V * cos (60°) = -V / 2 // V_y : -V * sin (60°) = -V * RACINE(3) / 2 commande_vitesse(-TRANSLATION_CERISE/2., -TRANSLATION_CERISE / 2. * RACINE_DE_3, 0); } enum longer_direction_t inverser_longe_direction(enum longer_direction_t direction){ if(direction ==LONGER_VERS_A){ return LONGER_VERS_C; } return LONGER_VERS_A; }