strategie.cpp

来自「this the code of bootstation」· C++ 代码 · 共 346 行

CPP
346
字号


#include "stdafx.h"		//in MFC einkommentieren, sonst raus!



#include "Strategie.h"


void Strategie()
{
	switch (Handlung)
	{
	case Fwd:			Strategie_Vor();		break;
	case Turn:			Strategie_Dreh();		break;
	case Rev:			Strategie_Ruek();		break;
	case Koor_r_Turn:	Koor_rechts_Dreh();		break;
	case Koor_l_Turn:	Koor_links_Dreh();		break;
	case Koor_Fwd_Rev:	Koord_Vor_Ruek();		break;
	case Stop:			Flug_stoppen();			break;
	case ToOrigin:		ZumStartpunkt();		break;
	case FollowObject:	Objektverfolgung();		break;

	default:					 break;
	}	
}

//******************************************************************************
//Sollwertgenerierung Vorw鋞s: Leistung_x_soll, Hoehe_soll, Richtung_soll
void Strategie_Vor()
{
	
	float temp_P;	//Variablen f黵 Leistung_x_soll Berechnung (Geschwindigkeit)
	float temp_I;
	float temp_D;
	float temp_e;
	float temp_Erg;

	//Hoehe_soll ------------------------------------------------------------------
	Flug_Hoehe();

	//keine x_Bewegung, bei H鰄enunterschied zwischen Soll und Ist >1m (Strategie wird ausgesetzt)
	if (Hoehe_soll - Entf_unten[0] > 1)
	{
		Leistung_x_soll = 0;
	}
	//-----------------------------------------------------------------------------
	//sonst Strategie ausf黨ren
	else
	{

		if (Strategie_Sperrzeit > 0)
		{
			Strategie_Sperrzeit--; //Sperrzeit verringern, falls vorhanden
		}
		else
		{
			//Regelung der Geschwindigkeit mit Sollwert (1m) Abstand zum Hindernis vorne.

			temp_e 			= Entf_vorne[0] - Stop_vor_Wand;

		//Strategie鋘derung, wenn Sollwert praktisch erreicht und Geschwindigkeit praktisch 0
			if ((fabs(e_Entf_Fwd_alt - temp_e) < 0.02) && (fabs(temp_e) < 0.1))
			{
				//auf Drehm鰃lichkeit pr黤en und angemessene Entfernung
				if ( ((Entf_rechts[0] >= 2) && (Entf_links[0] >= 2)) &&
					 ((Entf_rechts[0] >= 3) || (Entf_links[0] >= 3)) )
				{
					Handlung = Turn;		
				}
				//sonst wieder R點kw鋜ts
				else
				{
					Handlung = Rev;
				}	
			}
			
			//sonst Sollwertberechnung f黵 Fwd Funktion
			else
			{
		//Leistung_x_soll ---------------------------------------------------------------
				temp_P 			= temp_e * P_Entf_Fwd;
				temp_I			= 0.5*(temp_e + e_Entf_Fwd_alt)*Prozesszyklus;
				temp_I 			= temp_I * I_Entf_Fwd + I_Anteil_Entf_Fwd;
				
				//Wenn e_Entfernung > 1m, keinen I_Anteil berechnen
				if (fabs(temp_e) > 1) temp_I = 0;				
				I_Anteil_Entf_Fwd= temp_I;

				temp_D			= (temp_e - e_Entf_Fwd_alt)/Prozesszyklus * D_Entf_Fwd;
				
				//Wenn e_Entfernung > 1m, keinen D_Anteil berechnen
				if (fabs(temp_e) > 1) temp_D = 0;
				
				e_Entf_Fwd_alt 	= temp_e;
				temp_Erg		= temp_P + temp_I + temp_D;
				
				if (temp_Erg >= 1){temp_Erg = 1;}
				if (temp_Erg <= -1){temp_Erg = -1;}
				
				//neuer Leistungssollwert
				Leistung_x_soll = temp_Erg;	
		//-------------------------------------------------------------------------------

		//Richtung_soll -----------------------------------------------------------------

				//Regeln des Seitenabstandes auf 2m, bei einer Gangbreite von >=4m, sonst mittig zum Gang
				
				//Regelung, wenn Seitenabstand > 4m
				if (Entf_rechts[0] + Entf_links[0] >=4)
				{
					//Regelminimum: Entfernung < 3m
					if ((Entf_rechts[0] < 3) || (Entf_links[0] < 3))
					{	
						//Regeln auf rechte Seite (2m)
						if (Entf_rechts[0] < Entf_links[0])
						{
							//Seitenregelung true==Linksdrehung, wenn soll-ist==pos. auf 2m
							PID_Seite(true, Entf_rechts, Entf_soll);
						}
						//Regeln auf linke Seite (2m)
						else
						{
							//Seitenregelung false==Rechtsdrehung, wenn soll-ist==pos. auf 2m
							PID_Seite(false, Entf_links, Entf_soll);
						}
					}
				}
				//Regelung, wenn Entfernung < 4m auf Sollabstand (R+L)/2
				else
				{
					//Seitenregelung true==Linksdrehung, wenn soll-ist==pos. auf (R+L)/2
					PID_Seite(true, Entf_rechts, (Entf_rechts[0]+Entf_links[0])/2);

				}
		//-----------------------------------------------------------------------------

			}//else Sollwertberechnug
		}//else Sperrzeit
	}//else Strategie ausf黨ren (H鰄e ist OK)
}//Funktion

//********************************************************************************
//Sollwertgenerierung Drehung: Leistung_x_soll=0, Hoehe_soll, Richtungs_Orientierung=+-90
void Strategie_Dreh()
{
	Leistung_x_soll = 0;

	if (Dreh_gestartet == true)
	{
		//wenn Richtung praktisch erreicht, dann n鋍hste Handlung ausf黨ren
		if(fabs(Richtung_ist[0] - Richtungs_Orientierung) < 3)
		{
			//n鋍hste Handlung ist Fwd
			temp_init();					//temp Variablen initialisieren
			Dreh_gestartet = false;
			Handlung = Fwd;
			Strategie_Sperrzeit = 1;		//Sperrzeit f黵 10 Zyklen (wg Istwert Erfassung)
		}
	}	
	//Drehung starten
	else
	{
		Dreh_gestartet = true;	//Drehung gestartet vermerken		
		Leistung_x_soll = 0;	//Vortrieb abschalten

		//Drehung in Richtung rechts
		if (Entf_rechts[0] > Entf_links[0])
		{
			Richtungs_Orientierung -= 90;
		}
		//Drehung in Richtung links
		else
		{
			Richtungs_Orientierung += 90;
		}
		Richtung_soll = Richtungs_Orientierung; //neue Orientierung dem Sollwert zuweisen
	}
}

//*******************************************************************************
//Sollwertgenerierung R點kwarts: Leistung_x_soll, Hoehe_soll, Richtung_soll
//bis Drehung m鰃lich oder Hindernis erreicht
void Strategie_Ruek()
{
	float temp_P;
	float temp_I;
	float temp_D;
	float temp_e;
	float temp_Erg;

	//Hoehe_soll ------------------------------------------------------------------
	Flug_Hoehe();

	//keine x_Bewegung, bei H鰄enunterschied zwischen Soll und Ist >1m (Strategie wird ausgesetzt)
	if (Hoehe_soll - Entf_unten[0] > 1)
	{
		Leistung_x_soll = 0;
	}
	//-----------------------------------------------------------------------------
	//sonst Strategie ausf黨ren
	else
	{
		temp_e 			= Entf_hinten[0] - temp_Entf_stop; //Stopenffernung (evtl. Seitenweg)

		//testen, ob eine Drehung sinnvoll ist (Seitenabstand > 4m)
		if( ((Entf_rechts[0] >= 4) || (Entf_links[0] >= 4)) && 
			((Entf_rechts[0] >= 2) && (Entf_links[0] >= 2))	&& 
			(Seitenweg_gesehen == false) && 
			(Entf_hinten[0] < 6) )
		{
			//Wenn noch kein Seitenweg gesehen wurde, diesen vermerken und nach 50cm stoppen
			temp_Entf_stop = Entf_hinten[0] - 0.5;	
			Seitenweg_gesehen = true;
		}

		//Strategie鋘derung, wenn Sollwert praktisch erreicht und Geschwindigkeit praktisch 0
		if ((fabs(e_Entf_Fwd_alt - temp_e) < 0.03) && (fabs(temp_e) < 0.1))
		{
			//Wenn Seitenweg gesehen
			if (Seitenweg_gesehen==true)
			{
				//auf Drehm鰃lichkeit pr黤en, wenn m鰃lich, dann Strategie "Turn"
				if ((Entf_rechts[0] > 2) && (Entf_links[0] > 2))
				{
					//stoppen
					Seitenweg_gesehen = false;
					temp_Entf_stop = Stop_vor_Wand;			//Stopentfernung wieder auf default setzen
					Handlung = Turn;		
				}
				//sonst wieder R點kw鋜ts und Seitengang ignorieren
				else
				{
					Seitenweg_gesehen = false;
					temp_Entf_stop = Stop_vor_Wand;	//Stop-Entfernung wieder auf default setzen
				}
			}
			//sonst Handlung Fwd, da Ruck nicht mehr m鰃lich
			else
			{
				temp_Entf_stop = Stop_vor_Wand;
				Handlung = Fwd;		
			}
		}

		//normaler R點kw鋜tsflug
		else
		{
			temp_e 			= Entf_hinten[0] - temp_Entf_stop; //Stopenffernung (evtl Seitenweg)
	//Leistung_x_soll ---------------------------------------------------------------
			temp_P 			= temp_e * P_Entf_Fwd;
			temp_I			= 0.5*(temp_e + e_Entf_Fwd_alt)*Prozesszyklus;
			temp_I 			= temp_I * I_Entf_Fwd + I_Anteil_Entf_Fwd;

			//Wenn e_Entfernung > 1m, keinen I_Anteil berechnen
			if (fabs(temp_e) > 1) temp_I = 0;			
			I_Anteil_Entf_Fwd= temp_I;

			temp_D	= (temp_e - e_Entf_Fwd_alt)/Prozesszyklus * D_Entf_Fwd;
			
			//Wenn e_Entfernung > 1m, keinen D_Anteil berechnen
			if (fabs(temp_e) > 1) temp_D = 0;
			
			e_Entf_Fwd_alt 	= temp_e;
			temp_Erg		= temp_P + temp_I + temp_D;
			
			if (temp_Erg >= 1){temp_Erg = 1;}
			if (temp_Erg <= -1){temp_Erg = -1;}
			
			//neuer Leistungssollwert (R點kw鋜ts)
			Leistung_x_soll = temp_Erg *(-1);	
	//-------------------------------------------------------------------------------

	//Richtung_soll -----------------------------------------------------------------

			//Regeln des Seitenabstandes auf 2m, bei einer Gangbreite von >4m, sonst mittig zum Gang
			
			//keine Regelung, wenn Entfernung > Reglebereich (R+L max. 6m)
			if (Entf_rechts[0] + Entf_links[0] >=4)
			{
				//Regelminimum: Entfernung < 3m
				if ((Entf_rechts[0] < 3) || (Entf_links[0] < 3))
				{
					//Regeln auf rechte Seite (2m)
					if (Entf_rechts[0] < Entf_links[0])
					{	
						//Seitenregelung false==Linksdrehung, wenn soll-ist==pos. auf 2m
						PID_Seite(false, Entf_rechts, Entf_soll);
					}

					//Regeln auf linke Seite (2m)
					else
					{
						//Seitenregelung true==Rechtsdrehung, wenn soll-ist==pos. auf 2m
						PID_Seite(true, Entf_links, Entf_soll);
					}
				}
			}
			//Regelung, wenn Entfernung < 4m auf Sollabstand (R+L)/2
			else
			{
				PID_Seite(false, Entf_rechts, (Entf_rechts[0]+Entf_links[0])/2);
			}
	//-----------------------------------------------------------------------------

		}//else normaler R點kw鋜tsflug
	}//lese Strategie ausf黨ren
}//Funktion


//*******************************************************************************
//Seitenregelung auf Seitenabstand_soll
void PID_Seite(bit Richtung, float Seitenabstand[5], float Seitenabstand_soll)
{
	//Richtung == false -> Rechtsdreh (negative Werte) wenn soll-ist==pos
	//Richtung == true -> Linksdreh (positive Werte) 
	float temp_P;
	float temp_I;
	float temp_D;
	float temp_e;
	float temp_Erg;
	float temp_x;
	
	temp_x = (Seitenabstand[0] - Seitenabstand[4])/5;
	temp_e 	= Seitenabstand_soll - Seitenabstand[0];//temp_x;

	//nur Regeln, wenn der Abstand sich <30cm ge鋘dert hat
	if (fabs(temp_x < 0.3))
	{
		temp_P 			= temp_e * P_Seite;
		temp_I			= 0.5*(temp_e + e_Seite_alt)*Prozesszyklus;
		temp_I 			= temp_I * I_Seite + I_Anteil_Seite;

		//Wenn abs(e_Seitenabstand) > 50cm, keinen I_Anteil berechnen
		if (fabs(temp_e) > 0.5) temp_I = 0;		
		I_Anteil_Seite	= temp_I;

		temp_D			= (temp_e - e_Seite_alt)/Prozesszyklus * D_Seite;

		e_Seite_alt 	= temp_e;
		temp_Erg		= temp_P + temp_I + temp_D;

		//Bestimmung der Richtung (s.o.)
		if (Richtung == false) temp_Erg = temp_Erg*(-1);
		
		//maximal zul鋝sige Richtungskorrektur ist 40

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?