Request for an Air SDK mission example with relative movement

Hello,
I have read the documentation on the AirSDK and I’m having a little trouble getting started with the example you give for making the drone do an automatic patrol.

My idea would be to start with a course with relative displacements (take off, 2m forward, 90°, 2m forward … etc… then land alone)

Is it possible to have an example of an Air SDK mission that does this? In the simplest way possible.

Hello @LouisGenetec,

This is a simple example to draw a square with relative displacements.

First, a new guidance mode needs to be added in Flying mode:

    autopilot-plugins
             └── fsup
                  ├──flying << NEW_FOLDER
                  |    ├── __init__.py
                  |    └── stage.py
                  ├── __init__.py
                  └── mission.py

That is the code of the file stage.py:

from fsup.utils import is_msg
from fsup.genstate import State, guidance_modes

from fsup.missions.default.flying.stage import FLYING_STAGE as DEF_FLYING_STAGE

import guidance.relative_move_pb2 as rm_pb

_MOVE_ALTITUDE = 0
_MOVE_FORWARD = 1
_ROTATION = 2

@guidance_modes("mission_relative_move")
class MovePolygon(State):
    def enter(self, msg):

        self.distance = 10
        self.altitude = -1
        self.counter = 4
        self.yaw_drone = (360.0 / float(self.counter)) * np.pi / 180.0
        self.is_last_move = False
        self.last_action = _MOVE_ALTITUDE

        dis = rm_pb.Displacement(
            dx=0, dy=0, dz=self.altitude, dyaw=0
        )
        cfg = rm_pb.Config(
            displacement=dis, last_move=self.is_last_move
        )
        self.set_guidance_mode("relative_move", cfg)

    def step(self, msg):
        # Repeat the guidance mode "mission_relative_move" until the drone
        # arrives at its starting position
        if is_msg(msg, rm_pb.Event, "move_validated"):
            if self.counter > 0:
                if self.last_action == _MOVE_FORWARD:
                    dis = rm_pb.Displacement(
                        dx=0, dy=0, dz=0, dyaw=self.yaw_drone
               )
                    if self.counter == 1:
                        self.is_last_move = True
                    self.counter -= 1
                    self.last_action = _ROTATION
                else:
                    dis = rm_pb.Displacement(
                        dx=self.distance, dy=0, dz=0, dyaw=0
                    )
                    self.last_action = _MOVE_FORWARD

                cfg = rm_pb.Config(
                    displacement=dis, last_move=self.is_last_move
                )
                self.set_guidance_mode("relative_move", cfg)

MOVE_POLYGON_STATE = {
    "name": "move_polygon",
    "class": MovePolygon,
}

FLYING_STAGE = {
    "name": "flying",
    "class": DEF_FLYING_STAGE["class"],
    "initial": "manual",
    "children": [child for child in DEF_FLYING_STAGE["children"]]
    + [MOVE_POLYGON_STATE],
}         

And this is the code of the file mission.py:

from fsup.genmission import AbstractMission
from fsup.utils import msg_id

###################################################
# Stages and transitions

from fsup.missions.default.ground.stage import (
    GROUND_STAGE as DEF_GROUND_STAGE,
)
from fsup.missions.default.takeoff.stage import (
    TAKEOFF_STAGE as DEF_TAKEOFF_STAGE,
)
from fsup.missions.default.hovering.stage import (
    HOVERING_STAGE as DEF_HOVERING_STAGE,
)
from fsup.missions.default.landing.stage import (
    LANDING_STAGE as DEF_LANDING_STAGE,
)
from fsup.missions.default.critical.stage import (
    CRITICAL_STAGE as DEF_CRITICAL_STAGE,
)

from fsup.missions.default.mission import TRANSITIONS as DEF_TRANSITIONS

###################################################
# Messages

# to receive message from guidance relative_move mode
import guidance.relative_move_pb2 as rm_pb
# to receive message from guidance ascent mode
import guidance.ascent_pb2 as gdnc_ascent_msgs

###################################################
# UID

UID = "com.examplecompanyname.missions.move-polygon"

###################################################
# Overwritten Stages

from .flying.stage import FLYING_STAGE 

###################################################
# Mission

class Mission(AbstractMission):
    def __init__(self, env):
        super().__init__(env)
        # Init guidance modes message services
        self.gdnc_relative_move_msgs = None

    def on_load(self):
        # Set guidance channel and message services registration
        # To get message from relative_move guidance mode
        self.gdnc_relative_move_msgs = self.mc.attach_client_service_pair(
            self.mc.gdnc_channel, rm_pb, True
        )

    def on_unload(self):
        # Guidance channel is cleaned by message center
        self.mc.detach_client_service_pair(self.gdnc_relative_move_msgs)
        self.gdnc_relative_move_msgs = None

    def on_activate(self):
        pass

    def on_deactivate(self):
        pass

    def states(self):
        return [
            DEF_GROUND_STAGE,
            DEF_TAKEOFF_STAGE,
            DEF_HOVERING_STAGE,
            FLYING_STAGE,
            DEF_LANDING_STAGE,
            DEF_CRITICAL_STAGE,
        ]

    def transitions(self):

        return TRANSITIONS + DEF_TRANSITIONS

GdncAscent = lambda evt: msg_id(gdnc_ascent_msgs.Event, evt)
MissionRelativeMove = lambda evt: msg_id(rm_pb.Event, evt)

TRANSITIONS = [
    [GdncAscent("done"), "takeoff", "flying.move_polygon"],
    [MissionRelativeMove("done"), "flying.move_polygon", "flying"],
]

When the mission is loaded into the drone, just send a takeoff command. Once the drone is flying, the mission start automatically and the drone “draw a square”.

Hello, thank you for your answer. I will test your code as soon as possible on the Sphinx simulator. I will come back to this post to keep you informed

This topic was automatically closed after 30 days. New replies are no longer allowed.