Hello Urara,

I made a mistake in my code above. Changing your toe-in function from 

def get_toe_in(self, wheel_state_global): 
    # Wheel normal expressed in global frame
    wheel_normal = wheel_state_global.rot.GetYaxis()
    # Terrain normal at wheel location expressed in global frame
    Z_dir = self.terrain.GetNormal(wheel_state_global.pos)
    # Longitudinal (heading) and lateral directions, in the terrain plane
    wheel_normal_np = np.array([wheel_normal.x, wheel_normal.y, 
wheel_normal.z])

    #Vcross cannot be found in pychrono. So I'm converting ChVectorD to 
numpy array and using np.cross
    Z_dir_np = np.array([Z_dir.x, Z_dir.y, Z_dir.z])
    X_dir_np = np.cross(wheel_normal_np, Z_dir_np) 
    X_dir = chrono.ChVectorD(X_dir_np[0], X_dir_np[1], X_dir_np[2])
    X_dir.Normalize()
    X_dir_np = np.array([X_dir.x, X_dir.y, X_dir.z])   
    Y_dir_np = np.cross(Z_dir_np, X_dir_np)
    Y_dir = chrono.ChVectorD(Y_dir_np[0], Y_dir_np[1], Y_dir_np[2])
    rot = chrono.ChMatrix33D()
    rot.Set_A_axis(X_dir, Y_dir, Z_dir)
    tire_csys = chrono.ChCoordsysD(wheel_state_global.pos, 
rot.Get_A_quaternion()) 

    # Express wheel normal in tire frame
    n = tire_csys.TransformDirectionParentToLocal(wheel_normal)
    # print("n",n.x, n.y, n.z)

    # Wheel normal in the vehicle frame
    n_v = 
self.my_hmmwv.GetVehicle().GetTransform().TransformDirectionLocalToParent(wheel_normal)

    # Toe-in
    toe_in = math.atan2(n_v.x, n_v.y)

    return toe_in

To 

def get_toe_in(self, wheel_state_global): 
# Wheel normal expressed in global frame
wheel_normal = wheel_state_global.rot.GetYaxis()
# Terrain normal at wheel location expressed in global frame
Z_dir = self.terrain.GetNormal(wheel_state_global.pos)
# Longitudinal (heading) and lateral directions, in the terrain plane
wheel_normal_np = np.array([wheel_normal.x, wheel_normal.y, wheel_normal.z])

#Vcross cannot be found in pychrono. So I'm converting ChVectorD to numpy 
array and using np.cross
Z_dir_np = np.array([Z_dir.x, Z_dir.y, Z_dir.z])
X_dir_np = np.cross(wheel_normal_np, Z_dir_np) 
X_dir = chrono.ChVectorD(X_dir_np[0], X_dir_np[1], X_dir_np[2])
X_dir.Normalize()
X_dir_np = np.array([X_dir.x, X_dir.y, X_dir.z]) 
Y_dir_np = np.cross(Z_dir_np, X_dir_np)
Y_dir = chrono.ChVectorD(Y_dir_np[0], Y_dir_np[1], Y_dir_np[2])
rot = chrono.ChMatrix33D()
rot.Set_A_axis(X_dir, Y_dir, Z_dir)
tire_csys = chrono.ChCoordsysD(wheel_state_global.pos, 
rot.Get_A_quaternion()) 

# Express wheel normal in tire frame
n = tire_csys.TransformDirectionParentToLocal(wheel_normal)
# print("n",n.x, n.y, n.z)

# Toe-in
toe_in = math.atan2(n.x, n.y)

return toe_in

The mistake is that the code unnecessarily converted the wheel normal back 
to the vehicle frame and used that for the toe-in computation. So as you 
rightly pointed out, the angles were in vehicle frame.

That being said, I realized that the approach I proposed is too convoluted, 
the following code also works 

# Get wheel state
wheel_state_global = self.my_hmmwv.GetVehicle().GetWheel(0,0).GetState() #in 
global frame
# Express wheel normal in tire frame
wheel_normal = wheel_state_global.rot.GetYaxis()
n = self.my_hmmwv.GetVehicle().GetWheel(0,0
).GetTransform().TransformDirectionParentToLocal(wheel_normal)
# toe_in = get_toe_in(self, wheel_state_global)
toe_in = math.atan2(n.x, n.y)

This directly gets the tire frame using GetTransform(). 
These modified functions produce the following plot, which I think is what 
we expect

Best Huzaifa

On Wednesday, November 8, 2023 at 11:02:54 AM UTC-6 [email protected] 
wrote:

> Dear Huzaifa,
>
> Thank you so much! This is the link to my code: 
> https://github.com/UraraKono/pychrono-steering
> Could you first look at the README file to get the overview of my code? 
> Please run main.py.
>
> Best regards,
> Urara
>
> On Mon, Nov 6, 2023 at 1:02 PM 'HUZAIFA MUSTAFA UNJHAWALA' via 
> ProjectChrono <[email protected]> wrote:
>
>> Hello Urara, 
>>
>> The code I provided for toe_in_r is what I suppose is the \delta from 
>> your image. However note that the vehicles in PyChrono are 4 wheeled, so 
>> you might need to make an approximation to get the \delta from the image 
>> (maybe take the average). 
>> That being said, from your plot, it is surprising that the rear tires 
>> have a toe angle and the angle keeps decreasing. Can you please post here 
>> the snippet of code that generated the data for the plots? I can try taking 
>> a quick look and reproduce this on my end. 
>>
>> Best
>> Huzaifa
>>
>> On Friday, November 3, 2023 at 11:03:56 AM UTC-5 [email protected] 
>> wrote:
>>
>>> Hello,
>>>
>>> Thank you so much for the reply!
>>> By "steering velocity and acceleration", I meant the steering angular 
>>> velocity of the tires and the longitudinal acceleration of the vehicle body.
>>>
>>> I tried your code in Pychrono.
>>> However, even though I set the driver's steering input to be always "1" 
>>> so that the vehicle keeps turning anti-clock-wise, the toe_in_r of all four 
>>> wheels kept decreasing as shown in "toe-in.png".
>>> The trajectory is shown in "trajectory.png". The vehicle starts from 
>>> (0,0) and keeps turning to the left. 
>>> Maybe the toe-in obtained from your code is still in the global frame?
>>>
>>> Is toe_in_r equivalent to "δ" in the screenshot of the vehicle model 
>>> figure attached to this email?
>>> I want to obtain this "δ".
>>>
>>> Best regards,
>>> Urara
>>>
>>>
>>>
>>>
>>> On Wednesday, November 1, 2023 at 9:55:12 AM UTC-4 [email protected] 
>>> wrote:
>>>
>>>> Hello,
>>>>
>>>> Do you want to get the angle by which the tire-wheel steers? 
>>>> GetSteering will only give you the normalized steering input (between -1 
>>>> and 1) that the driver applies onto the steering wheel at the current time 
>>>> step. 
>>>> If you would like to get the tire-wheel steer angle, you could do 
>>>> something like this
>>>>
>>>>             // Get the right wheel state
>>>>             auto state = vehicle.GetWheel(0, 
>>>> VehicleSide{RIGHT})->GetState();
>>>>             // Wheel normal (expressed in global frame)
>>>>             ChVector<> wheel_normal = state.rot.GetYaxis();
>>>>
>>>>             // Terrain normal at wheel location (expressed in global 
>>>> frame)
>>>>             ChVector<> Z_dir = terrain.GetNormal(state.pos);
>>>>
>>>>             // Longitudinal (heading) and lateral directions, in the 
>>>> terrain plane
>>>>             ChVector<> X_dir = Vcross(wheel_normal, Z_dir);
>>>>             X_dir.Normalize();
>>>>             ChVector<> Y_dir = Vcross(Z_dir, X_dir);
>>>>
>>>>             // Tire reference coordinate system
>>>>             ChMatrix33<> rot;
>>>>             rot.Set_A_axis(X_dir, Y_dir, Z_dir);
>>>>             ChCoordsys<> tire_csys(state.pos, rot.Get_A_quaternion());
>>>>
>>>>             // Express wheel normal in tire frame
>>>>             ChVector<> n = 
>>>> tire_csys.TransformDirectionParentToLocal(wheel_normal);
>>>>
>>>>             // Wheel normal in the Vehicle frame
>>>>             ChVector<> n_v = 
>>>> vehicle.GetTransform().TransformDirectionParentToLocal(wheel_normal);
>>>>
>>>>             // Toe-in
>>>>             auto toe_in_r = std::atan2(n_v.x(), n_v.y());
>>>>
>>>> However, I do not understand what you mean by "steering velocity and 
>>>> acceleration", do you want to control the lateral velocity and 
>>>> acceleration 
>>>> of the vehicle? 
>>>>
>>>>
>>>>
>>>>
>>>>
>>>> On Monday, October 23, 2023 at 9:23:40 AM UTC-5 [email protected] 
>>>> wrote:
>>>>
>>>>> Hello,
>>>>>
>>>>> Thank you so much for providing this wonderful simulator.
>>>>> I'm new to Pychrono and I have a question.
>>>>>
>>>>> I'm trying to modify demo_VEH_SteeringController.py so that the 
>>>>> vehicle can accept steering velocity and acceleration commands. I want to 
>>>>> convert these two commands into throttle, brake, and steering input. 
>>>>> ChPathFillowerDriver has GetSteering to get the driver steering 
>>>>> *input,* but how can I get the *current actual *steering angle so 
>>>>> that I can implement a PID controller for the steering?
>>>>>
>>>>> Or in this simulation, is it assumed that the driver steering input is 
>>>>> always the same as the actual steering?
>>>>>
>>>>> Best regards,
>>>>> Urara
>>>>>
>>>> -- 
>> You received this message because you are subscribed to a topic in the 
>> Google Groups "ProjectChrono" group.
>> To unsubscribe from this topic, visit 
>> https://groups.google.com/d/topic/projectchrono/bGrK7NFxsBI/unsubscribe 
>> <https://urldefense.com/v3/__https://groups.google.com/d/topic/projectchrono/bGrK7NFxsBI/unsubscribe__;!!IBzWLUs!VEreeTZm1KgpDeiWYmCTDRYWhiKJqfzXDEKYU59kbFDJ_2ZcUm7gnZiztNrlSdmlWbNvWiYj1gv6pD9ZozBOiFn11u021xw$>
>> .
>> To unsubscribe from this group and all its topics, send an email to 
>> [email protected].
>> To view this discussion on the web visit 
>> https://groups.google.com/d/msgid/projectchrono/235b7608-63bb-46a4-91e0-0f27f75e0e06n%40googlegroups.com
>>  
>> <https://urldefense.com/v3/__https://groups.google.com/d/msgid/projectchrono/235b7608-63bb-46a4-91e0-0f27f75e0e06n*40googlegroups.com?utm_medium=email&utm_source=footer__;JQ!!IBzWLUs!VEreeTZm1KgpDeiWYmCTDRYWhiKJqfzXDEKYU59kbFDJ_2ZcUm7gnZiztNrlSdmlWbNvWiYj1gv6pD9ZozBOiFn1bxQTjlE$>
>> .
>>
>
>
> -- 
> *Urara Kono*, Ph.D. student
> GRASP Laboratory <https://www.grasp.upenn.edu>
> Electrical and Systems Engineering
> University of Pennsylvania 
> she/her/hers
>

-- 
You received this message because you are subscribed to the Google Groups 
"ProjectChrono" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/projectchrono/1730ba00-7e2a-43eb-b546-e82ce77b3293n%40googlegroups.com.

Reply via email to