NVIDIA / warp

A Python framework for high performance GPU simulation and graphics
https://nvidia.github.io/warp/
Other
4.28k stars 243 forks source link

[BUG] Implicit Type Conversions Occurring within wp.func #345

Open Sina-Haz opened 2 weeks ago

Sina-Haz commented 2 weeks ago

Bug Description

Type Aliasing

I am building a simulator with warp. I want to be able to define the precision of the simulator using the following file where I define some aliases:

import warp as wp import numpy as np

default_dtype = float vec3 = wp.vec(length=3, dtype=default_dtype) mat33 = wp.mat(shape=(3,3), dtype=default_dtype)

Code Snippets

I am noticing a lot of bugs occurring while using this however as while I debug I notice that in a lot of operations the datatypes are converted or casted when passed through a lot of simple functions such as add, sub, etc. and that I often need to cast them back as a patchwork fix to this. Here is an example wp.func where this happens:

@wp.func def update_cable(act_cable:ActuatedCable, control: default_dtype, cable_len: default_dtype, dt: default_dtype): ''' Updates the actuation rest length and endpoints of the actuated cable based on the control input, winch radius, and time step. Ensures that the actuation length doesn't exceed the original rest length.

Args:
    act_cable (ActuatedCable): The actuated cable object to update.
    control (default_dtype): Control signal used to determine motor actuation.
    cable_len (default_dtype): Current length of the cable.
    dt (default_dtype): Time step for the simulation.

Ensures:
    act_cable.act_L0 <= act_cable.L0, so the actuation length does not exceed the original rest length.
'''
assert act_cable.act_L0 != None

# compute change in cable length based on our motor, control and winch radius
dl = compute_cable_length_delta(act_cable.motor, control, act_cable.winch_r, dt) 

# We scale this and add to our actuation length
act_cable.act_L0 += dl * compute_rest_len(act_cable) / cable_len

# Ensure actuation length is <= base rest length
act_cable.act_L0 = min(act_cable.act_L0, act_cable.L0) # cable cannot be longer than original rest length

diff = act_cable.x2 - act_cable.x1
ndiff = wp.normalize(diff)
delta_pos = (act_cable.act_L0 - act_cable.L0) * ndiff
act_cable.x1 += vec3(delta_pos * 0.5)  # Move x1 towards x2
act_cable.x2 -= vec3(delta_pos * 0.5)  # Move x2 towards x1

For further information here is the definition of the ActuatedCable struct:

@wp.struct class ActuatedCable: ke: default_dtype # Spring stiffness kd: default_dtype # Spring damping L0: default_dtype # Rest length (Base, not taking into acct any actuation length) x1: vec3 # Endpoint 1 x2: vec3 # Endpoint 2 winch_r: default_dtype # Winch radius to convert b/w angular and linear velocity _winch_r: default_dtype # Winch radius in space of logits min_winch_r: default_dtype # min winch_r (for when all of cable is unspooled) max_winch_r: default_dtype # max winch_r (for when all of cable wrapped around the winch) motor: DCMotor # The DC motor with angular velocity and speed act_L0: default_dtype # Actuation length init_act_L0: default_dtype # Initial actuation length (for easy reset)

The Error

The error occurs in the update_cable method above. While stepping through the code, first I got a no overload exists error when I pass my arguments to the function. After verifying the datatypes of all of the arguments and that they match I set the types to Any in the function signature and try running the function again. This is where I get this error:

File "state_objects/Cables.py", line 188, in update_cable act_cable.x1 += vec3(delta_pos * 0.5) # Move x1 towards x2 ^^^^^^^^^^^^ File "/Library/Frameworks/Python.framework/Versions/3.11/lib/python3.11/site-packages/warp/codegen.py", line 305, in setattr setattr(self._ctype, name, value) TypeError: incompatible types, vec3f instance instead of vec_t instance

I step through the code line by line using a debugger. It verifies that act_cable.x1 and act_cable.x2 are both vec_t types but when I compute the following line: diff = act_cable.x2 - act_cable.x1 diff is stored as a wp.vec3f type. I tried casting diff using: diff = vec3(act_cable.x2 - act_cable.x1) but then on the very next line: ndiff = wp.normalize(diff) ndiff is again stored as a wp.vec3f vector. I can go on and on, but no matter how many times I try to cast it, it always implicitly converts my datatypes. I especially don't understand the last line where the exception occurs: act_cable.x1 += vec3(delta_pos 0.5) In the debugger, once again it shows that act_cable.x1 is a vec_t and I explicitly cast the result of delta_pos 0.5 to vec3 (which is an alias for vec_t) before adding them yet I still get the TypeError.

What can I do to fix this so that I don't need to be constantly casting my data? Is there any way you can stop the type conversions? Or at the very least make it so that vec3f and vec_t can be operated on when they have the same size and precision? I have been having a lot of errors.

System Information

Warp: 1.4.1 Python: 3.11.6 OS: macOS, "arm"