Мелкие исправления, теоретически рабочие приоритеты операций, рефакторинг

This commit is contained in:
VladislavOstapov 2022-12-05 09:43:44 +03:00
parent 9faaacfd91
commit 3cd8f8369b
2 changed files with 253 additions and 172 deletions

View File

@ -102,7 +102,7 @@ static void emulate_robot(robot_code &code, robot_regs& r, char robot_id) {
case ROBOT_CMD_TMR_SET_code: case ROBOT_CMD_TMR_SET_code:
if (code.barrel_id >= 0) { 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; r.mz.is_up = 0;
} }
code.PC++; code.PC++;

View File

@ -177,9 +177,64 @@ struct scheduler_task {
short priority; // приоритет, чем больше тем выше, по умолчанию 0 short priority; // приоритет, чем больше тем выше, по умолчанию 0
}; };
// выставляет приоритет операции // выставляет приоритет операции (зависит только от зоны, в которой робот находится)
short get_operation_priority(short barrel_id) { 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; // task->priority = 0;
// switch (barrel_process) { // switch (barrel_process) {
@ -187,7 +242,7 @@ short get_operation_priority(short barrel_id) {
// break; // 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_degreasing = 12;
b.time_washing_1a = 4; b.time_washing_1a = 4;
b.time_washing_1b = 6; b.time_washing_1b = 6;
b.time_etching = 16; b.time_etching = 25;
b.time_washing_2a = 6; b.time_washing_2a = 6;
b.time_washing_2b = 8; b.time_washing_2b = 8;
b.time_galvanizing = 30; b.time_galvanizing = 60;
b.time_washing_3a = 8; b.time_washing_3a = 8;
b.time_washing_3b = 10; b.time_washing_3b = 10;
b.time_passivation = 3; 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) { 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; short left = -1, right = -1;
for (short i = 0; i < BARRELS_COUNT; i++) { 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; continue;
} }
// чтобы не получилось перемещать барабаны с приоритетом ниже
if (tasks[i].priority < max_priority) {
continue;
}
if (curr_pos <= target) { if (curr_pos <= target) {
// это таск справа, надо найти ближайший // это таск справа, надо найти ближайший
if (right == -1) { if (right == -1) {
@ -273,7 +346,7 @@ void debug_print_robot1_code() {
for (int i = 0; i < 16; i++) { for (int i = 0; i < 16; i++) {
const short cmd_arg = (short)(robot1_code.code[i] & (short)(~ROBOT_CMD_MASK)); 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) { if ((robot1_code.code[i] & ROBOT_CMD_MASK) == ROBOT_CMD_END_code) {
printf(" END\n"); printf(" END\n");
@ -341,65 +414,47 @@ void debug_print_robot1_code() {
} }
void schedule_robot_1() { void create_operation(const short target_task, const struct scheduler_task* tasks, struct robot_code* code, const short current_zone) {
// формируем список задач
struct scheduler_task tasks[BARRELS_COUNT];
for (short i = 0; i < BARRELS_COUNT; i++) {
// для каждой задачи:
tasks[i].start_zone = barrels[i].zone;
// определяем можно ли ее выполнить и что вообще нужно выполнить
tasks[i].dest_zone = can_move(barrels + i);
if (tasks[i].dest_zone >= 0) {
tasks[i].priority = get_operation_priority(i);
}
}
// 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; code->barrel_id = target_task;
short cmd_index = 0; short cmd_index = 0;
// первым делом добавляем команду опустить траверсу // первым делом добавляем команду опустить траверсу
robot1_code.code[cmd_index++] = ROBOT_CMD_DOWN(); code->code[cmd_index++] = ROBOT_CMD_DOWN();
if (tasks[target_task].dest_zone == ZONE_PASSIVATION) { if (tasks[target_task].dest_zone == ZONE_PASSIVATION) {
// пассивация, тут все просто // пассивация, тут все просто
if (robot1.dx.current_zone != tasks[target_task].start_zone) { if (current_zone != tasks[target_task].start_zone) {
robot1_code.code[cmd_index++] = ROBOT_CMD_MOVE_TO_ZONE(ZONE_WASHING_3B); code->code[cmd_index++] = ROBOT_CMD_MOVE_TO_ZONE(ZONE_WASHING_3B);
} }
robot1_code.code[cmd_index++] = ROBOT_CMD_UP_WITH_BARREL(); code->code[cmd_index++] = ROBOT_CMD_UP_WITH_BARREL();
robot1_code.code[cmd_index++] = ROBOT_CMD_MOVE_TO_ZONE_WITH_BARREL(ZONE_PASSIVATION); code->code[cmd_index++] = ROBOT_CMD_MOVE_TO_ZONE_WITH_BARREL(ZONE_PASSIVATION);
robot1_code.code[cmd_index++] = ROBOT_CMD_DOWN_WITH_BARREL(); code->code[cmd_index++] = ROBOT_CMD_DOWN_WITH_BARREL();
robot1_code.code[cmd_index++] = ROBOT_CMD_TMR_SET(barrels[target_task].time_passivation); code->code[cmd_index++] = ROBOT_CMD_TMR_SET(barrels[target_task].time_passivation);
robot1_code.code[cmd_index++] = ROBOT_CMD_UP_WITH_BARREL(); code->code[cmd_index++] = ROBOT_CMD_UP_WITH_BARREL();
robot1_code.code[cmd_index++] = ROBOT_CMD_MOVE_TO_ZONE_WITH_BARREL(ZONE_WASHING_4A); code->code[cmd_index++] = ROBOT_CMD_MOVE_TO_ZONE_WITH_BARREL(ZONE_WASHING_4A);
robot1_code.code[cmd_index++] = ROBOT_CMD_DOWN_WITH_BARREL(); code->code[cmd_index++] = ROBOT_CMD_DOWN_WITH_BARREL();
robot1_code.code[cmd_index++] = ROBOT_CMD_TMR_SET(barrels[target_task].time_washing_4a); code->code[cmd_index++] = ROBOT_CMD_TMR_SET(barrels[target_task].time_washing_4a);
} else { } else {
// любой другой случай // любой другой случай
if (robot1.dx.current_zone != tasks[target_task].start_zone) { if (current_zone != tasks[target_task].start_zone) {
if (tasks[target_task].start_zone != 22) { if (tasks[target_task].start_zone != 22) {
robot1_code.code[cmd_index++] = ROBOT_CMD_MOVE_TO_ZONE(tasks[target_task].start_zone); code->code[cmd_index++] = ROBOT_CMD_MOVE_TO_ZONE(tasks[target_task].start_zone);
} else { } else {
robot1_code.code[cmd_index++] = ROBOT_CMD_MOVE_OFF(); code->code[cmd_index++] = ROBOT_CMD_MOVE_OFF();
robot1_code.code[cmd_index++] = ROBOT_CMD_UP(); code->code[cmd_index++] = ROBOT_CMD_UP();
robot1_code.code[cmd_index++] = ROBOT_CMD_MOVE_TO_ZONE(22); code->code[cmd_index++] = ROBOT_CMD_MOVE_TO_ZONE(22);
robot1_code.code[cmd_index++] = ROBOT_CMD_MOVE_OFF(); code->code[cmd_index++] = ROBOT_CMD_MOVE_OFF();
robot1_code.code[cmd_index++] = ROBOT_CMD_DOWN(); code->code[cmd_index++] = ROBOT_CMD_DOWN();
robot1_code.code[cmd_index++] = ROBOT_CMD_MOVE_ACCURATE(); code->code[cmd_index++] = ROBOT_CMD_MOVE_ACCURATE();
} }
} }
robot1_code.code[cmd_index++] = ROBOT_CMD_UP_WITH_BARREL(); code->code[cmd_index++] = ROBOT_CMD_UP_WITH_BARREL();
// теперь надо определиться с тем, сколько ждать скапывания // теперь надо определиться с тем, сколько ждать скапывания
switch (tasks[target_task].start_zone) { switch (tasks[target_task].start_zone) {
@ -416,7 +471,7 @@ void schedule_robot_1() {
case ZONE_GALVANIZING_8: case ZONE_GALVANIZING_8:
// время скапывания реактивов // время скапывания реактивов
// TODO добавить переменные времен скапывания // TODO добавить переменные времен скапывания
robot1_code.code[cmd_index++] = ROBOT_CMD_WAIT(30); code->code[cmd_index++] = ROBOT_CMD_WAIT(30);
break; break;
case ZONE_WASHING_1A: case ZONE_WASHING_1A:
@ -424,7 +479,7 @@ void schedule_robot_1() {
case ZONE_WASHING_3A: case ZONE_WASHING_3A:
case ZONE_WASHING_4A: case ZONE_WASHING_4A:
// время скапывания 1-го каскада промывок // время скапывания 1-го каскада промывок
robot1_code.code[cmd_index++] = ROBOT_CMD_WAIT(3); code->code[cmd_index++] = ROBOT_CMD_WAIT(3);
break; break;
case ZONE_WASHING_1B: case ZONE_WASHING_1B:
@ -432,26 +487,26 @@ void schedule_robot_1() {
case ZONE_WASHING_3B: case ZONE_WASHING_3B:
case ZONE_WASHING_4B: case ZONE_WASHING_4B:
// время скапывания 2-го каскада промывок // время скапывания 2-го каскада промывок
robot1_code.code[cmd_index++] = ROBOT_CMD_WAIT(20); code->code[cmd_index++] = ROBOT_CMD_WAIT(20);
break; break;
} }
robot1_code.code[cmd_index++] = ROBOT_CMD_MOVE_TO_ZONE_WITH_BARREL(tasks[target_task].dest_zone); 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) { 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); 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) { } 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); code->code[cmd_index++] = ROBOT_CMD_INC_ZONE(ROBOT_ZONE_GAL);
} }
robot1_code.code[cmd_index++] = ROBOT_CMD_DOWN_WITH_BARREL(); code->code[cmd_index++] = ROBOT_CMD_DOWN_WITH_BARREL();
if (tasks[target_task].dest_zone == 22) { if (tasks[target_task].dest_zone == 22) {
robot1_code.code[cmd_index++] = ROBOT_CMD_MOVE_TO_ZONE(21); code->code[cmd_index++] = ROBOT_CMD_MOVE_TO_ZONE(21);
// NOTE старая механика не позволяет просто опустить траверсу до конца, для новой изменить поведение // NOTE старая механика не позволяет просто опустить траверсу до конца, для новой изменить поведение
robot1_code.code[cmd_index++] = ROBOT_CMD_UP(); code->code[cmd_index++] = ROBOT_CMD_UP();
robot1_code.code[cmd_index++] = ROBOT_CMD_DOWN(); code->code[cmd_index++] = ROBOT_CMD_DOWN();
} else { } else {
if (tasks[target_task].dest_zone != 0) { if (tasks[target_task].dest_zone != 0) {
@ -510,16 +565,40 @@ void schedule_robot_1() {
if (tmp > 8000) { if (tmp > 8000) {
tmp = 8000; tmp = 8000;
} }
robot1_code.code[cmd_index++] = ROBOT_CMD_TMR_SET(tmp); code->code[cmd_index++] = ROBOT_CMD_TMR_SET(tmp);
} }
} }
} }
} }
robot1_code.code[cmd_index++] = ROBOT_CMD_END(); code->code[cmd_index++] = ROBOT_CMD_END();
robot1_code.PC = 0; code->PC = 0;
printf("INFO: code length is %d\n", cmd_index); printf("INFO: code length is %d\n", cmd_index);
}
void schedule_robot_1() {
// формируем список задач
struct scheduler_task tasks[BARRELS_COUNT];
for (short i = 0; i < BARRELS_COUNT; i++) {
// для каждой задачи:
tasks[i].start_zone = barrels[i].zone;
// определяем можно ли ее выполнить и что вообще нужно выполнить
tasks[i].dest_zone = can_move(barrels + i);
if (tasks[i].dest_zone >= 0) {
tasks[i].priority = get_operation_priority(i);
}
}
// TODO добавить вставку lock-point'ов на задачах на несколько роботов
// найти подходящую задачу
if (schedulerOneRobotMode) {
short target_task = scheduler_find_task(tasks, robot1.dx.current_zone);
if (target_task >= 0) {
create_operation(target_task, tasks, &robot1_code, robot1.dx.current_zone);
debug_print_robot1_code(); debug_print_robot1_code();
} }
} else { } else {
@ -528,13 +607,15 @@ void schedule_robot_1() {
} }
// вернет false если удалось вставить барабан, иначе true // вернет false если удалось вставить барабан, иначе true
char create_barrel_in_load(short zone) { char create_barrel_in_load() {
if (!zone_is_busy(1)) {
for (int i = 0; i < BARRELS_COUNT; i++) { for (int i = 0; i < BARRELS_COUNT; i++) {
if (!barrels[i].flags.is_exist) { if (!barrels[i].flags.is_exist) {
barrels[i] = makeBarrel(1, zone, 0); barrels[i] = makeBarrel(1, 1, 0);
return 0; return 0;
} }
} }
}
return 1; return 1;
} }
@ -588,7 +669,7 @@ void scheduler_main() {
// тут возможна только вставка барабанов // тут возможна только вставка барабанов
if (schedulerLoadButton2) { if (schedulerLoadButton2) {
schedulerLoadButton2 = create_barrel_in_load(1); schedulerLoadButton2 = create_barrel_in_load();
} }
if (schedulerSoftwareTimer) { if (schedulerSoftwareTimer) {