BeamNG / BeamNGpy

Python API for BeamNG.tech
https://beamng.tech
MIT License
257 stars 45 forks source link

About the wheelspeed for individual wheel #248

Closed ShaoshuSu closed 7 months ago

ShaoshuSu commented 8 months ago

Dear BeamNG Team,

I am here to ask about a challenge we have encountered concerning the wheel speed reading, which is vital for our ongoing research project.

Currently, when attempting to retrieve the wheel speed data by enabling the electrics sensor electrics = Electrics() and accessing the value with ego.sensors['electrics']['wheelspeed'], we are only able to obtain a single float value. However, during manual operation of a rear-wheel-drive (RWD) vehicle on an ice surface, it looks like the wheel speeds vary across the four wheels or at least the front and rear wheels.

So, I want to inquire if there is a specific method or approach available to retrieve the readings for all four wheel speeds simultaneously.

Your guidance and assistance in resolving this matter would be immensely appreciated!

aivora-beamng commented 7 months ago

Hi, for the values which are not yet exposed to BeamNGpy API directly, you can use the approach suggested in the Using mods with BeamNGpy demo.

Replace the vehicleEngineCode.lua from the example with the one provided here: vehicleEngineCode.zip

And in the using_mods_with_bngpy.ipynb notebook, you'll need to add following code:

def getWheelSpeeds(veh):
    data = dict(type='GetWheelSpeeds')
    response = veh.connection.send(data)
    return response.recv()

import time
for _ in range(10):
    print(getWheelSpeeds(etk))
    time.sleep(1.0)

With this approach you can get any available values from the simulation, even if the Python API does not expose them.

ShaoshuSu commented 7 months ago

Hi @aivora-beamng,

Thank you so much for your detailed explanation! It really helpful and helped us solve the problem! And by the way, I want to ask one more follow-up question.

Is there any mod that could help us to read the information about the moment of inertia, the position of the center of mass, and the position of each of the wheels wrt to the vehicle?

I have explored some existing mods, but haven't found something related.

Thanks a lot again!

aivora-beamng commented 7 months ago

Hello, you will need to delve into depths of BeamNG VLua for this again.

The inertia is calculated in wheels.lua and therefore you can access it in a similar way as the wheel speed. You can edit your vehicleEngineCode.lua to return multiple values at once, like this:

local function handleGetWheelData(request)
    local response = {}
    for name, wheel in pairs(wheelCache) do
        response[name] = {
            ['speed'] = wheel.wheelSpeed,
            ['inertia'] = wheel.inertia,
        }
    end
    request:sendResponse(response)
end

M.handleGetWheelData = handleGetWheelData

For the other values, you want to get the center of the mass for every wheel individually, right? And what is the reference point you have in mind when talking about "wrt to the vehicle"?

aivora-beamng commented 7 months ago

Also, do you want to compute the center of mass once for the initial position of the vehicle, or do you want it to be a runtime value for the current tire shape?

ShaoshuSu commented 7 months ago

Hi @aivora-beamng,

Sorry for the confusing description of the question. But thank you for your detailed explanation!

But by saying the moment of inertia and the position of the center of mass, I mean the moment of inertia and the center of mass position for the whole vehicle.

I think the initial value for the center of mass position and moment of inertia of the vehicle are good for us, as we might only need an approximated value in our research work. But If there's a method to access the runtime value, that would be great for us too. It would allow us to understand the impact of changes in these two values.

And by saying "the position of each of the wheels wrt to the vehicle", I mean the geometrical parameters of the wheels for the vehicle. For example, the distance from the center of mass to the front axle, $L_f$, to the rear axle, $L_r$ ,and the width between two front/rear wheels $d$ as shown in the attached figures. Not sure if there is certain way that we could read these geometrical parameters as well?

Thank you!

image
aivora-beamng commented 7 months ago

Hi again, OK, that's much easier than computing it for the individual wheels (although that is also possible with the nodes-and-beams model)!

To get the center of gravity of the whole vehicle, you can use the existing function Vehicle.get_center_of_gravity(): https://beamngpy.readthedocs.io/en/latest/beamngpy.html#beamngpy.Vehicle.get_center_of_gravity

I think this Lua function that you can add to your vehicleEngineCode.lua should get you all the values that you need (you should be able to calculate everything from the positions of the center of the wheels and the COG):

local function handleGetCustomVehicleData(request)
    -- get the moments of inertia
    local roll, pitch, yaw = obj:getRollPitchYaw()

    local withoutWheels = false
    local cog = obj:calcCenterOfGravity(withoutWheels)
    local pos = obj:getPosition() -- position of the reference node of the vehicle

    local wheelData = {}
    for name, wheel in pairs(wheelCache) do
        local centerPos = (obj:getNodePosition(wheel.node1) + obj:getNodePosition(wheel.node2)) / 2
        centerPos = centerPos + pos

        wheelData[name] = {
            ['speed'] = wheel.wheelSpeed,
            ['position'] = {centerPos.x, centerPos.y, centerPos.z}
        }
    end

    local response = {
        ['roll'] = roll,
        ['pitch'] = pitch,
        ['yaw'] = yaw,
        ['cog'] = {cog.x, cog.y, cog.z},
        ['wheels'] = wheelData
    }
    request:sendResponse(response)
end

M.handleGetCustomVehicleData = handleGetCustomVehicleData

All the positions that are returned are dynamically calculated, absolute and in the world-space. The angles are in radians.

We are working on making more information from the simulator available without having to resort to writing Lua modules, but right now, you can use this method of extending the BeamNGpy library with custom data.

ShaoshuSu commented 7 months ago

Got it, thank you so much for your detailed code and explanation!