Cách chính xác để sử dụng Kiến trúc dự phòng với Robot C


11

Gần đây tôi đã đọc rất nhiều về Kiến trúc dự phòng và có một vài cách khác nhau mà mọi người dường như ủng hộ.

Ví dụ, một số người sử dụng biến "cờ" toàn cầu để kiểm soát nhiệm vụ. Những người khác sử dụng endTimeSlice()và cho phép trọng tài thực sự lựa chọn. Và tôi nghĩ điều này là chính xác.

Tôi có một phần nhỏ mã RobotC mà tôi đang làm việc cho một dòng theo robot nhưng tôi không chắc là tôi đang làm đúng vì hiện tại phương thức theo dõi sẽ luôn chiếm phương thức tìm kiếm. Luồng chính xác phải là tìm thấy nên hướng dẫn robot đến đường bằng cách sử dụng đường xoắn ốc để tìm đường. Một khi dòng được tìm thấy theo dõi nên tiếp quản.

task evade(){
    if(SensorValue(forwardSonarSensor) > threshold){
            //box the obstruction
    }
}

task find(){
    if(SensorValue(lightSensor) > threshold){
            //spiral the robot
    }
}

task track(){

    if(SensorValue(lightSensor) < threshold){
            //go straight
    }else{
                //execute turns to follow the line
    }
}

task main(){
    while(true){
        StartTask(evade,9);
        StartTask(track,8);
        StartTask(find,7);
        wait1Msec(250);
    }
}

Tôi chỉ sử dụng một số ý kiến ​​ở đây thay vì mã thực tế để giữ cho nó ngắn gọn. Là câu lệnh if của tôi không đủ tốt như điều kiện bởi vì khi robot ra khỏi dòng, track()sẽ tiếp quản. Đây có phải là do tuyên bố khác trong theo dõi? Nếu vậy, làm thế nào để track()thực hiện lần lượt khi nó mất dòng mà không tiếp quản thức ăn khi bắt đầu chương trình?


1
Những con số bạn đưa ra StartTask, chúng có phải là ưu tiên của nhiệm vụ? Là 9 sẽ là ưu tiên cao nhất? Trong trường hợp đó, không nên findcó nhiều ưu tiên hơn track? Trong thực tế, điều kiện findelseđiều kiện tracklà như nhau. Vì vậy, là một con người, nếu giá trị cảm biến lớn hơn ngưỡng, bạn sẽ làm gì? Đi trên xoắn ốc hoặc biến để điều chỉnh dòng?
Shahbaz

Tôi biết kiến ​​trúc phụ là gì và tôi chắc chắn rằng robot của bạn sẽ có các mô-đun phần cứng khác nhau chịu trách nhiệm cho các nhiệm vụ tính toán cấp thấp. Và rằng mã thực sự nên hấp thụ tín hiệu thay vì chỉ nghe trạng thái có điều kiện. Vì vậy, bạn không nên truyền tín hiệu vào một phần cứng khác? Bây giờ vấn đề của tôi là tôi có hai Arduinos và tôi muốn Arduino A thu lại hoặc ức chế tín hiệu từ Arduino B. Có ai có bất kỳ ý tưởng làm thế nào điều này được thực hiện? Vì tôi có thể kết nối Arduino A để gửi tín hiệu đến Arduino B nhưng tôi không chắc làm thế nào để giảm bớt hoặc ức chế sig
Ambient Soda

Câu trả lời:


7

Với Kiến trúc phụ, bạn nên thiết kế cẩn thận các hành vi của mình theo cách mà nếu bạn chỉ định Tmức độ ưu tiên của nhiệm vụ n, thì đó Tsẽ là những gì robot nên làm nếu tất cả các nhiệm vụ có mức độ ưu tiên cao hơn nbị bỏ qua.

Hãy đặt hàng các nhiệm vụ ví dụ của bạn, sau đó tìm ra cách để thực hiện nó. Nhiệm vụ của bạn là evade, findtrack.

Nói chung, bạn sẽ muốn robot theo dõi một dòng. Tuy nhiên, nếu nó không thể phát hiện ra dòng, thì nó nên cố gắng tìm nó. Trên hết, nó nên trốn tránh những trở ngại. Điều này cho chúng tôi thứ tự sau đây:

  • Mức ưu tiên cao nhất: evade
  • Sau đó: find
  • Sau đó: track

Lý do findcó mức độ ưu tiên cao hơn tracklà, như tôi đã đề cập ở trên, bạn sẽ trackchỉ khi evadefindkhông cần thiết. Nếu bạn đặt findbên dưới track, điều đó có nghĩa là bạn bắt đầu theo dõi nếu không có chướng ngại vật, ngay cả khi bạn không ở trên đường.

Bây giờ hãy xem việc thực hiện của bạn:

task find(){
    if(SensorValue(lightSensor) > threshold){
            //spiral the robot
    }
}

task track(){

    if(SensorValue(lightSensor) < threshold){
            //go straight
    }else{
                //execute turns to follow the line
    }
}

Hãy nhớ rằng chúng tôi đã findưu tiên cao hơn. Do đó, nếu robot không thể cảm nhận được lightSensor, nó sẽ đi theo hình xoắn ốc cố gắng tìm dòng. Một khi nó xảy ra, trackđá vào. Như bạn có thể thấy, elseđiều kiện trackkhông bao giờ xảy ra.

Trong khi điều này hoạt động, robot sẽ di chuyển rất lúng túng. Thực tế không có nhiều thứ bạn có thể làm về nó, dựa trên bản dựng hiện tại của robot của bạn.


Mặc dù tôi đã trả lời câu hỏi của bạn, nhưng đây là một cải tiến đơn giản để theo dõi dòng của bạn:

Thay vì một cảm biến ánh sáng, sử dụng hai; ls_leftls_right . Sử dụng (ít nhất) hai cảm biến, bạn có thể hiểu liệu bạn hoàn toàn không theo dõi hay sắp ra khỏi đường đua. Trong trường hợp thứ hai, bạn có thể dễ dàng chuyển sang hướng thích hợp và quay lại theo dõi.

findNhiệm vụ của bạn là tương tự:

task find(){
    if (SensorValue(ls_left) > threshold
        && Sensorvalue(ls_right) > threshold){
            //spiral the robot
    }
}

Đó là, bạn đi theo hình xoắn ốc chỉ khi bạn không cảm thấy gì cả

trackNhiệm vụ của bạn bây giờ trở nên hiệu quả hơn:

task track(){

    if (SensorValue(ls_left) < threshold
        && SensorValue(ls_right) < threshold){
            //go straight
    } else if (SensorValue(ls_left) < threshold
        && SensorValue(ls_right) > threshold){
            //turn left
    } else if (SensorValue(ls_left) > threshold
        && SensorValue(ls_right) < threshold){
            //turn right
    } else {
            // shouldn't happen, but go on spiral anyway
    }
}

Rõ ràng, với một ma trận các cảm biến ánh sáng, bạn có thể đánh giá tốt hơn mức độ bạn đang đi sai đường (nghĩa là với góc nào) và quyết định tốt hơn làm thế nào để quay lại theo dõi (tức là với tốc độ góc nào).


4

câu trả lời ngắn; không, bạn thực sự cần phải làm mọi thứ khá khác một chút.

câu trả lời dài không đầy đủ; Hãy để tôi cung cấp cho bạn một số mã psuedo thích hợp cho robotC, điều đó đưa bạn đến một con đường tốt hơn. Đầu tiên, không sử dụng các tác vụ - đây KHÔNG phải là nhiệm vụ của robotC dành cho. Chúng có thể được tạo ra để hoạt động, có thể, có thể không (và bạn cần khá nhiều thay đổi để thậm chí thử).

// 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();   
   }
}

Có một vài điều ở đây; ưu tiên trở nên không liên quan. Mặc dù có vẻ như có các nhiệm vụ trong robotC với các ưu tiên, nhưng chúng không phải là một lựa chọn tốt để thực hiện trợ cấp theo kinh nghiệm của tôi. Vì những lý do như, các ưu tiên không phải lúc nào cũng được tôn trọng, các nhiệm vụ không thể bị gián đoạn (đôi khi) vì vậy khi xảy ra sự kiện ưu tiên cao hơn, nó sẽ không phản ứng như bạn mong đợi, robotC chỉ mới được đăng ký lại, vì vậy những thứ như truy cập vào cảm biến từ hơn 1 nhiệm vụ có thể có rủi ro (vấn đề thời gian I2C) và trong một số trường hợp không phải là (cảm biến được thăm dò tự động).

Bạn có thể thêm triển khai ưu tiên của riêng mình vào vòng lặp ở trên khi bạn làm mọi thứ hoạt động, nhưng nó thực sự không cần thiết để bắt đầu.

Nhận xét của bạn "// hộp vật cản" mô tả hành vi đạn đạo. Đó là một chút khó khăn để thực hiện bằng cách sử dụng đa tác vụ. Vòng lặp đơn giản mà tôi đã sử dụng làm cho nó dễ dàng hơn nhiều và tốt hơn cho người mới bắt đầu / học tập.

Một điều khác tôi sẽ để lại cho bạn, đó là sự phụ thuộc trong khi gọn gàng và phù hợp với nhiều thứ, không phải là một cách tốt để thực hiện những gì được thực hiện tốt hơn theo truyền thống. Thật vậy, phần 'trốn tránh' có thể là một ứng cử viên tốt cho việc trợ cấp, nhưng thành thật mà nói, nhiệm vụ khác của bạn nên được gọi là 'GoOnTheYourBusiness'. Tôi nói điều này bởi vì có lẽ bạn không muốn thay đổi từ tìm kiếm sang theo dõi với sự sụt giảm. Xử lý những người có vòng lặp lập trình truyền thống. Với một cảm biến duy nhất, - ánh sáng được cảm nhận tối hơn hoặc sáng hơn so với vòng lặp trước? nếu trời tối hơn (giả sử đường màu đen) tiếp tục quay cùng hướng, nếu trời sáng hơn thì rẽ theo hướng khác, nếu nó giữ nguyên, hãy đi thẳng. Bạn có thể cần phải thêm một số PID và sử dụng đường cong lái thay vì chỉ rẽ trái và phải để mượt mà hơn.

Và có, nhiều cảm biến giúp. http://www.mindsensors.com/ - vâng, đó là tôi trong phim hiện tại (11/10/2012)

Cập nhật: mã thực tế

Tôi sẽ thử điều này trong một thời gian ngắn, nhưng nó biên dịch và minh họa những gì tôi đã viết ở trên:

#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
    }
}

Tôi đồng ý rằng vấn đề này được giải quyết dễ dàng hơn với một vòng lặp đơn giản. Tôi không hiểu tại sao mọi người sẽ đánh giá thấp điều này.
Shahbaz

Tôi không muốn để lại ấn tượng rằng việc giải quyết dễ dàng hơn với một vòng lặp đơn giản, mà là ấn tượng rằng đó là cách sử dụng chính xác để sử dụng một vòng lặp đơn giản như một trong những nhiệm vụ. Bất cứ ai hạ cấp nó đều có điểm mod, và không hiểu gì về sự sụt giảm. Bạn sẽ không thấy rằng không có nhiều người thực hiện việc trợ cấp cho LEGO NXT (ngụ ý bằng cách sử dụng robotC), vì vậy đừng hy vọng mã sẽ có sẵn để được dán.
Spiked3

Vâng, tôi tự hỏi tại sao OP lại sử dụng các tác vụ cho một thứ đơn giản như là sự sụt giảm.
Rocketmagnet

Bởi vì đó là một lỗi rất rất rất rất rất phổ biến đối với người mới bắt đầu với robotC - để thử và sử dụng các tác vụ cho mọi thứ. Tôi ước họ sẽ chuyển nó đến một khu vực duy nhất tiên tiến.
Spiked3
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.