BeamNG / BeamNGpy

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

Controlling vehicle actuation with road wheel angle and acceleration. #224

Open BleedObsidian opened 1 year ago

BleedObsidian commented 1 year ago

Hello,

Currently the only way to control the actuation of a vehicle is using a steering wheel, throttle and brake interface. This type of interface is very much tied to the exact make and model of car you're using:

  1. The steering rack ratio of every car is different (and often not linear). The maximum achievable road wheel angle at full lock of the steering wheel also differs between cars.
  2. 50% throttle on a more powerful car is likely to result in a faster rate of acceleration. To deal with this, I have to write PID controllers that have to be tuned differently for every car I use in the simulator.

A more common interface (found on drive-by-wire systems on a real car) is to control using:

Any chance we could get this interface type of interface? I think it's a really important issue personally.

dstark481 commented 1 year ago

Thanks Jesse,

We can consider it.

Regarding the first point, you could get the two front road wheel angles (RWA) with something like this in Lua:

-- Get the two RWA angles from the vehicle (FL and FR).
local function getWheelAngles()
  local steeringSign = sign(electrics.values.steering_input)
  local frontLeftWheel = wheels.wheelRotators[wheels.wheelRotatorIDs["FL"]]
  local frontRightWheel = wheels.wheelRotators[wheels.wheelRotatorIDs["FR"]]
  local frontLeftWheelAngle = acos(obj:nodeVecPlanarCosRightForward(frontLeftWheel.node2, frontLeftWheel.node1)) * steeringSign
  local frontRightWheelAngle = acos(obj:nodeVecPlanarCosRightForward(frontRightWheel.node1, frontRightWheel.node2)) * steeringSign
  return frontLeftWheelAngle, frontRightWheelAngle
end

you also know the steering wheel angle (STWA) in the range [-1, 1], since it is whatever you set it to. From there, you can compute the map between STWA and RWA, which as you say will depend on the steering mechanism of the vehicle, and will not be linear. This may be a bit tedious, but it would only need done once per vehicle. You could save the data to .csv or whatever.

On the second point regarding acceleration, though, I am not sure it is completely clear how to do this well. It sounds like some kind of PID or similar. We can either supply a gas pedal value in [0, 1] or supply the propulsion torques directly, but it sounds like we would need some kind of feedback thing where we monitor the acceleration value and adjust accordingly, which will be pretty laggy. We would need to investigate how the drive-by-wire systems do it, then. The relationship between acceleration and pedal/torques would be complicated, so you cant just do a look-up or have some formula, I guess.

Best regards, Dave

BleedObsidian commented 1 year ago

@dstark481

Hi Dave,

The lua code is really useful thank you, it would be really nice if this was integrated natively so we can get the road wheel angles through vehicle.state or similar. At least this is a step upwards.

As for the second point, yeah ultimately real drive by wire systems will be using PID (or potentially LQR or MPC) controllers. The main thing is dealing with wheel slip under heavy acceleration or low friction surfaces, so no a lookup table doesn't cut it really. But you mentioned you can control via propulsion torque, again this would be really useful to expose via the Python interface as torque is far less tied to the vehicle than gas pedal position and it's one step further to controlling acceleration directly (if you assume no tyre slip).

Thanks, Jesse.

dstark481 commented 1 year ago

Controlling the vehicle through torques (drive and brake) alone is something we already do through Simulink, eg see https://github.com/BeamNG/BeamNG-Simulink_generic_interface, but would take some work for BeamNGpy. Let me discuss it, it might make a good little project for someone. Getting the RWAs through in the vehicle state should be simple enough.

Best, Dave

BleedObsidian commented 1 year ago

@dstark481

That would be super super useful thank you. Road wheel angle control is my biggest concern just because it's so important when making stable and accurate motion control algorithms.

I've just spotted this method for the vehicle class, velocity over dt is literally acceleration, so assuming it already handles wheel slip, an acceleration interface basically already exists, it's a bit of a weird method. Would be nice if it was simply made available via vehicle.control().

image

dstark481 commented 1 year ago

I have had trouble with that function before, but maybe you will have better luck. I would be sure to test it out carefully first.

Shibodd commented 6 months ago

The fact that it's not yet possible to control the steering angle directly is a big issue. Together with #273, the steering wheel angle is cumbersome to retrieve and due to #195 it's not even clear what is currently being reported (is it just visual, like this comment seems to report?).

aivora-beamng commented 5 months ago

Hi, the steering wheel angle is just visual, as reported in the comment. Support for RWA to control the vehicle is on our backlog, but with no ETA.

Shibodd commented 5 months ago

I assume steering_input is just visual, too?

aivora-beamng commented 5 months ago

Hi, steering_input is a value in the range of [-1; 1] and it is used to actually steer the vehicles.

https://documentation.beamng.com/modding/vehicle/vehicle_system/electrics/