Why wont my exponential drive code work?

I have been trying to find a decent exponential function for my drive code, and I have found one that suits my needs. However, I get an error occasionaly when accessing my drive vaue. (I can’t remember exactly what it was, but I think it said something about not being able to convert to a float). I belive this should only happen if my drive speed is not returning a number, but a NaN, imaginary number or String. But the function should only return a real number value.

drivetrain_left_side_speed = (pow((left / 127), 1.7) * 100)

Is there something I am missing?

Full code
# ---------------------------------------------------------------------------- #
#                                                                              #
# 	Module:       main.py                                                      #
# 	Author:       deshe                                                        #
# 	Created:      5/29/2025, 12:17:02 PM                                       #
# 	Description:  V5 project                                                   #
#                                                                              #
# ---------------------------------------------------------------------------- #

# Library imports
from vex import *


# Brain should be defined by default
brain=Brain()

controller = Controller(PRIMARY)

l1 = Motor(Ports.PORT17, True)
l2 = Motor(Ports.PORT1, True)
l3 = Motor(Ports.PORT18, True)

r1 = Motor(Ports.PORT11, False)
r2 = Motor(Ports.PORT16, False)
r3 = Motor(Ports.PORT2, False)

intakeM2 = Motor(Ports.PORT10, True)
intakeM1 = Motor(Ports.PORT12, True)

rDriveA = MotorGroup(r1, r2)
rDrive = MotorGroup(rDriveA, r3)
lDriveA = MotorGroup(l1, l2)
lDrive = MotorGroup(lDriveA, l3)

link = MessageLink(Ports.PORT1, 'james', VexlinkType.MANAGER)

drivetrain = DriveTrain(rDrive, lDrive, 1, 1, 1, INCHES)

brain.screen.print("Hello V5")

# define variables used for controlling motors based on controller inputs
drivetrain_l_needs_to_be_stopped_controller = False
drivetrain_r_needs_to_be_stopped_controller = False
intake_motors_stopped = True
controller_button_L_motors_stopped = True

# define a task that will handle monitoring inputs from controller
def rc_auto_loop_function_controller():
    global drivetrain_l_needs_to_be_stopped_controller, drivetrain_r_needs_to_be_stopped_controller, intake_motors_stopped, controller_button_L_motors_stopped, remote_control_code_enabled
    # process the controller input every 20 milliseconds
    # update the motors based on the input values
    while True:
        if remote_control_code_enabled:
            
            # calculate the drivetrain motor velocities from the controller joystick axies
            # left = axisA + axisC
            # right = axisA - axisC

            left = controller.axis3.position()
            right = controller.axis2.position()

            if controller.axis3.position() <= 0: 
                drivetrain_left_side_speed = -(pow((left / 127), 1.7) * 100)
            else:
                drivetrain_left_side_speed = (pow((left / 127), 1.7) * 100)

            if controller.axis2.position() <= 0:
                drivetrain_right_side_speed = -(pow((right / 127), 1.7) * 100)
            else:   
                drivetrain_right_side_speed = (pow((right / 127), 1.7) * 100)
            

            # drivetrain_left_side_speed = pow((left / 127), 2) * 100
            # drivetrain_right_side_speed = pow((right / 127), 2) * 100
            
            # drivetrain_left_side_speed = ((left / 127) ** 1.8) * 100
            # drivetrain_right_side_speed = ((right / 127) ** 1.8) * 100
            
            
            
            # check if the value is inside of the deadband range
            if controller.axis3.position() < 5 and controller.axis3.position() > -5:
                # check if the left motor has already been stopped
                if drivetrain_l_needs_to_be_stopped_controller:
                    # stop the left drive motor
                    l1.stop()
                    l2.stop()
                    l3.stop()
                    # tell the code that the left motor has been stopped
                    drivetrain_l_needs_to_be_stopped_controller = False
            else:
                # reset the toggle so that the deadband code knows to stop the left motor next
                # time the input is in the deadband range
                drivetrain_l_needs_to_be_stopped_controller = True
            # check if the value is inside of the deadband range
            if controller.axis2.position() < 5 and controller.axis2.position() > -5:
                # check if the right motor has already been stopped
                if drivetrain_r_needs_to_be_stopped_controller:
                    # stop the right drive motor
                    r1.stop()
                    r2.stop()
                    r3.stop()
                    # tell the code that the right motor has been stopped
                    drivetrain_r_needs_to_be_stopped_controller = False
            else:
                # reset the toggle so that the deadband code knows to stop the right motor next
                # time the input is in the deadband range
                drivetrain_r_needs_to_be_stopped_controller = True
            
            # only tell the left drive motor to spin if the values are not in the deadband range
            if drivetrain_l_needs_to_be_stopped_controller:
                l1.set_velocity(drivetrain_left_side_speed, PERCENT)
                l2.set_velocity(drivetrain_left_side_speed, PERCENT)
                l3.set_velocity(drivetrain_left_side_speed, PERCENT)
                l1.spin(FORWARD)
                l2.spin(FORWARD)
                l3.spin(FORWARD)
            # only tell the right drive motor to spin if the values are not in the deadband range
            if drivetrain_r_needs_to_be_stopped_controller:
                r1.set_velocity(drivetrain_right_side_speed, PERCENT)
                r2.set_velocity(drivetrain_right_side_speed, PERCENT)
                r3.set_velocity(drivetrain_right_side_speed, PERCENT)
                r1.spin(FORWARD)
                r2.spin(FORWARD)
                r3.spin(FORWARD)

            if controller.buttonR1.pressing():
                if intake_motors_stopped:
                    intakeM1.spin(FORWARD, 100, PERCENT)
                    intakeM2.spin(FORWARD, 100, PERCENT)
                    intake_motors_stopped = False

            if controller.buttonR2.pressing():
                if intake_motors_stopped:
                    intakeM2.spin(FORWARD, 100, PERCENT)
                    intake_motors_stopped = False

            if controller.buttonL1.pressing():
                if intake_motors_stopped:
                    intakeM1.spin(FORWARD, 100, PERCENT)
                    intakeM2.spin(REVERSE, 100, PERCENT)
                    intake_motors_stopped = False

            if controller.buttonL2.pressing():
                if intake_motors_stopped:
                    intakeM1.spin(REVERSE, 100, PERCENT)
                    intakeM2.spin(REVERSE, 100, PERCENT)
                    intake_motors_stopped = False

            if not intake_motors_stopped and not controller.buttonR1.pressing() and not controller.buttonR2.pressing() and not controller.buttonL1.pressing() and not controller.buttonL2.pressing():
                    intake_motors_stopped = True
                    intakeM1.stop()
                    intakeM2.stop()
                

        # wait before repeating the process
        wait(10, MSEC)

# define variable for remote controller enable/disable
remote_control_code_enabled = True

rc_auto_loop_thread_controller = Thread(rc_auto_loop_function_controller)
        

By chance does it think ‘left’ is a different keyword or something? Like maybe try changing the name to be more specific and see if it works. Next time you get the error could you copy it over?

Also when reading your code (very well commented btw), just one suggestion for simplicity is for the dead and you can do the absolute value of the value instead of <5 and >-5.

If you raise a negative number to a real exponent you can get an imaginary number. You’ll have to do something about the sign.

Also, Your 100 isn’t 100. If you plug in 100 you don’t get 100 out, you get 66. I would fix your scaling by multiplying by a different number other than 100 at the end.

I just realized that I missed a negetive sign in my code.

Instead of this:

if controller.axis3.position() <= 0: 
    drivetrain_left_side_speed = -(pow((left / 127), 1.7) * 100)

I needed this:

if controller.axis3.position() <= 0: 
    drivetrain_left_side_speed = -(pow((-left / 127), 1.7) * 100)

I don’t know how I missed this…

Thanks for your help @sankeydd!

Left is a keyword. left is not.

I was going to fix all of the readability issues after I get it working, but I didn’t think of this, Thanks!

Not necessarily. If I raise a negetive number to an even power, I would get an imaginary number. However, if I raise it to an odd power, I get a real number.

I didn’t know that the controller.axis1.position() gave a percentage value. I thought it gave [127, -127]. Thanks for catching that.

Your right that’s probably why. What I do in my exponential code (this isn’t the reason, but it fixes it), is check if the sign is negative, going backwards. If it is I multiply it by -1, put it through the function, and make it negative again. If it’s positive, just leave it how it is

Another trick to get the sign (+/-) of the value is to take x/abs(x), but you still have to handle the case where x=0 (divide-by-zero error). You can easily handle that in deadband calculations (ignore values where abs(x) < [some small value]).

Also note that there is a different version for floating point numbers: fabs(x).