kısa cevap; Hayır, gerçekten işleri biraz farklı yapmanız gerekiyor.
uzun eksik cevap; Size robotC için uygun bir psuedo kodu vereyim, bu da sizi daha iyi bir yola sokuyor. İlk olarak, görevleri kullanmayın - bu robotC görevlerinin ne olduğu DEĞİLDİR. Belki işe yarayabilirler, belki de olmayabilirler (ve denemek için birkaç değişikliğe ihtiyacınız var).
// global variables
int distance;
int light;
main() {
while (true) {
distance = read_distance;
light = read_light;
if (task1_wantsToRun())
task1_run();
if (task2_wantsToRun())
task2_run();
}
}
burada birkaç şey var; öncelik önemsiz hale gelir. RobotC'ta öncelikleri olan görevler varmış gibi görünse de, tecrübelerime göre birikim uygulaması için iyi bir seçim değiller. Öncelikler her zaman onurlandırılmaz, görevler kesilemez (bazen), bu nedenle daha yüksek öncelikli bir olay meydana geldiğinde, beklediğiniz gibi tepki vermez, robotC sadece son zamanlarda yeniden girildi, böylece bir sensöre erişmek gibi şeyler 1'den fazla görev riskli olabilir (I2C zamanlama sorunları) ve bazı durumlarda değildir (otomatik olarak yoklanan sensörler).
İşleri çalıştırırken yukarıdaki döngüye kendi öncelik uygulamanızı ekleyebilirsiniz, ancak başlangıçlar için gerçekten gerekli değildir.
"// tıkanıklığı engelle" yorumunuz balistik bir davranışı açıklar. Bunlar çoklu görev kullanarak uygulamak biraz zor. Kullandığım basit döngü, yeni başlayanlar / öğrenme için çok daha kolay ve daha iyi hale getiriyor.
Sizi bırakacağım bir diğer şey de, bir çok şey için temiz ve uygunken, toplamın geleneksel olarak daha iyi olanı uygulamak için iyi bir yol olmadığıdır. Gerçekten de 'kaçınma' kısmı toplam için iyi bir aday olabilir, ama dürüst olmak gerekirse diğer göreviniz 'GoOnAboutYourBusiness' olarak adlandırılmalıdır. Bunu söylüyorum çünkü büyük olasılıkla aramadan izlemeye geçerek değiştirmek istemezsiniz. Geleneksel programlama döngülerine sahip olanlarla başa çıkın. Tek bir sensörle, - ışık algılanan son döngüden daha koyu veya daha açık mı? daha koyu hale gelirse (siyah çizgi varsayarak) aynı yönü çevirmeye devam edin, daha açıksa diğer yöne çevirin, eğer aynı kaldıysa, düz gidin. Daha yumuşak olabilmek için muhtemelen biraz PID eklemeniz ve sadece sola ve sağa döndürmek yerine bir direksiyon eğrisi kullanmanız gerekir.
Ve evet, çoklu sensörler yardımcı olur. http://www.mindsensors.com/ - evet, şu anda filmde benim (11/10/2012)
Güncelleme: gerçek kod
Bunu kısa bir süre içinde deneyeceğim, ancak yukarıda yazdıklarımı derleyip gösteriyor:
#pragma config(Sensor, S1, S_LIGHT, sensorLightActive)
#pragma config(Sensor, S2, S_DISTANCE, sensorSONAR)
#pragma config(Motor, motorB, LEFT, tmotorNXT, PIDControl, encoder)
#pragma config(Motor, motorC, RIGHT, tmotorNXT, PIDControl, encoder)
//*!!Code automatically generated by 'ROBOTC' configuration wizard !!*//
int distance_value, light_value;
bool evade_wantsToRun()
{
return distance_value < 30;
}
void evade_task()
{
// full stop
motor[LEFT] = 0;
// evade the object ballistically (ie in full control)
// turn left, drive
nSyncedTurnRatio = 0;
motor[LEFT] = -20;
Sleep(500);
nSyncedTurnRatio = 100;
Sleep(1000);
// turn right, drive
nSyncedTurnRatio = 0;
motor[LEFT] = 20;
Sleep(500);
nSyncedTurnRatio = 100;
Sleep(1000);
// turn right, drive
nSyncedTurnRatio = 0;
motor[LEFT] = 20;
Sleep(500);
nSyncedTurnRatio = 100;
Sleep(1000);
// turn left, resume
nSyncedTurnRatio = 0;
motor[LEFT] = 20;
Sleep(500);
motor[LEFT] = 0;
}
///////////////////////////////
void TurnBySteer(int d)
{
// normalize -100 100 to 0 200
nSyncedTurnRatio = d + 100;
}
///////////////////////////////
typedef enum programPhase { starting, searching, following, finished };
programPhase phase = starting;
// these 'tasks' are called from a loop, thus do not need to loop themselves
void initialize()
{
nSyncedTurnRatio = 50;
nSyncedMotors = synchBC;
motor[LEFT] = 30; // start a spiral drive
phase = searching;
}
void search()
{
if (light_value < 24)
{
nSyncedTurnRatio = 100;
phase = following;
}
}
int lastLight = -1;
int currentSteer = 0;
void follow()
{
// if it is solid white we have lost the line and must stop
// if lightSensors detects dark, we are on line
// if it got lighter, we are going more off line
// if it got darker we are headed in a good direction, slow down turn in anticipation
// +++PID will be even smoother
if (light_value > 64)
{
motor[LEFT] = 0;
phase = finished;
return;
}
if (light_value < 24)
currentSteer = 0;
else if (light_value > lastLight)
currentSteer += sgn(currentSteer) * 1;
else // implied (light_value < lastLight)
currentSteer -= sgn(currentSteer) * 1;
TurnBySteer(currentSteer);
}
bool regularProcessing_wantsToRun()
{
return phase != finished;
}
void regularProcessing_task()
{
switch (phase)
{
case starting:
initialize();
break;
case searching:
search();
break;
case following:
follow();
}
}
task main()
{
// subsumption tasks in priority oder
while (true)
{
// read sensors once per loop
distance_value = SensorValue[S_DISTANCE];
light_value = SensorValue[S_LIGHT];
if (evade_wantsToRun())
evade_task();
if (regularProcessing_wantsToRun())
regularProcessing_task();
else
StopAllTasks();
EndTimeSlice(); // give others a chance, but make it as short as possible
}
}
StartTask
, görevin önceliği midir? 9 en yüksek öncelik olacak mı? Bu durumda,find
önceliğinden daha fazla olmamalıdırtrack
? Aslında, durumufind
veelse
durumutrack
aynıdır. Yani, bir insan olarak, sensör değeri eşikten büyükse, ne yapardınız? Spira devam edin veya hattı ayarlamak için dönün?