Control of the throttle using LUA Script

Hi,
I’m getting the height of the drone using “rangefinder:distance_cm_orient(25)”
I would like to be able to modify the throttle (increase or decrease) depending of height of the drone.
I’m using the command “vehicle:set_target_throttle_rate_rpy(throttle, 0, 0, 0)” in “Stabilized” mode but nothing is happening.

I have tried many different value for “throttle” but with no success.

btw “vehicle:get_mode()” is working fine.

Thanks for advice.

Sam_4.lua (1.8 KB)

You’ll probably want to use an RC override for that, but what’s the goal? Why script control of stabilized mode? That seems somewhat dangerous…

Hi Yuri,
Thanks for asking.
The stabilzed mode balance perfectly but the drone is going up and down all the time. Today to stabilized it at the right distance above the surface i need to accelerate or decelerate manually.
I would like to find a way that the drone correct himself (autonomusly).
It looks like a boat but under the water there is a plane with flaps, Video of test, height difficulties

EDIT: I see you’re using a very unconventional vehicle, and “altitude” is probably speed dependent. Try an RC override command in Lua.

Thanks for your help. your right it’s quite an “unconventional vehicle” ! :rofl:
I did not find any exemple of “RC Override command in Lua”… if you have any advice.

My purpose was to use (like in “plane_aerobatics.lua”) “vehicle:set_target_throttle_rate_rpy(throttle, 0, 0, 0)” where it seems to work.

Plane aerobatics use guided mode, which is probably counter to your goal. Here’s the RC override example:

ardupilot/libraries/AP_Scripting/examples/RC_override.lua at master · ArduPilot/ardupilot (github.com)

There’s also SRV_Channels:set_output_norm(), but I don’t think that will work in stabilized mode where RC throttle commands are expected.

Hi,
Yes you’re right could be a good idea to override ! (because as i have reverse and forward throttle, in Auto mode it’s going back…)
I have tested the script that you have joint.
I’m able to get the pwm of the throttle using (rc:get_pwm(3)) but “set_override” command generate an “attempt to call a nil value (method set_overrride)”
I have tried to use different channel but I got the same error.

I was thinking that maybe “RC4 = rc:get_channel(3)” was not working properly.
But I did not sucess to print on the screen RC4 (RC_Channel_ud) (integer, float string not working)… to test it.

Something like this should work. I did not test it, so please do not put it on your vehicle directly without some refinement.

It is not adequate to simply retrieve the RC throttle pwm and manipulate it, since we are intentionally overriding it, so we must look at current output state and normalize it against RC values.

local UPDATE_MS = 10
local THROTTLE_RC = 3

local throttle_min = param:get(('RC%d_MIN'):format(THROTTLE_RC))
local throttle_trim = param:get(('RC%d_TRIM'):format(THROTTLE_RC))
local throttle_max = param:get(('RC%d_MAX'):format(THROTTLE_RC))
local throttle_reversed = param:get(('RC%d_REVERSED'):format(THROTTLE_RC))

local throttle_ch = rc:get_channel(THROTTLE_RC)

local function get_throttle_rc_pwm()
    local throttle_percent = motors:get_throttle()
    if throttle_reversed > 0 then
        throttle_percent = -throttle_percent
    end
    if throttle_percent < 0 then
        return throttle_trim - math.floor((throttle_min - throttle_trim) * throttle_percent)
    end
    return math.floor((throttle_max - throttle_trim) * throttle_percent) + throttle_trim
end

function update()
    if not arming:is_armed() then return update, UPDATE_MS end

    local throttle_pwm = get_throttle_rc_pwm()

    -- manipulate the override value here - this example just quickly ramps to max throttle
    throttle_pwm = math.max(throttle_pwm + 1, 2200)

    throttle_ch:set_override(throttle_pwm)

    return update, UPDATE_MS 
end

return update()
1 Like

I made a minor error in my first post of the example above. It’s corrected now. You may find that you need to employ some sort of process control (like PI or PID) to get good results.

Your very kind to work like this…

after several tests :

throttle_min = Ok (1095)
throttle_trim =Ok (1535)
throttle_max = Ok (1935)

“throttle_reversed” is not changing (0) even if I move throttle forward and backward but it’s not an issue because we are always in forward direction when monitoring throttle to adjust height above water.

motors:get_throttle() is not working (I read doc it could be because I’m in plane mode)
but it’s not an issue because I have the value through “rc:get_pwm(THROTTLE_RC)”

But the mean issue is that i still have an “attempt to call a nil value (method set_overrride)”

And I’m unable to check the return of “throttle_ch = rc:get_channel(THROTTLE_RC)”

throttle_reversed is to detect a reversed RC channel. It will remain static after the param lookup.

Not sure why you’re seeing the other errors. I can look into it later. Possibly a version mismatch. Confirm you are using 4.4? Is your RC transmitter connected while testing?

The motors binding should work with Plane or Copter alike. It may return an error if disarmed.

Again, you can’t just read the RC channel input value because you are overriding it…

Hi,

I have updated my version to 4.4 and now command “override” is working ! (i thought i’d already done it… thanks for asking)

In script joint when Mode is stabilized it increase or decrease autonomously depending of the height above surface. (but you loose control throught RC)
And when back to manuel mode you get control of throttle again !

That is great ! Without your help youri i would never manage it. many thanks.

Override_throttle.lua (3.3 KB)

PS : how can I directly write you in pm ?

It seems that the “override command” when not used after a certain delay x MS cancels the modifications done and comes back to the RC value.
Do we have access to that delay ?

Glad you got things working. I don’t think we can modify the timeout via that binding. You might be able to use the new MavLink Lua bindings and send an RC override that way, which takes timeout as an argument, but there’s a limit to that as well, and I think it’s something like 3 seconds.

1 Like

Hi yuri i want to land my vehicle in specific waypoint with lua script
i use this function vehicle:set_target_location(target_loc) but my vehicle slowly descent and not land at my target location how do i do that?

This really has nothing to do with the topic where you posted.

But there’s no need to use Lua for that. Use AUTO mode and set a LAND waypoint.

thanks for your answer i want to know that in this function vehicle:set_target_posvel_NED(target_pos, target_vel) how do i caculate target pos and target vel

Even your question is a moving target (using different bindings with each iteration of it), and you’ve been about as specific as my sister’s kids trying to decide on a dinner option.

Here’s an example that uses the latest binding you mentioned:
ardupilot/libraries/AP_Scripting/examples/set_target_posvel_circle.lua at master · ArduPilot/ardupilot (github.com)

And here’s an example using the other one you tried:
ardupilot/libraries/AP_Scripting/examples/set-target-location.lua at master · ArduPilot/ardupilot (github.com)

I still think you probably don’t need to use scripting to achieve your intent, and if you’re having this much trouble, it’s probably best to explore another option.

1 Like

thank you. excuse me i want to answer another question in this function vehicle:set_target_posvel_NED(target_pos, target_vel) when i use this function in update function, does it need to update velocity frequently?