diff --git a/executor/executor.c b/executor/executor.c index 2075e1c4..e1b96df6 100644 --- a/executor/executor.c +++ b/executor/executor.c @@ -195,77 +195,56 @@ static void executor_init(char* student_code) { * 3: Timed out by executor * 4: Unable to find the given function in the student code */ -static uint8_t run_py_function(const char* func_name, struct timespec* timeout, int loop, PyObject* args, PyObject** py_ret) { +static uint8_t run_py_function(const char* func_name, struct timespec* timeout, PyObject* args, PyObject** py_ret) { uint8_t ret = 0; // retrieve the Python function from the student code PyObject* pFunc = PyObject_GetAttrString(pModule, func_name); PyObject* pValue = NULL; + log_printf(ERROR, "%s", func_name); if (pFunc && PyCallable_Check(pFunc)) { - struct timespec start, end; - uint64_t time, max_time = 0; - if (timeout != NULL) { - max_time = timeout->tv_sec * 1e9 + timeout->tv_nsec; + pValue = PyObject_CallObject(pFunc, args); // make call to Python function + + // Set return value + if (py_ret != NULL) { + Py_XDECREF(*py_ret); // Decrement previous reference, if it exists + *py_ret = pValue; + } else { + Py_XDECREF(pValue); } - do { - clock_gettime(CLOCK_MONOTONIC, &start); - pValue = PyObject_CallObject(pFunc, args); // make call to Python function - clock_gettime(CLOCK_MONOTONIC, &end); - - // if the time the Python function took was greater than max_time, warn that it's taking too long - time = (end.tv_sec - start.tv_sec) * 1e9 + (end.tv_nsec - start.tv_nsec); - if (timeout != NULL && time > max_time) { - log_printf(WARN, "Function %s is taking longer than %lu milliseconds, indicating a loop or sleep in the code. You probably forgot to put a Robot.sleep call into a robot action instead of a regular function.", func_name, (long) (max_time / 1e6)); - } - // if the time the Python function took was less than min_time, sleep to slow down execution - if (time < min_time) { - usleep((min_time - time) / 1000); // Need to convert nanoseconds to microseconds - } - - // Set return value - if (py_ret != NULL) { - Py_XDECREF(*py_ret); // Decrement previous reference, if it exists - *py_ret = pValue; + // catch execution error + if (pValue == NULL) { + if (!PyErr_ExceptionMatches(PyExc_TimeoutError)) { + PyErr_Print(); + log_printf(ERROR, "Python function %s call failed", func_name); + ret = 2; } else { - Py_XDECREF(pValue); + ret = 3; // Timed out by parent process } - - // catch execution error - if (pValue == NULL) { + } else if (mode == AUTO || mode == TELEOP) { + // Need to check if error occurred in action thread + PyObject* event = PyObject_GetAttrString(pRobot, "error_event"); + if (event == NULL) { + PyErr_Print(); + log_printf(ERROR, "Could not get error_event from Robot instance"); + exit(2); + } + PyObject* event_set = PyObject_CallMethod(event, "is_set", NULL); + if (event_set == NULL) { if (!PyErr_ExceptionMatches(PyExc_TimeoutError)) { PyErr_Print(); - log_printf(ERROR, "Python function %s call failed", func_name); - ret = 2; + log_printf(DEBUG, "Could not get if error is set from error_event"); + exit(2); } else { ret = 3; // Timed out by parent process } - break; - } else if (mode == AUTO || mode == TELEOP) { - // Need to check if error occurred in action thread - PyObject* event = PyObject_GetAttrString(pRobot, "error_event"); - if (event == NULL) { - PyErr_Print(); - log_printf(ERROR, "Could not get error_event from Robot instance"); - exit(2); - } - PyObject* event_set = PyObject_CallMethod(event, "is_set", NULL); - if (event_set == NULL) { - if (!PyErr_ExceptionMatches(PyExc_TimeoutError)) { - PyErr_Print(); - log_printf(DEBUG, "Could not get if error is set from error_event"); - exit(2); - } else { - ret = 3; // Timed out by parent process - } - break; - } else if (PyObject_IsTrue(event_set) == 1) { - log_printf(ERROR, "Stopping %s due to error in action", func_name); - ret = 1; - break; - } + } else if (PyObject_IsTrue(event_set) == 1) { + log_printf(ERROR, "Stopping %s due to error in action", func_name); + ret = 1; } - } while (loop); + } + Py_DECREF(pFunc); } else { if (PyErr_Occurred()) { @@ -278,32 +257,6 @@ static uint8_t run_py_function(const char* func_name, struct timespec* timeout, } -/** - * Begins the given game mode and calls setup and main appropriately. Will run main forever. - * - * Behavior: This is a blocking function and will block the calling thread forever. - * This should only be run as a separate thread. - * - * Inputs: - * args: string of the mode to start running - */ -static void run_mode(robot_desc_val_t mode) { - // Set up the arguments to the threads that will run the setup and main threads - char* mode_str = get_mode_str(mode); - char setup_str[20], main_str[20]; - sprintf(setup_str, "%s_setup", mode_str); - sprintf(main_str, "%s_main", mode_str); - - int err = run_py_function(setup_str, &setup_time, 0, NULL, NULL); // Run setup function once - if (err == 0) { - err = run_py_function(main_str, &main_interval, 1, NULL, NULL); // Run main function on loop - } else { - log_printf(WARN, "Won't run %s due to error %d in %s", main_str, err, setup_str); - } - return; -} - - /** * Handler for killing the child mode subprocess */ @@ -361,7 +314,12 @@ static pid_t start_mode_subprocess(char* student_code) { signal(SIGINT, SIG_IGN); // Disable Ctrl+C for child process executor_init(student_code); signal(SIGTERM, python_exit_handler); // Set handler for killing subprocess - run_mode(mode); + + char* mode_str = get_mode_str(mode); + int err = run_py_function(mode_str, &main_interval, NULL, NULL); // Run main function + if (err) { + log_printf(WARN, "NEED TO EDIT STATEMENT"); // "Problem Child" + } exit(0); return pid; // Never reach this statement due to exit, needed to fix compiler warning } else { diff --git a/executor/studentcode.py b/executor/studentcode.py index 005fa383..92bca9a5 100755 --- a/executor/studentcode.py +++ b/executor/studentcode.py @@ -1,12 +1,5 @@ +def autonomous(): + print("Autonomous has begun!") -def autonomous_setup(): - print('Autonomous setup has begun!') - -def autonomous_main(): - pass - -def teleop_setup(): - print('Teleop setup has begun!') - -def teleop_main(): - pass +def teleop(): + print("Teleop has begun!") diff --git a/systemd/runtime_update.service b/systemd/runtime_update.service index 34d0f35d..d4648fda 100644 --- a/systemd/runtime_update.service +++ b/systemd/runtime_update.service @@ -3,9 +3,9 @@ Description=Update process for Runtime [Service] Type=oneshot -User=pi -WorkingDirectory=/home/pi/runtime -ExecStart=/home/pi/runtime/scripts/update.sh +User=ubuntu +WorkingDirectory=/home/ubuntu/runtime +ExecStart=/home/ubuntu/runtime/scripts/update.sh KillSignal=SIGINT [Install] diff --git a/tests/integration/tc_71_2.c b/tests/integration/tc_71_2.c index 4579c479..3eac4ff4 100644 --- a/tests/integration/tc_71_2.c +++ b/tests/integration/tc_71_2.c @@ -8,7 +8,7 @@ */ char check_output_6[] = - " File \"/home/runner/work/runtime/runtime/tests/student_code/executor_sanity.py\", line 25, in teleop_main\n" + " File \"/home/runner/work/runtime/runtime/tests/student_code/executor_sanity.py\", line 19, in teleop\n" " oops = 1 / 0\n" " ~~^~~\n" "ZeroDivisionError: division by zero\n"; @@ -37,7 +37,7 @@ int main() { send_run_mode(SHEPHERD, TELEOP); add_ordered_string_output("Traceback (most recent call last):\n"); add_ordered_string_output(check_output_6); - add_ordered_string_output("Python function teleop_main call failed\n"); + add_ordered_string_output("Python function teleop call failed\n"); check_run_mode(TELEOP); send_run_mode(DAWN, IDLE); diff --git a/tests/student_code/executor_sanity.py b/tests/student_code/executor_sanity.py index 2d17be72..adf561e8 100644 --- a/tests/student_code/executor_sanity.py +++ b/tests/student_code/executor_sanity.py @@ -8,18 +8,12 @@ def constant_print(msg): print(f"{msg} printing again") time.sleep(2) -def autonomous_setup(): +def autonomous(): print('Autonomous setup has begun!') print(f"Starting position: {Robot.start_pos}") Robot.run(constant_print, "autonomous") -def autonomous_main(): - pass - # This teleop code generates a DivisionByZero Python error -def teleop_setup(): - pass - -def teleop_main(): +def teleop(): oops = 1 / 0 diff --git a/tests/student_code/keyboard_input.py b/tests/student_code/keyboard_input.py index fe72d09f..90ac611b 100644 --- a/tests/student_code/keyboard_input.py +++ b/tests/student_code/keyboard_input.py @@ -1,18 +1,13 @@ simple_device = "62_20" -def autonomous_setup(): +def autonomous(): pass -def autonomous_main(): - pass - -def teleop_setup(): - pass - -def teleop_main(): - if Keyboard.get_value('a'): - Robot.set_value(simple_device, "MY_INT", 123454321) - elif Keyboard.get_value('y'): - print(Robot.get_value(simple_device, "MY_INT")) - Robot.sleep(.45) +def teleop(): + while True: + if Keyboard.get_value('a'): + Robot.set_value(simple_device, "MY_INT", 123454321) + elif Keyboard.get_value('y'): + print(Robot.get_value(simple_device, "MY_INT")) + Robot.sleep(.45) diff --git a/tests/student_code/net_handler_integration.py b/tests/student_code/net_handler_integration.py index cddaaab7..5ee27eb8 100644 --- a/tests/student_code/net_handler_integration.py +++ b/tests/student_code/net_handler_integration.py @@ -20,13 +20,12 @@ def modify_my_int(): Robot.set_value(SIMPLE_DEV, "MY_INT", Robot.get_value(SIMPLE_DEV, "MY_INT") - 1) Robot.sleep(1) -def teleop_setup(): +def teleop(): print("Teleop setup has begun!") Robot.run(print_if_button_a) Robot.run(modify_my_int) - -def teleop_main(): global i - if i < 3 and Gamepad.get_value('joystick_left_x') != 0.0: - print("Left joystick moved in x direction!") - i += 1 + while True: + if i < 3 and Gamepad.get_value('joystick_left_x') != 0.0: + print("Left joystick moved in x direction!") + i += 1 diff --git a/tests/student_code/runtime_latency.py b/tests/student_code/runtime_latency.py index 471c343c..0ac2d67c 100644 --- a/tests/student_code/runtime_latency.py +++ b/tests/student_code/runtime_latency.py @@ -2,15 +2,10 @@ time_dev = '60_123' -def autonomous_setup(): +def autonomous(): pass -def autonomous_main(): - pass - -def teleop_setup(): - pass - -def teleop_main(): - if Gamepad.get_value('button_a'): - Robot.set_value(time_dev, "GET_TIME", True) +def teleop(): + while True: + if Gamepad.get_value('button_a'): + Robot.set_value(time_dev, "GET_TIME", True) diff --git a/tests/student_code/sanity_write.py b/tests/student_code/sanity_write.py index f3801448..54a9f670 100644 --- a/tests/student_code/sanity_write.py +++ b/tests/student_code/sanity_write.py @@ -15,18 +15,14 @@ def constant_write(): Robot.set_value(GeneralTestDevice, "RED_INT", int_val) Robot.set_value(GeneralTestDevice, "ORANGE_FLOAT", float_val) Robot.set_value(GeneralTestDevice, "YELLOW_BOOL", bool_val) - int_val += 2; + int_val += 2 float_val += 3.14 bool_val = not bool_val -def autonomous_setup(): +def autonomous(): Robot.run(constant_write) + while True: + pass -def autonomous_main(): - pass - -def teleop_setup(): - pass - -def teleop_main(): +def teleop(): pass diff --git a/tests/student_code/sound_device.py b/tests/student_code/sound_device.py index cc9cb825..49465235 100644 --- a/tests/student_code/sound_device.py +++ b/tests/student_code/sound_device.py @@ -1,4 +1,5 @@ # Student code that plays pitches from keyboard inputs +# Commented out print_buttons and play_notes functions as they are not run import time SOUND = '59_1' @@ -23,8 +24,8 @@ ################################## AUTONOMOUS ################################## -def autonomous_setup(): - print("Now executing AUTONOMOUS SETUP") +def autonomous(): + print("Now executing AUTONOMOUS") # Write pitches for note in NOTES: if (note == ' '): @@ -35,35 +36,30 @@ def autonomous_setup(): Robot.set_value(SOUND, "PITCH", MAP[note]) time.sleep(NOTE_DURATION) -def autonomous_main(): - pass - #################################### TELEOP #################################### -def teleop_setup(): - print("Now executing TELEOP SETUP") +def teleop(): + print("Now executing TELEOP") # Robot.run(print_button) # Robot.run(play_notes) - pass - -def teleop_main(): - if Gamepad.get_value('button_a'): - Robot.set_value(SOUND, "PITCH", MAP['C']) - print("Wrote Button A: Pitch C") - time.sleep(NOTE_DURATION); - if Gamepad.get_value('button_b'): - Robot.set_value(SOUND, "PITCH", MAP['B']) - print("Wrote Button B: Pitch B") - time.sleep(NOTE_DURATION); + while True: + if Gamepad.get_value('button_a'): + Robot.set_value(SOUND, "PITCH", MAP['C']) + print("Wrote Button A: Pitch C") + time.sleep(NOTE_DURATION); + if Gamepad.get_value('button_b'): + Robot.set_value(SOUND, "PITCH", MAP['B']) + print("Wrote Button B: Pitch B") + time.sleep(NOTE_DURATION); ################################### THREADS #################################### -def print_button(): - while (1): - if Gamepad.get_value('button_a'): - print("BUTTON A IS PRESSED") - if Gamepad.get_value('button_b'): - print("BUTTON B IS PRESSED") +# def print_button(): +# while (1): +# if Gamepad.get_value('button_a'): +# print("BUTTON A IS PRESSED") +# if Gamepad.get_value('button_b'): +# print("BUTTON B IS PRESSED") # def play_notes(): # while (1): diff --git a/tests/student_code/tc_212_a.py b/tests/student_code/tc_212_a.py index df235457..6f003897 100644 --- a/tests/student_code/tc_212_a.py +++ b/tests/student_code/tc_212_a.py @@ -6,15 +6,10 @@ DEVICE = "62_1" PARAM = "MY_INT" -def autonomous_setup(): +def autonomous(): pass -def autonomous_main(): - pass - -def teleop_setup(): - pass - -def teleop_main(): - Robot.set_value(DEVICE, PARAM, 999) +def teleop(): + while True: + Robot.set_value(DEVICE, PARAM, 999) diff --git a/tests/student_code/tc_212_b.py b/tests/student_code/tc_212_b.py index 1951da90..43990b1f 100644 --- a/tests/student_code/tc_212_b.py +++ b/tests/student_code/tc_212_b.py @@ -7,16 +7,12 @@ DEVICE = "62_1" PARAM = "MY_INT" -def autonomous_setup(): +def autonomous(): pass -def autonomous_main(): - pass - -def teleop_setup(): +def teleop(): Robot.set_value(DEVICE, PARAM, 999) - -def teleop_main(): - if Keyboard.get_value('w'): - Robot.set_value(DEVICE, PARAM, 1000) + while True: + if Keyboard.get_value('w'): + Robot.set_value(DEVICE, PARAM, 1000) \ No newline at end of file diff --git a/tests/student_code/tc_212_c.py b/tests/student_code/tc_212_c.py index a58a563e..c29a0aec 100644 --- a/tests/student_code/tc_212_c.py +++ b/tests/student_code/tc_212_c.py @@ -6,17 +6,12 @@ DEVICE = "62_1" PARAM = "MY_INT" -def autonomous_setup(): +def autonomous(): pass -def autonomous_main(): - pass - -def teleop_setup(): - pass - -def teleop_main(): - if Keyboard.get_value('w'): - Robot.set_value(DEVICE, PARAM, 999) - else: - Robot.set_value(DEVICE, PARAM, 111) \ No newline at end of file +def teleop(): + while True: + if Keyboard.get_value('w'): + Robot.set_value(DEVICE, PARAM, 999) + else: + Robot.set_value(DEVICE, PARAM, 111) \ No newline at end of file