Lua Scripting Live Stream [recording available on YouTube]

Sad I had to miss it. I have to watch later.

1 Like

Slideshow and examples are hosted on GitHub:

@iampete - ahrs:get_vibration() is an existing binding, so we were wrong about that!



Since I mentioned a table (array) demo but never actually did one, here’s a short primer:

Declare a table like so:
local tbl = {'apples', 'oranges', 'bananas'}

Though I used all strings, the element types do not have to match.

Unless indices are expliclty defined, tables are integer indexed starting at 1. Use square brackets to reference an element index like so:
local element = tbl[1] -- element is now assigned 'apples'

Unlike more strict language array types, Lua tables are not fixed size and can be expanded on the fly:
tbl[4] = 'peaches'

For a 0-based table, declare like so:

local nerdy_tbl = {
    [0] = 'count',
    [1] = 'from',
    [2] = 'zero!'
}

Indices must be unique, but they do not have to be integers. This is also a valid table (that you should never use :slight_smile: ):

local confusing_tbl = {
    ['zero'] = true,
    [1] = 3.1415927,
    [true] = false
}

Multi-dimensional tables are also possible:

local multi_tbl = {
    {'apples', 'oranges', 'bananas'},
    {'peaches', 'apricots', 'durian'}
}
local element = multi_tbl[1][2] -- element is now assigned 'oranges'

For more info (like iterating over table elements), visit https://lua.org

2 Likes

I never promised no homework, so if you can explain (not just guess the output of) the logic presented in this obfuscated mess, you have an excellent handle on Lua scope, typing, and, to an extent, tables:

True = false

local function False()
    local True = true
    return false
end

if not True then
    True = False
else
    True = true
end

False = {
    [True()] = true,
    [not True()] = false
}

print(False[true])

Thanks for the beginner lesson! I was hesitant to get into Lua scripting because I have no programming background. After watching I started on a script for a function I’ve wanted, an auto stop and start again based on GPS fix. I haven’t field tested it yet but I think it should be good. Feel free to roast my attempt.

local ROVER_MODE_HOLD = 4       -- # for setting hold mode
local ROVER_MODE_AUTO = 10      -- # for setting auto mode
local FREQUENCY       = 500     -- How often to run the script
local START_WP        = 3       -- When to start looking for bad ahrs, default set to waypoint 3


function auto_hold()              -- Checks to see if ahrs is bad and sends rover into hold mode if it is
        if ahrs:healthy() == false then
            vehicle:set_mode(ROVER_MODE_HOLD)
            gcs:send_text(4, 'GPS fix lost, rover in hold mode')
            return auto_return()
        end
        return auto_hold, FREQUENCY
end

function auto_return()            -- Check to see if ahrs is back up to snuff then turns auto back on
    if ahrs:healthy() == true then
        vehicle:set_mode(ROVER_MODE_AUTO)
        gcs:send_text(4, 'GPS fix recovered, auto mode engaged.')
        return auto_hold()
    end
    return auto_return, FREQUENCY
end

function start_scanning()         -- Waits until your are past a certain WP to begin scanning ahrs / prevents startup issues  
    if (mission:get_current_nav_index() <= START_WP) then
        gcs:send_text(4, 'Script pending')  -- I used this for debugging, it can be removed to prevent startup spam
        return start_scanning, FREQUENCY
    end
    if (mission:get_current_nav_index() >= START_WP) then
        gcs:send_text(4, 'Script starting')
        return auto_hold()
    end
end

return start_scanning()  -- Call the waiting function first before scanning ahrs

1 Like

That script looks a bit dangerous. You could be in another mode with a wp index greater than 3 and accidentally find yourself back in auto mode.

It’s an excellent start, but you need to check for either an intentional switch to auto mode or for mission:state() == mission.MISSION_RUNNING

I just rewrote a similar script, and I’m still testing the new version. As @iampete suggested, I will add that to the ArduPilot script examples library when I’m happy that it’s working well. For now, have a look at the old version to see all of the pitfalls and edge cases that I safeguard against.

My biggest problem with the older version that I linked is that I do not check for zero RC throttle command before switching to manual mode. I use a spring-loaded throttle gimbal, so that’s not a problem on my rig. It could cause some pretty ugly results for someone else. The reason I use manual mode instead of hold mode is to be able to drive out of an area of poor GPS reception without canceling the mission pause. It’s actually pretty cool to watch as I drive out from under some trees, and the rover takes off again on its own once the fix type improves (intentional, monitored behavior).

I’m also not really happy with the very convoluted logic structure of that script - it’s hard to read! The newer version is a bit better in that regard.



I’ve also been working up a rough terrain detection script to slow vehicle speed like we discussed on the live stream. It’s a little tricky to get Rover to slow down on the fly. Simply setting WP_SPEED during an auto mission is not sufficient. Instead, I’m inserting a DO_CHANGE_SPEED waypoint command as the current waypoint (I think in a very efficient way that doesn’t require storing the entire mission in a Lua table). Will share that when I get the kinks worked out.

UPDATE: The rough terrain script is working pretty well! @ktrussell and I have both tested it on our mowers with decent success. It needs some polishing, but I will make it available along with the revised MinFixType script soon.

3 Likes

Not sure how I missed the LiveStream?!
In any case, I watched the YouTube video. Brilliant.
Never worked with Lua or MissionPlanner, hence the video provided great insight.
Thank you @Yuri_Rage for making this effort; much appreciated.

I read /heard somewhere you sponsored the cost of Zoom; happy to chip in to ease the burden. Simply let me know.

Again, thank you very much for the video.

@Max_G ,

Thanks so much for the kind words! It was a fun session.

I didn’t mean to insinuate that I was put out by the cost of a Zoom subscription - just intended to underscore the point that I’m not on any sort of payroll by ArduPilot or its partners. I’m happy to absorb the cost for now in the interest of helping the community.

1 Like

Pull request submitted for the examples we discussed during the Live Stream, including a functional rough terrain detection script.

The TerrainDetector script is likely to change slightly (and become significantly better) once this issue is addressed, and we get a binding for DO_CHANGE_SPEED. If I get a moment to tackle it, I may add the binding and pull request myself.

Hi pete! I have no idea how to direct message you cos im a complete newbie on this website lol, but heres the basic rundown.Im buying a drone with ardupiolot and i wanna use it for drone delivey. I wanna make an app that communicates with ardupilot which then communicates with the drone .so the customer chooses the location and the drone takesoff, scans for an april tag at the location(or maybe just wait for confirmation from the customer) and then lowers the parcel.and the customer must be able to see where the drone is and the camera view. I have no experience in coding and very little with drones so i have no idea where to start and it would be terrific if you could help me, thanks!

I feel remiss to have let this languish a bit. PR has been revised per Randy’s request and will hopefully be approved shortly.

I am also about to submit another PR to allow DO_CHANGE_SPEED behavior via scripting. The “TerrainDetector” example script will be a part of that PR.

Pull request submitted for DO_CHANGE_SPEED behavior as a scripting feature.

It looks like this will be merged fairly soon and adds a set_desired_speed() binding that will allow scripting to change the navigation speed on the fly in any autopilot assisted mode.

The included rover-TerrainDetector.lua example script builds upon the discussion from the live stream, slowing a Rover whenever G or pitch/roll rate transients exceed user-defined thresholds. @iampete was a great help in getting that script to create a set of custom parameters (ROUGH_*) for use in tuning detection and slowing behavior without editing the script directly.

1 Like

very cool!, I was looking for this function for boats to stop the boat getting damaged by launching its self off of waves when they get too high, this is a very good example of boats hitting waves too fast and getting massive Z axis G loads.

Using the terrain script on a boat, in theory it would slow down the boat as soon as the boat z axis limit is breached on the smaller wave so it doesnt launch off the larger ones.

With some tuning of the ROUGH_* parameters, I’m sure the script will be of value there!

1 Like

Yes I suspect the limits are going to be variable depending on the boats design and will need some test runs to find a good setting.

It could be easily modified to slow until user input is made to speed back up as well, if that’s a desired outcome.

1 Like

Both PRs (scripting examples and set_desired_speed()) have been merged!

1 Like