Script to get takeoff yaw and use it at landing

Hi Guys,

I am new to Lua but have been watching a lot of videos on Lua and ardupilot and managed to get started but am not able to get it working.

I am trying to create a simple script to run after the drone is armed and capture the Yaw position to be used when the “LAND” command is called in an Auto Mission. So when the drone takes off it will land with the same orientation as when it took off.

Here is what I have managed to get running but it’s not changing the drone’s YAW when landing.

Any help would be greatly appreciated.

Thank you

Here is the script that I was able to piece together:

local takeoffYaw = nil – variable to store the yaw angle at takeoff
local landingYaw = nil – variable to store the desired yaw angle at landing
local takeoffYawRad = nil – variable to store the yaw angle at takeoff in radians

local armed = false
local landed = false – flag to track if the vehicle has landed

function update()
if not arming:is_armed() then
armed = false – vehicle is disarmed
return update, 100

if not armed then -- vehicle just got armed
    armed = true

    -- Get the takeoffYaw every time the vehicle is armed
    takeoffYaw = math.deg(ahrs:get_yaw()) -- record the yaw angle at takeoff
    takeoffYawRad = ahrs:get_yaw() -- record the yaw angle at takeoff in radians
    gcs:send_text(0, "Takeoff yaw recorded: " .. takeoffYaw)

if takeoffYaw then -- if takeoffYaw is set
    if not landingYaw then -- if landingYaw is not set
        landingYaw = takeoffYaw -- set the desired yaw angle at landing to match takeoff yaw
        gcs:send_text(0, "Desired yaw at landing: " .. landingYaw)
        local currentYaw = math.deg(ahrs:get_yaw()) -- get the current yaw angle
        local yawDifference = currentYaw - takeoffYaw -- calculate the difference between current yaw and takeoff yaw
        -- Check if the drone is approaching the landing stage
        if vehicle:get_mode() == "LAND" and not landed then
            gcs:send_text(0, "Yaw difference at landing: " .. yawDifference)
            landed = true -- mark the vehicle as landed

return update, 1000 -- reschedule the loop


return update() – run immediately before starting to reschedule

I didn’t set out to write a complete script, but it got a little tricky to find the right examples, so I ended up writing something that should work, though it’s not a great solution.

If you aren’t using a yaw-enabled gimbal, it should be possible to use the mount:set_roi_target() or mount:set_angle_target() binding to achieve your intent without modifying the mission (at least according to the binding’s intent), but I have yet to make that work. @iampete, any idea why that’s not working?

Technically, MavLink land commands are supposed to support a yaw argument, but I don’t think ArduPilot supports that (yet). With the advent of precision landing, I know there’s been a bit of discussion on the topic. I don’t know where that stands. I did try a few things in SITL, but it appears that the yaw argument is ignored for the moment.

Instead, this script inserts a DO_SET_ROI before the landing waypoint that is offset by at least 1 km in the direction of the takeoff heading. After disarming or a mode change away from auto, it overwrites the inserted ROI command with the previous landing command. Since there is no (scripted) way to delete a waypoint without clearing the entire mission, you are left with an extra land command at the end.

If there are waypoints after the land command, this script is problematic. Also, if you are using a yaw-enabled gimbal, it will simply point the camera toward the takeoff heading rather than the whole copter. However, that’s the best I can do for now without forcing a switch to guided mode or spending more time doing mental gymnastics.

copter-land-yaw.lua (2.5 KB)

@Yuri_Rage Thank you so much, I have spent the last few days watching your videos and trying 100s of codes with the help of chatGBT and Brad and only started using VS Code for the first time 2 days ago. But that explains why I was getting stuck and also wasn’t happy with the “get_yaw()”.

I am using the cube and irlock so will be interesting to see how this works.

I have tested your script and it works fine in the sim.