From 3cd8f8369b07405bc9695e4bce0076d804afec27 Mon Sep 17 00:00:00 2001 From: VladislavOstapov Date: Mon, 5 Dec 2022 09:43:44 +0300 Subject: [PATCH] =?UTF-8?q?=D0=9C=D0=B5=D0=BB=D0=BA=D0=B8=D0=B5=20=D0=B8?= =?UTF-8?q?=D1=81=D0=BF=D1=80=D0=B0=D0=B2=D0=BB=D0=B5=D0=BD=D0=B8=D1=8F,?= =?UTF-8?q?=20=D1=82=D0=B5=D0=BE=D1=80=D0=B5=D1=82=D0=B8=D1=87=D0=B5=D1=81?= =?UTF-8?q?=D0=BA=D0=B8=20=D1=80=D0=B0=D0=B1=D0=BE=D1=87=D0=B8=D0=B5=20?= =?UTF-8?q?=D0=BF=D1=80=D0=B8=D0=BE=D1=80=D0=B8=D1=82=D0=B5=D1=82=D1=8B=20?= =?UTF-8?q?=D0=BE=D0=BF=D0=B5=D1=80=D0=B0=D1=86=D0=B8=D0=B9,=20=D1=80?= =?UTF-8?q?=D0=B5=D1=84=D0=B0=D0=BA=D1=82=D0=BE=D1=80=D0=B8=D0=BD=D0=B3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- robot.cpp | 2 +- scheduler.c | 423 +++++++++++++++++++++++++++++++--------------------- 2 files changed, 253 insertions(+), 172 deletions(-) diff --git a/robot.cpp b/robot.cpp index cf95892..fda3a6d 100644 --- a/robot.cpp +++ b/robot.cpp @@ -102,7 +102,7 @@ static void emulate_robot(robot_code &code, robot_regs& r, char robot_id) { case ROBOT_CMD_TMR_SET_code: if (code.barrel_id >= 0) { - barrels[code.barrel_id].software_timer = code.code[code.PC]; + barrels[code.barrel_id].software_timer = cmd_arg; r.mz.is_up = 0; } code.PC++; diff --git a/scheduler.c b/scheduler.c index f4012ad..c3c4a48 100644 --- a/scheduler.c +++ b/scheduler.c @@ -177,9 +177,64 @@ struct scheduler_task { short priority; // приоритет, чем больше тем выше, по умолчанию 0 }; -// выставляет приоритет операции +// выставляет приоритет операции (зависит только от зоны, в которой робот находится) short get_operation_priority(short barrel_id) { // сделать приоритет на барабан, который больше всего ждет + if (barrels[barrel_id].zone >= ZONE_GALVANIZING_1 && barrels[barrel_id].zone <= ZONE_GALVANIZING_8) { + // теперь надо выяснить, есть ли барабаны с большим временем ожидания + // тут возможны несколько случаев: + // 1) когда барабан один такой (больше в цинковании нет барабанов чтобы их изъять), + // 2) когда барабанов несколько, соотвественно если есть барабан с наибольшим временем, то надо ему дать приоритет 1, а остальным 0, + // + + char is_not_one = 0; + char is_with_max_time = 1; + + for (short i = 0; i < BARRELS_COUNT; i++) { + if (i == barrel_id) { + continue; + } + if (barrels[i].flags.is_exist && barrels[i].zone >= ZONE_GALVANIZING_1 && barrels[i].zone <= ZONE_GALVANIZING_8) { + if (can_move(barrels + i) >= 0) { + is_not_one = 1; + if (barrels[i].software_timer > barrels[barrel_id].software_timer) { + is_with_max_time = 0; + break; + } + } + } + if (is_not_one == 0) { + return 1; + } + return is_with_max_time; + + } + return 0; + } + + + // теперь то же самое, только для травления (только тут задача проще потому что травления всего 2 зоны, и надо только один барабан если он есть) + if (barrels[barrel_id].zone >= ZONE_ETCHING_1 && barrels[barrel_id].zone <= ZONE_ETCHING_2) { + + for (short i = 0; i < BARRELS_COUNT; i++) { + if (i == barrel_id) { + continue; + } + + if (barrels[i].flags.is_exist && barrels[i].zone >= ZONE_ETCHING_1 && barrels[i].zone <= ZONE_ETCHING_2) { + if (can_move(barrels + i) >= 0) { + if (barrels[i].software_timer > barrels[barrel_id].software_timer) { + return 0; // у этого барабана меньше время операции, так что приоритет ему 0 + } else { + return 1; // поскольку у нашего барабана максимальное время ожидания + } + } + } + // барабан не найден, приоритет ему 1 + return 1; + } + return 0; + } // task->priority = 0; // switch (barrel_process) { @@ -187,7 +242,7 @@ short get_operation_priority(short barrel_id) { // break; // } - return 0; + return 1; // 1 - нормальный приоритет } @@ -199,10 +254,10 @@ struct barrel makeBarrel(short flags, short zone, short timer) { b.time_degreasing = 12; b.time_washing_1a = 4; b.time_washing_1b = 6; - b.time_etching = 16; + b.time_etching = 25; b.time_washing_2a = 6; b.time_washing_2b = 8; - b.time_galvanizing = 30; + b.time_galvanizing = 60; b.time_washing_3a = 8; b.time_washing_3b = 10; b.time_passivation = 3; @@ -213,6 +268,19 @@ struct barrel makeBarrel(short flags, short zone, short timer) { static short scheduler_find_task(struct scheduler_task* tasks, const short curr_pos) { + // TODO добавить поддержку ночного режима и режима двух роботов + // для начала надо найти максимальный приоритет у операций + short max_priority = -1; + for (short i = 0; i < BARRELS_COUNT; i++) { + if (tasks[i].priority > max_priority) { + max_priority = tasks[i].priority; + } + } + + if (max_priority < 0) { + return -1; // тасков нет) + } + // ищем первый барабан слева, и ближайший справа short left = -1, right = -1; for (short i = 0; i < BARRELS_COUNT; i++) { @@ -223,6 +291,11 @@ static short scheduler_find_task(struct scheduler_task* tasks, const short curr_ continue; } + // чтобы не получилось перемещать барабаны с приоритетом ниже + if (tasks[i].priority < max_priority) { + continue; + } + if (curr_pos <= target) { // это таск справа, надо найти ближайший if (right == -1) { @@ -273,7 +346,7 @@ void debug_print_robot1_code() { for (int i = 0; i < 16; i++) { const short cmd_arg = (short)(robot1_code.code[i] & (short)(~ROBOT_CMD_MASK)); - printf(" %3d: 0x%04X", i, robot1_code.code[i] & 0xFFFF); + printf(" %3d 0x%04X", i, robot1_code.code[i] & 0xFFFF); if ((robot1_code.code[i] & ROBOT_CMD_MASK) == ROBOT_CMD_END_code) { printf(" END\n"); @@ -341,6 +414,170 @@ void debug_print_robot1_code() { } +void create_operation(const short target_task, const struct scheduler_task* tasks, struct robot_code* code, const short current_zone) { + // создаем код транзакции, пока обычный + code->barrel_id = target_task; + short cmd_index = 0; + + // первым делом добавляем команду опустить траверсу + code->code[cmd_index++] = ROBOT_CMD_DOWN(); + + if (tasks[target_task].dest_zone == ZONE_PASSIVATION) { + // пассивация, тут все просто + if (current_zone != tasks[target_task].start_zone) { + code->code[cmd_index++] = ROBOT_CMD_MOVE_TO_ZONE(ZONE_WASHING_3B); + } + + code->code[cmd_index++] = ROBOT_CMD_UP_WITH_BARREL(); + code->code[cmd_index++] = ROBOT_CMD_MOVE_TO_ZONE_WITH_BARREL(ZONE_PASSIVATION); + code->code[cmd_index++] = ROBOT_CMD_DOWN_WITH_BARREL(); + + code->code[cmd_index++] = ROBOT_CMD_TMR_SET(barrels[target_task].time_passivation); + + code->code[cmd_index++] = ROBOT_CMD_UP_WITH_BARREL(); + code->code[cmd_index++] = ROBOT_CMD_MOVE_TO_ZONE_WITH_BARREL(ZONE_WASHING_4A); + code->code[cmd_index++] = ROBOT_CMD_DOWN_WITH_BARREL(); + + code->code[cmd_index++] = ROBOT_CMD_TMR_SET(barrels[target_task].time_washing_4a); + } else { + // любой другой случай + if (current_zone != tasks[target_task].start_zone) { + if (tasks[target_task].start_zone != 22) { + code->code[cmd_index++] = ROBOT_CMD_MOVE_TO_ZONE(tasks[target_task].start_zone); + } else { + code->code[cmd_index++] = ROBOT_CMD_MOVE_OFF(); + code->code[cmd_index++] = ROBOT_CMD_UP(); + code->code[cmd_index++] = ROBOT_CMD_MOVE_TO_ZONE(22); + code->code[cmd_index++] = ROBOT_CMD_MOVE_OFF(); + code->code[cmd_index++] = ROBOT_CMD_DOWN(); + code->code[cmd_index++] = ROBOT_CMD_MOVE_ACCURATE(); + } + } + + code->code[cmd_index++] = ROBOT_CMD_UP_WITH_BARREL(); + + // теперь надо определиться с тем, сколько ждать скапывания + switch (tasks[target_task].start_zone) { + case ZONE_DEGREASING: + case ZONE_ETCHING_1: + case ZONE_ETCHING_2: + case ZONE_GALVANIZING_1: + case ZONE_GALVANIZING_2: + case ZONE_GALVANIZING_3: + case ZONE_GALVANIZING_4: + case ZONE_GALVANIZING_5: + case ZONE_GALVANIZING_6: + case ZONE_GALVANIZING_7: + case ZONE_GALVANIZING_8: + // время скапывания реактивов + // TODO добавить переменные времен скапывания + code->code[cmd_index++] = ROBOT_CMD_WAIT(30); + break; + + case ZONE_WASHING_1A: + case ZONE_WASHING_2A: + case ZONE_WASHING_3A: + case ZONE_WASHING_4A: + // время скапывания 1-го каскада промывок + code->code[cmd_index++] = ROBOT_CMD_WAIT(3); + break; + + case ZONE_WASHING_1B: + case ZONE_WASHING_2B: + case ZONE_WASHING_3B: + case ZONE_WASHING_4B: + // время скапывания 2-го каскада промывок + code->code[cmd_index++] = ROBOT_CMD_WAIT(20); + break; + } + + code->code[cmd_index++] = ROBOT_CMD_MOVE_TO_ZONE_WITH_BARREL(tasks[target_task].dest_zone); + + // инкремент зоны (если травление или цинкование) + if (tasks[target_task].dest_zone == ZONE_ETCHING_1 || tasks[target_task].dest_zone == ZONE_ETCHING_2) { + code->code[cmd_index++] = ROBOT_CMD_INC_ZONE(ROBOT_ZONE_ETCH); + } else if (tasks[target_task].dest_zone >= ZONE_GALVANIZING_1 && tasks[target_task].dest_zone <= ZONE_GALVANIZING_8) { + code->code[cmd_index++] = ROBOT_CMD_INC_ZONE(ROBOT_ZONE_GAL); + } + + code->code[cmd_index++] = ROBOT_CMD_DOWN_WITH_BARREL(); + + if (tasks[target_task].dest_zone == 22) { + code->code[cmd_index++] = ROBOT_CMD_MOVE_TO_ZONE(21); + // NOTE старая механика не позволяет просто опустить траверсу до конца, для новой изменить поведение + code->code[cmd_index++] = ROBOT_CMD_UP(); + code->code[cmd_index++] = ROBOT_CMD_DOWN(); + } else { + + if (tasks[target_task].dest_zone != 0) { + + // установка времени ожидания барабана + short tmp = -1; + switch (tasks[target_task].dest_zone) { + case ZONE_DEGREASING: + tmp = barrels[target_task].time_degreasing; + break; + + case ZONE_ETCHING_1: + case ZONE_ETCHING_2: + tmp = barrels[target_task].time_etching; + break; + + case ZONE_GALVANIZING_1: + case ZONE_GALVANIZING_2: + case ZONE_GALVANIZING_3: + case ZONE_GALVANIZING_4: + case ZONE_GALVANIZING_5: + case ZONE_GALVANIZING_6: + case ZONE_GALVANIZING_7: + case ZONE_GALVANIZING_8: + tmp = barrels[target_task].time_galvanizing; + break; + + case ZONE_WASHING_1A: + tmp = barrels[target_task].time_washing_1a; + break; + case ZONE_WASHING_2A: + tmp = barrels[target_task].time_washing_2a; + break; + case ZONE_WASHING_3A: + tmp = barrels[target_task].time_washing_3a; + break; + case ZONE_WASHING_4A: + tmp = barrels[target_task].time_washing_4a; + break; + + case ZONE_WASHING_1B: + tmp = barrels[target_task].time_washing_1b; + break; + case ZONE_WASHING_2B: + tmp = barrels[target_task].time_washing_2b; + break; + case ZONE_WASHING_3B: + tmp = barrels[target_task].time_washing_3b; + break; + case ZONE_WASHING_4B: + tmp = barrels[target_task].time_washing_4b; + break; + } + + if (tmp > 0) { + if (tmp > 8000) { + tmp = 8000; + } + code->code[cmd_index++] = ROBOT_CMD_TMR_SET(tmp); + } + } + } + } + + code->code[cmd_index++] = ROBOT_CMD_END(); + code->PC = 0; + + printf("INFO: code length is %d\n", cmd_index); +} + + void schedule_robot_1() { // формируем список задач struct scheduler_task tasks[BARRELS_COUNT]; @@ -355,171 +592,13 @@ void schedule_robot_1() { } // TODO добавить вставку lock-point'ов на задачах на несколько роботов + // найти подходящую задачу if (schedulerOneRobotMode) { short target_task = scheduler_find_task(tasks, robot1.dx.current_zone); if (target_task >= 0) { - // создаем код транзакции, пока обычный - robot1_code.barrel_id = target_task; - short cmd_index = 0; - - // первым делом добавляем команду опустить траверсу - robot1_code.code[cmd_index++] = ROBOT_CMD_DOWN(); - - if (tasks[target_task].dest_zone == ZONE_PASSIVATION) { - // пассивация, тут все просто - if (robot1.dx.current_zone != tasks[target_task].start_zone) { - robot1_code.code[cmd_index++] = ROBOT_CMD_MOVE_TO_ZONE(ZONE_WASHING_3B); - } - - robot1_code.code[cmd_index++] = ROBOT_CMD_UP_WITH_BARREL(); - robot1_code.code[cmd_index++] = ROBOT_CMD_MOVE_TO_ZONE_WITH_BARREL(ZONE_PASSIVATION); - robot1_code.code[cmd_index++] = ROBOT_CMD_DOWN_WITH_BARREL(); - - robot1_code.code[cmd_index++] = ROBOT_CMD_TMR_SET(barrels[target_task].time_passivation); - - robot1_code.code[cmd_index++] = ROBOT_CMD_UP_WITH_BARREL(); - robot1_code.code[cmd_index++] = ROBOT_CMD_MOVE_TO_ZONE_WITH_BARREL(ZONE_WASHING_4A); - robot1_code.code[cmd_index++] = ROBOT_CMD_DOWN_WITH_BARREL(); - - robot1_code.code[cmd_index++] = ROBOT_CMD_TMR_SET(barrels[target_task].time_washing_4a); - } else { - // любой другой случай - if (robot1.dx.current_zone != tasks[target_task].start_zone) { - if (tasks[target_task].start_zone != 22) { - robot1_code.code[cmd_index++] = ROBOT_CMD_MOVE_TO_ZONE(tasks[target_task].start_zone); - } else { - robot1_code.code[cmd_index++] = ROBOT_CMD_MOVE_OFF(); - robot1_code.code[cmd_index++] = ROBOT_CMD_UP(); - robot1_code.code[cmd_index++] = ROBOT_CMD_MOVE_TO_ZONE(22); - robot1_code.code[cmd_index++] = ROBOT_CMD_MOVE_OFF(); - robot1_code.code[cmd_index++] = ROBOT_CMD_DOWN(); - robot1_code.code[cmd_index++] = ROBOT_CMD_MOVE_ACCURATE(); - } - } - - robot1_code.code[cmd_index++] = ROBOT_CMD_UP_WITH_BARREL(); - - // теперь надо определиться с тем, сколько ждать скапывания - switch (tasks[target_task].start_zone) { - case ZONE_DEGREASING: - case ZONE_ETCHING_1: - case ZONE_ETCHING_2: - case ZONE_GALVANIZING_1: - case ZONE_GALVANIZING_2: - case ZONE_GALVANIZING_3: - case ZONE_GALVANIZING_4: - case ZONE_GALVANIZING_5: - case ZONE_GALVANIZING_6: - case ZONE_GALVANIZING_7: - case ZONE_GALVANIZING_8: - // время скапывания реактивов - // TODO добавить переменные времен скапывания - robot1_code.code[cmd_index++] = ROBOT_CMD_WAIT(30); - break; - - case ZONE_WASHING_1A: - case ZONE_WASHING_2A: - case ZONE_WASHING_3A: - case ZONE_WASHING_4A: - // время скапывания 1-го каскада промывок - robot1_code.code[cmd_index++] = ROBOT_CMD_WAIT(3); - break; - - case ZONE_WASHING_1B: - case ZONE_WASHING_2B: - case ZONE_WASHING_3B: - case ZONE_WASHING_4B: - // время скапывания 2-го каскада промывок - robot1_code.code[cmd_index++] = ROBOT_CMD_WAIT(20); - break; - } - - robot1_code.code[cmd_index++] = ROBOT_CMD_MOVE_TO_ZONE_WITH_BARREL(tasks[target_task].dest_zone); - - // инкремент зоны (если травление или цинкование) - if (tasks[target_task].dest_zone == ZONE_ETCHING_1 || tasks[target_task].dest_zone == ZONE_ETCHING_2) { - robot1_code.code[cmd_index++] = ROBOT_CMD_INC_ZONE(ROBOT_ZONE_ETCH); - } else if (tasks[target_task].dest_zone >= ZONE_GALVANIZING_1 && tasks[target_task].dest_zone <= ZONE_GALVANIZING_8) { - robot1_code.code[cmd_index++] = ROBOT_CMD_INC_ZONE(ROBOT_ZONE_GAL); - } - - robot1_code.code[cmd_index++] = ROBOT_CMD_DOWN_WITH_BARREL(); - - if (tasks[target_task].dest_zone == 22) { - robot1_code.code[cmd_index++] = ROBOT_CMD_MOVE_TO_ZONE(21); - // NOTE старая механика не позволяет просто опустить траверсу до конца, для новой изменить поведение - robot1_code.code[cmd_index++] = ROBOT_CMD_UP(); - robot1_code.code[cmd_index++] = ROBOT_CMD_DOWN(); - } else { - - if (tasks[target_task].dest_zone != 0) { - - // установка времени ожидания барабана - short tmp = -1; - switch (tasks[target_task].dest_zone) { - case ZONE_DEGREASING: - tmp = barrels[target_task].time_degreasing; - break; - - case ZONE_ETCHING_1: - case ZONE_ETCHING_2: - tmp = barrels[target_task].time_etching; - break; - - case ZONE_GALVANIZING_1: - case ZONE_GALVANIZING_2: - case ZONE_GALVANIZING_3: - case ZONE_GALVANIZING_4: - case ZONE_GALVANIZING_5: - case ZONE_GALVANIZING_6: - case ZONE_GALVANIZING_7: - case ZONE_GALVANIZING_8: - tmp = barrels[target_task].time_galvanizing; - break; - - case ZONE_WASHING_1A: - tmp = barrels[target_task].time_washing_1a; - break; - case ZONE_WASHING_2A: - tmp = barrels[target_task].time_washing_2a; - break; - case ZONE_WASHING_3A: - tmp = barrels[target_task].time_washing_3a; - break; - case ZONE_WASHING_4A: - tmp = barrels[target_task].time_washing_4a; - break; - - case ZONE_WASHING_1B: - tmp = barrels[target_task].time_washing_1b; - break; - case ZONE_WASHING_2B: - tmp = barrels[target_task].time_washing_2b; - break; - case ZONE_WASHING_3B: - tmp = barrels[target_task].time_washing_3b; - break; - case ZONE_WASHING_4B: - tmp = barrels[target_task].time_washing_4b; - break; - } - - if (tmp > 0) { - if (tmp > 8000) { - tmp = 8000; - } - robot1_code.code[cmd_index++] = ROBOT_CMD_TMR_SET(tmp); - } - } - } - } - - robot1_code.code[cmd_index++] = ROBOT_CMD_END(); - robot1_code.PC = 0; - - printf("INFO: code length is %d\n", cmd_index); + create_operation(target_task, tasks, &robot1_code, robot1.dx.current_zone); debug_print_robot1_code(); } } else { @@ -528,11 +607,13 @@ void schedule_robot_1() { } // вернет false если удалось вставить барабан, иначе true -char create_barrel_in_load(short zone) { - for (int i = 0; i < BARRELS_COUNT; i++) { - if (!barrels[i].flags.is_exist) { - barrels[i] = makeBarrel(1, zone, 0); - return 0; +char create_barrel_in_load() { + if (!zone_is_busy(1)) { + for (int i = 0; i < BARRELS_COUNT; i++) { + if (!barrels[i].flags.is_exist) { + barrels[i] = makeBarrel(1, 1, 0); + return 0; + } } } return 1; @@ -588,7 +669,7 @@ void scheduler_main() { // тут возможна только вставка барабанов if (schedulerLoadButton2) { - schedulerLoadButton2 = create_barrel_in_load(1); + schedulerLoadButton2 = create_barrel_in_load(); } if (schedulerSoftwareTimer) {