microsoft / AirSim

Open source simulator for autonomous vehicles built on Unreal Engine / Unity, from Microsoft AI & Research
https://microsoft.github.io/AirSim/
Other
16.49k stars 4.59k forks source link

Adding new firmware for Car - ArduPilot Rover SITL #2102

Closed rajat2004 closed 4 years ago

rajat2004 commented 5 years ago

Hi, I'm trying to add support for ArduPilot's Rover SITL (http://ardupilot.org/rover/) in Airsim using the Car model.

I have figured out (hopefully correctly!) few of the things which would be required for achieving this-

  1. Add new files in AirLib/include/vehicles/api/firmwares (new folder) for connecting and interfacing with the external firmware This would be similar to how it's done for Multirotor except that it would inherit from CarApiBase and implement those functions.

  2. Add a new intermediary file for spawning the model similar to MultiRotorParamsFactory and change it in CarPawnApi

  3. Add new model in Settings

I would like to have some guidance from the Airsim developers on how to proceed with this and what all other things would be needed Will add the links of the branches when some progress is made

Thanks, Rajat

rajat2004 commented 5 years ago

The part where I'm more confused is about passing the control values from the ApiBase to Unreal

https://github.com/microsoft/AirSim/blob/2450acfea564da1e426a5a5152ce4881ae76ccbb/Unreal/Plugins/AirSim/Source/Vehicles/Car/CarPawnSimApi.cpp#L88

This directly gets the values from the RC or Keyboard and passes it. The getRCData() function is here

https://github.com/microsoft/AirSim/blob/2450acfea564da1e426a5a5152ce4881ae76ccbb/Unreal/Plugins/AirSim/Source/PawnSimApi.cpp#L218

From loooking at the code of updateCarControls, one thing which might be possible is to always return True with isApiControlEnabled() which should get the values from the firmware and pass to Unreal

Though I'm not sure if this is the correct method, but looks promising. ArduRover has throttle-steering control, so might work.

rajat2004 commented 5 years ago

Made this issue but forgot to add updates on what I have tried so far-

  1. As mentioned in the first comment of the issue, I would probably need to add an intermediary "CarApiFactory" to create the vehicle instance, tried a few different ways, my cleanest method (according to me :sweat_smile: ) is https://github.com/microsoft/AirSim/compare/master...rajat2004:pr-car-restructure

It separates the Physics (Movement) update happening in CarPawnApi from the CarApiBase stuff present (since it inherits from that), by adding a minimal PhysXCarApi.hpp in AirLib which inherits from CarApiBase (see the compare for a much better idea of what I did)

It worked, the keyboard & API controls also work correctly, though one small thing is left which is the getCarState API call which I'll probably fix tonight There are certain more cleanups which can be done, one of which is to remove the structs in CarApiBase and move into a different file such as commonStructs

I'll make a PR for this if the devs think it's a good thing.

  1. So what was the point to do all that?

To make the Car code structure more similar to MultiRotor and to make it much more simpler to add external firmware control, this can be seen here - https://github.com/microsoft/AirSim/compare/master...rajat2004:pr-ardurover2 Check the second commit for how I added the new API (I added it in the MavlinkSettings as well since they were needed for ArduRover)

The new API worked, specify the vehicle in the settings file and done! Follow-up comment about the problems specific to ArduRover is coming

Hope this will be helpful!

rajat2004 commented 5 years ago

So coming to the current problem which I'm facing after all this, the API worked, I'm able to connect, send and receive messages and control the car

But the physics rate is too slow, it's running the same rate as the graphics, so I'm getting around 70-90 Ardupilot's firmware runs at 400Hz, so this is too less, after some 10-15 seconds, it starts showing "Link down" messages even though the messages are still coming Also, this has Lock-Step scheduling, meaning that the firmware sends the control message, stops, physics does one step, sends the sensor data, stops. This allows attaching running either side in a debugger and stopping and resuming without any change in the physics

The main culprit here I think is the PhysX, even if I increase the ClockSpeed, the update method is called at the same rate, so that's one Another is that I need to access the internal timestamp used by the physics and not the system clock, which is also something I haven't ben able to figure out (It should be possible - see this )

Important things for me are to have the physics run at a high rate, and having a constant timestep such as in Steppable Clock.

I think my next best option is to go for FastPhysicsEngine, modify that to add Car physics, but haven't started on that till now

Any thoughts or help on this is very much appreciated!

sytelus commented 5 years ago

When you increase the ClockSpeed, the PhysX indeed runs faster but currently in that mode the opportunity to send firmware signal only arise in render update. So this is not correct and we didn't bothered changing this because we didn't had HIL car until you did :). I think we need to handle physics tick event in Unreal (may be TickPostPhysics) and in that tick we send messages to firmware, just like we do for drones.

rajat2004 commented 5 years ago

@sytelus Yes, that's what I observed. Handling the Physics tick update would be a great thing, and that will allow Lock-Step Scheduling for Car vehicle as well. I'll look into "TickPostPhysics" and see if it can be used.

Another is that I need to access the internal timestamp used by the physics and not the system clock, which is also something I haven't ben able to figure out (It should be possible - see this )

Do you think it's possible to get the internal timestamp of the simulation? That is actually more of a concern right now rather than the Physics Tick.

But the physics rate is too slow, it's running the same rate as the graphics, so I'm getting around 70-90 Ardupilot's firmware runs at 400Hz, so this is too less

I was wrong in this, the firmware runs at 400Hz, but that's only needed for Copter. Rover is happy with 50Hz. There were some sensor inconsistencies, but thankfully there was already a PR for that (https://github.com/microsoft/AirSim/pull/1960)

After including that, I was able to get something working properly! Small video - https://drive.google.com/file/d/1MgqXYT7ouC9LMz35czZfZ8l2pyW5bXRF/view?usp=sharing

Ardupilot PR is here - https://github.com/ArduPilot/ardupilot/pull/12179 I had to do a bit of restructuring of Car Vehicle for this, therefore opened a seperate PR without the ArduRover additions - https://github.com/microsoft/AirSim/pull/2172

It would be great if you could do a review of the PRs!

The entire branch for this can be seen here - https://github.com/microsoft/AirSim/compare/master...rajat2004:pr-ardurover2

There's still a major problem in Ardupilot's side about Mavproxy (which is a minimal GCS used in AP development) disconnecting, still trying to figure that out.

I think my next best option is to go for FastPhysicsEngine, modify that to add Car physics, but haven't started on that till now

Finally, I don't think this is needed for now. But could be a new feature for later, also giving the Airsim user the choice of PhysicsEngine between FastPhysics and PhysXCar

TritonSailor commented 4 years ago

@rajat2004 Can you update me on where you're at with this? Are you still having an issue with Mavproxy disconnecting? I can test what you've done so far, since I'm also interested in ardurover SITL.

rajat2004 commented 4 years ago

Hey @TritonSailor, thanks for your interest in this and for helping in testing!

So currently, I am still having trouble with Mavproxy connecting, but there's a workaround which works and I have no idea why. The ArduPilot PR is here - https://github.com/ArduPilot/ardupilot/pull/12179 Use the code of that PR branch on the ArduPilot side. I'll post the instructions on that PR since if anyone else is also interested in trying it out, it'll be more easily found. The instructions are in this comment - https://github.com/ArduPilot/ardupilot/pull/12179#issuecomment-557590325

You might have seen the Car Restructure PR linked in this issue which is currently open, this is the first part to add the support, but that has diverged quite a lot from my other ArduRover branch and I haven't updated that in some time, so don't use this PR

Please put any comments on that PR itself, since there's no AirSim PR till now and the other Ardupilot devs will also be able to see it.

Hope this works, do let me know if there are any problems!

saihv commented 4 years ago

Closing as the discussion can move to the open PR - https://github.com/microsoft/AirSim/pull/2172

rajat2004 commented 4 years ago

@saihv Thanks! Had forgotten about this, PR for ArduRover support (https://github.com/microsoft/AirSim/pull/2383) which builds on top of the previous linked Car Restructure PR is also open

rajat2004 commented 4 years ago

For anyone interested, the ArduPilot PR has been merged, the instructions are on the Wiki page- https://ardupilot.org/dev/docs/sitl-with-airsim.html#launch-rover-sitl