Control a drone with keyboard using MavSDK

Hi,
I am trying to write a script that allows the user to control a simulated drone (simulated in Gazebo) using the ‘w’, ‘a’, ‘s’, and ‘d’ keys. My main code gets the keypress by subscribing to a publisher node that takes in the user’s keypress.
My drone is taking off to 1 meter, but as soon as I hit any key to change the attitude of the drone, the drone drops to the floor and then takes the change in attitude. the drone is responding to the change in attitude but the altitude is not being maintained. My code is structured in a way that the altitude should be maintained first then the attitude change should take place, but the drone is still dropping to the floor as soon as a key is pressed.

This is my main code

#!/usr/bin/env python3

import rospy
from std_msgs.msg import String
import asyncio
from mavsdk import System
from mavsdk.offboard import Attitude, OffboardError, PositionNedYaw

key_pressed = None  # Variable to store the key press

# Callback function for the keyboard input
def keyboard_callback(data):
    global key_pressed
    key_pressed = data.data

# Drone control logic
async def control_drone(drone):
    global key_pressed

    # Hover at 1 meter initially
    await drone.offboard.set_position_ned(PositionNedYaw(0.0, 0.0, -1.0, 0.0))
    await asyncio.sleep(2)  # Hover for 2 seconds

    while not rospy.is_shutdown():
        if key_pressed:
            key = key_pressed

            if key in ['w', 's', 'a', 'd', 'q', 'e']:
                await drone.offboard.set_position_ned(PositionNedYaw(0.0, 0.0, -1.0, 0.0))  # Maintain 1 meter altitude

                if key == 'w':
                    await drone.offboard.set_attitude(Attitude(30.0, 0.0, 0.0, 0.6))
                    await asyncio.sleep(1)
                    await drone.offboard.set_attitude(Attitude(0.0, 0.0, 0.0, 0.6))
                elif key == 's':
                    await drone.offboard.set_attitude(Attitude(-30.0, 0.0, 0.0, 0.6))
                    await asyncio.sleep(1)
                    await drone.offboard.set_attitude(Attitude(0.0, 0.0, 0.0, 0.6))
                elif key == 'a':
                    await drone.offboard.set_attitude(Attitude(0.0, 30.0, 0.0, 0.6))
                    await asyncio.sleep(1)
                    await drone.offboard.set_attitude(Attitude(0.0, 0.0, 0.0, 0.6))
                elif key == 'd':
                    await drone.offboard.set_attitude(Attitude(0.0, -30.0, 0.0, 0.6))
                    await asyncio.sleep(1)
                    await drone.offboard.set_attitude(Attitude(0.0, 0.0, 0.0, 0.6))
                elif key == 'q':
                    await drone.offboard.set_attitude(Attitude(0.0, 0.0, 30.0, 0.6))
                    await asyncio.sleep(1)
                    await drone.offboard.set_attitude(Attitude(0.0, 0.0, 0.0, 0.6))
                elif key == 'e':
                    await drone.offboard.set_attitude(Attitude(0.0, 0.0, -30.0, 0.6))
                    await asyncio.sleep(1)
                    await drone.offboard.set_attitude(Attitude(0.0, 0.0, 0.0, 0.6))


            key_pressed = None  # Reset the key_pressed variable after processing
        await asyncio.sleep(0.1)  # Adjust the sleep time as needed

async def run():
    drone = System()
    await drone.connect(system_address="udp://:14540")

    print("Waiting for drone to connect...")
    async for state in drone.core.connection_state():
        if state.is_connected:
            print("-- Connected to drone!")
            break

    print("Waiting for drone to have a global position estimate...")
    async for health in drone.telemetry.health():
        if health.is_global_position_ok and health.is_home_position_ok:
            print("-- Global position estimate OK")
            break

    print("-- Arming")
    await drone.action.arm()

    #print("-- Taking off")
    #await drone.action.takeoff()

    print("-- Setting initial setpoint")
    await drone.offboard.set_attitude(Attitude(0.0, 0.0, 0.0, 1))

    print("-- Starting offboard")
    try:
        await drone.offboard.start()
    except OffboardError as error:
        print(f"Starting offboard mode failed with error code: \
              {error._result.result}")
        print("-- Disarming")
        await drone.action.disarm()
        return

    # ROS Node initialization and subscriber
    rospy.init_node("keyboard_subscriber")
    rospy.Subscriber("keyboard_input", String, keyboard_callback)

    try:
        await control_drone(drone)  # Control the drone based on subscribed key presses
    except KeyboardInterrupt:
        print("\nExiting due to Ctrl+C")
    finally:
        await drone.offboard.stop()
        await drone.action.land()

if __name__ == "__main__":
    asyncio.run(run())

This is my Keypress publisher node

#!/usr/bin/env python3

import rospy
from std_msgs.msg import String
import sys, select, termios, tty

def getKey():
    tty.setraw(sys.stdin.fileno())
    rlist, _, _ = select.select([sys.stdin], [], [], 0.1)
    if rlist:
        key = sys.stdin.read(1)
    else:
        key = ''
    termios.tcsetattr(sys.stdin, termios.TCSADRAIN, settings)
    return key

if __name__ == "__main__":
    rospy.init_node("keyboard_publisher")

    key_pub = rospy.Publisher("keyboard_input", String, queue_size=10)

    settings = termios.tcgetattr(sys.stdin)

    rate = rospy.Rate(10)  # Adjust as needed

    print("Listening for keyboard input... Press down 'Ctrl+C' for more than 1 sec to exit.")
    try:
        while not rospy.is_shutdown():
            key = getKey()

            if key:
                rospy.loginfo(f"Key pressed: {key}")
                key_pub.publish(key)

            rate.sleep()
    except KeyboardInterrupt:
        print("\nExiting due to Ctrl+C")

I use the “make px4_sitl gazebo” to bring up the drone simulation in Gazebo and to have PX4 as SITL. And I am working with ROS1 in a Ubuntu 20.04 environment.

Could anyone please help me to understand what i am doing wrong?

check this video