Is there a function in VEXcode V5 - python with similar functionality to "task::yield();" from VEXcode Pro V5?

Recently, our team has been moving from C++ (VEXcode pro V5), over to the python platform offered by VEXcode V5.

In the past we have been using:

vex::task::yield();

to ensure control is passed between our many vex::task objects and threads while wasting as little time as possible.

The closest thing I have found in python is this:

wait(20, MSEC)
# Not necessarily 20 msecs, but you get the idea.

while this is an option, I would prefer a solution that doesn’t force the thread (or task) to wait the specified amount. Rather, something that allows as little time as possible to be “wasted” between times of control returned to the scheduler.

Desired functionality example:

def some_thread_callback():
  while True:
    # Do something
    yield()
    # Not to be confused with the built in 'yield' keyword for python generators

thread = Thread(some_thread_callback)

# main loop
while True:
  # Do something
  yield()

where each ’ yield() ’ would behave like vex::task::yield() found from C++, as seen below:

yield

Thanks in advance for any help offered.

3 Likes

Just use sleep (or wait, same thing), wait(1, MSEC) is the closest you can get, there is no binding for yield.

You may also find that just having no delay (sleep etc.) in the loop works, I think I have a hook that calls yield for each loop iteration so python doesn’t ever block the scheduler.

but yield is rarely needed even in C++ code, what’s the actual use case ?

4 Likes

First, thanks for your quick response.

Now, in answer to your question, the code below is our use case (this code will run on our robot and work as intended)

def _drive_(distance, speed):

    pid = PID(2.5, 0, 0, 200, 0, speed)
    distance_in_degrees = distance / WHEEL_CIRCUMFRENCE *REVERSE_GEAR_RATIO * 360

    for motor in DRIVE_MOTORS:
        motor.set_position(0, DEGREES)
        motor.set_velocity(0, PERCENT)
        motor.set_stopping(BRAKE)
        motor.spin(FORWARD)

    not_done = True

    last_time = brain.timer.time(SECONDS)
    current_time = brain.timer.time(SECONDS)

    while not_done:

        error = distance_in_degrees - sum([motor.position(DEGREES) for motor in DRIVE_MOTORS]) / 6

        last_time = current_time
        current_time = brain.timer.time(SECONDS)
        dt = current_time - last_time

        speed = pid.update(error, dt)

        for motor in DRIVE_MOTORS:
            motor.set_velocity(speed, PERCENT)

        if abs(error) < 0.5:
            not_done = False
        
        # This wait (and others) is where I was planning on implementing a 'yield()' function
        wait(20, MSEC)

    for motor in DRIVE_MOTORS:
        motor.stop()

def drive(distance, speed, wait=True):
    global THREAD
    if wait == True:
        _drive_(distance, speed)
    else:
        THREAD = Thread(_drive_, (distance, speed))

also…

I apologize for my confusion, but by ‘yield’ do you mean…

def infinite_counter():
    i = 0
    while True:
        yield i
        # ^ that yield ^
        i += 1

or

vex::task::yield();
1 Like

I meant task::yield().

Most loops that are controlling motors or reading sensors can sleep for a few mS as the motor/sensor update rate is not that fast. A PID loop also needs some delay otherwise derivative is almost always 0 as the error hasn’t changed.

5 Likes

Good point.

I will run a test to verify if our code still works after removing appropriate wait()s.

Thanks for your help!