Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

AP_Scripting: introduce serial device simulation support #27219

Merged
merged 13 commits into from
Jun 27, 2024

Conversation

tpwrules
Copy link
Contributor

@tpwrules tpwrules commented Jun 2, 2024

Allows a script to simulate a device attached via any serial protocol. The script can read and write data and have it handled according to the protocol as if exchanged over a serial port. The script can then do protocol translation, data filtering and validation, hardware-in-the-loop simulation, experimentation, etc., especially in combination with the scripting protocol which lets the script itself handle an attached device and so interpose any communication.

Costs about 850B flash on Cube Orange Plus.

Todo:

  • Test in SITL
  • Test that it properly disables
  • Test on real vehicle
  • Bikeshed names
  • Put parameters into a subgroup?
  • Examples
  • Binding docs
  • Wiki docs
  • Autotest script

@tridge
Copy link
Contributor

tridge commented Jun 2, 2024

@tpwrules interesting!
I'd like to see a working example, maybe a script that presents a NMEA GPS, mirroring real GPS data?

@tpwrules tpwrules force-pushed the scripting-serial-device branch from 2719533 to 45d8409 Compare June 2, 2024 19:59
@tpwrules
Copy link
Contributor Author

tpwrules commented Jun 2, 2024

That should be possible, I'll give it a try.

@tpwrules tpwrules force-pushed the scripting-serial-device branch from 45d8409 to d3e24c6 Compare June 4, 2024 02:28
@tpwrules
Copy link
Contributor Author

tpwrules commented Jun 4, 2024

I've added such an example, it works well in SITL. The extension to having a switch that starts fiddling with the data is obvious, but I'm not sure of a realistic method of doing that. It's pretty easy to confirm that the script is working and set up correctly, simply turn off scripting and watch the EKF failsafe activate after a few seconds.

@tpwrules
Copy link
Contributor Author

tpwrules commented Jun 4, 2024

Some more system questions:

  • Are protocols going to get confused that the baud rate is 0? I wasn't sure how to update the parameter, I can't just assign to it like a normal variable and exposing it as a real parameter doesn't really make sense IMO.
  • Are protocols going to get confused if the script doesn't drain the buffer and it fills up?

@tpwrules
Copy link
Contributor Author

I tested the example script on a real vehicle and it does work nice. There is a small amount of driftiness/toiletbowling possibly caused by the lag of the script processing the data (not helped by running on an F4 autopilot) or the unavailability of the 3D velocity information and ground course uncertainty, and the not particularly great mags on the tested drone.

But it worked fantastic as a protocol demo.

@tpwrules tpwrules force-pushed the scripting-serial-device branch from d3e24c6 to 7ee7a79 Compare June 16, 2024 15:36
Copy link
Member

@IamPete1 IamPete1 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

With this we now have two serial port userdata objects in lua. I suspect we could generalize so we only need one. I think you would only have to remove get_protocol_index. Maybe the get_device_port could become find_virtual_serial(portoocl) or something so you don't need the driver level protocol anymore.

@tpwrules
Copy link
Contributor Author

I see your point, but the problem is that for the device the script needs to read from the write buffer and write to the read buffer. There aren't any methods on AP_HAL::UARTDriver to accomplish this, and we need the subclass of AP_SerialManager::RegisteredPort anyway, so binding to that makes sense.

I suppose we could introduce a scripting-specific object that replaces both serial userdatas with some munging to access AP_HAL::UARTDriver or AP_SerialManager::RegisteredPort depending on the direction but it's not immediately clear that this would save anything. Is an additional userdata really that expensive?

@IamPete1
Copy link
Member

AP_SerialManager::RegisteredPort is already a subclass of AP_HAL::UARTDriver I think it should "just work" so long as we don't need any of the new methods not in the base class.

@tpwrules
Copy link
Contributor Author

tpwrules commented Jun 16, 2024

Consider the included loopback test script, both userdatas from find_port and get_device_port are bindings of the exact same AP_HAL::UARTDriver instance, but the former is accessing methods on the superclass and the latter methods on the subclass.

So we would need some sort of multiplex class that the script binds to that decides which to do. I don't think that's impossible, but it doesn't seem like it would save anything. I will investigate though.

I do like the idea of finding by protocol, I will try implementing that as well.

@tpwrules tpwrules force-pushed the scripting-serial-device branch from 7ee7a79 to cff9e93 Compare June 17, 2024 02:22
@tpwrules
Copy link
Contributor Author

I was able to implement your suggestions and get good savings. It saves about 300 bytes, but the base branch has changed somehow and the total cost is now only ~850 bytes. Thanks for the input.

@tpwrules tpwrules changed the title AP_Scripting: introduce serial device support AP_Scripting: introduce serial device simulation support Jun 17, 2024
@tpwrules
Copy link
Contributor Author

Tested again on a real drone and everything still works nice.

@Hwurzburg Hwurzburg added the WikiNeeded needs wiki update label Jun 17, 2024
@Hwurzburg
Copy link
Collaborator

needs a build_options.py and extract_feature.py

singleton AP_SerialManager method find_serial AP_HAL::UARTDriver AP_SerialManager::SerialProtocol_Scripting'literal uint8_t'skip_check
include AP_Scripting/AP_Scripting_SerialAccess.h
-- don't let user create access objects
userdata AP_Scripting_SerialAccess creation null -1
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder if we should rename this to "AP_Scripting_Serial".

Copy link
Contributor Author

@tpwrules tpwrules Jun 18, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like shorter names. It's not quite a port though, and it's on a layer separate from the device. I will probably still use "access" in the docs.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I did some thinking and I don't think AP_Scripting_Serial is descriptive enough. The only reason I'd see to shorten it is to save the few bytes of flash.

@tpwrules tpwrules force-pushed the scripting-serial-device branch from cff9e93 to f8ae3f2 Compare June 18, 2024 04:11
@tpwrules tpwrules requested a review from rmackay9 June 18, 2024 04:11
libraries/AP_Scripting/lua_bindings.cpp Show resolved Hide resolved
libraries/AP_Scripting/lua_bindings.cpp Show resolved Hide resolved
@@ -0,0 +1,36 @@
local ser_driver = serial:find_serial(0)
local ser_device = serial:find_simulated_device(28, 0)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it would be nice to not tie this method to just the SCR_SER devices. I've wanted for a while to be able to attach to serial devices that don't have their protocol set to scripting. For example, when writing a rangefinder driver in lua it would be nice for the user to be able to set the protocol to rangefinder instead of scripting.

Copy link
Contributor Author

@tpwrules tpwrules Jun 23, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don’t understand how that relates. That could be a future improvement, but we would have to figure out how to disconnect the existing driver I think?

What do you mean by "attach to" here? Acting as a device or as a driver?

tpwrules added 13 commits June 23, 2024 18:11
Passing -1 to the argument count for the `creation` tag (name does not
matter) will stop the generator from giving Lua a function to construct
that userdata. The C `new_<name>` function still works.
Adding another layer instead of just exposing UARTDriver bindings allows
substitution of the different functions for device simulation later.

Also take the opportunity to rework the docs a little.
Using `luaL_Buffer` avoids the need for any heap allocation in the
common case (count <= 512 bytes) and avoids stressing out the system
heap for large reads, instead using the script heap.

Zero net flash usage change.
Enables more efficient scripting.
Allows a script to simulate a device attached via any serial protocol.
The script can read and write data and have it handled according to the
protocol as if exchanged over a serial port. The script can then do
protocol translation, data filtering and validation,
hardware-in-the-loop simulation, experimentation, etc., especially in
combination with the scripting protocol which lets the script itself
handle an attached device and so interpose any communication.
Necessary for mavlink in particular to notice the port and hook up the
protocol internally.
Ensures the script won't process data created before it started, and
that the protocol won't process data created after the script stopped.
Tests that data can flow both ways with one end using protocol 28
(Scripting) and the other using the serial device simulation feature.
Tests that data can flow both ways with one end using protocol 28
(Scripting) and the other using the serial device feature.
@tpwrules tpwrules force-pushed the scripting-serial-device branch from f8ae3f2 to 2813ad8 Compare June 23, 2024 23:47
@tpwrules tpwrules requested a review from IamPete1 June 23, 2024 23:48
@tpwrules
Copy link
Contributor Author

Checked that the exceptions are safe and it's good, we should be ready to merge! Thanks!

@tpwrules tpwrules requested a review from peterbarker June 26, 2024 03:12
@peterbarker peterbarker merged commit 6e0d7bd into ArduPilot:master Jun 27, 2024
93 checks passed
@tpwrules tpwrules deleted the scripting-serial-device branch June 27, 2024 03:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
WikiNeeded needs wiki update
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants