Mission planning with the SDK
The SDK supports creating and running missions on the drone using the mission
attribute of the Drone
class. Missions are created using a set of instructions that define the actions the drone should perform.
Creating a mission
As an example we will create a mission that goes to the seabed, takes a picture with the main camera, and returns to the surface.
First we define the instructions we want to use. The available instructions are outlined in the Instruction
class.
import blueye.protocol as bp
go_to_seabed = bp.Instruction(go_to_seabed_command={"desired_speed": 0.3})
take_picture = bp.Instruction(camera_command={
"camera_action": bp.CameraAction.CAMERA_ACTION_TAKE_PHOTO
})
go_to_surface = bp.Instruction(go_to_surface_command={"desired_speed": 0.3})
Next we create the mission using these instructions. The mission is created by passing a list of instructions to the prepare_new_mission
function.
from blueye.sdk.mission import prepare_new_mission
go_to_seabed_mission = prepare_new_mission(
instruction_list = [go_to_seabed, take_picture, go_to_surface],
mission_id = 0,
mission_name = "Go to seabed and take a picture",
)
Loading and running the mission
With the mission created we can now transfer it to the drone and run it. The easiest way to do this is to use the load_and_run
method, which will transfer the mission the drone, wait for it to become ready and then start the mission.
from blueye.sdk import Drone
d = Drone()
d.mission.load_and_run(go_to_seabed_mission)
Getting status updates from the mission
The mission progress is published through the NotificationTel
messages. These messages can be read manually with the usual telemetry methods, ie. telemetry.get
or telemetry.add_msg_callback
.
Alternatively, if one initializes the Drone object with log_notifications=True
, the notifications will be logged with pythons logging
module. This is the recommended way to get notified about mission progress.
from blueye.sdk import Drone
d = Drone(log_notifications=True)
The termial output can however quickly become cluttered when the logs are being printed inbetween the program output. In such cases, it can be useful to run the program in one terminal and then run a separate terminal to read the logs. This can be accomplished by configuring a simple TCP server to listen for log messages. See the Receiving logs in another terminal section for an example of how to do this.
Exporting to JSON
The mission can be exported to a JSON file using the export_to_json
method. This allows you to save the mission for later use or share it with others. It is also possible to load the json file in the Blueye App.
import blueye.protocol as bp
from blueye.sdk.mission import export_to_json, prepare_new_mission
# Create a mission
mission = prepare_new_mission(
instruction_list=[bp.Instruction(go_to_seabed_command={"desired_speed": 0.3})]
)
# Export the mission to a JSON file
export_to_json(mission, "exported_mission.json")
Importing from JSON
You can also import a mission from a JSON file using the import_from_json
method. This allows you to load a previously saved mission and run it on the drone.
from blueye.sdk import Drone
from blueye.sdk.mission import import_from_json
mission = import_from_json("exported_mission.json")
d = Drone()
d.mission.load_and_run(mission)
Examples
Here are some examples outlining how to use some of the mission planning features
Tilt camera
This is a simple example that tilts the camera up and down. Useful for testing with the drone out of the water.
import logging
import logging.handlers
import time
import blueye.protocol as bp
from blueye.sdk import Drone
from blueye.sdk.mission import prepare_new_mission
# Publish runtime logs over TCP (including mission status notifications)
logger = logging.getLogger("blueye.sdk")
logger.setLevel(logging.DEBUG)
socket_handler = logging.handlers.SocketHandler(
"localhost", logging.handlers.DEFAULT_TCP_LOGGING_PORT
)
logger.addHandler(socket_handler)
# Create some instructions for the mission
tilt_camera_center = bp.Instruction(tilt_main_camera_command={"tilt_angle": {"value": 0.0}})
tilt_camera_top = bp.Instruction(tilt_main_camera_command={"tilt_angle": {"value": 30.0}})
tilt_camera_bottom = bp.Instruction(tilt_main_camera_command={"tilt_angle": {"value": -30.0}})
wait = bp.Instruction(wait_for_command={"wait_for_seconds": 4})
# Create a mission with the instructions
mission = prepare_new_mission(
instruction_list=[tilt_camera_top, wait, tilt_camera_bottom, wait, tilt_camera_center, wait],
mission_id=0,
mission_name="Tilt camera",
)
# Establish a connection to the drone
d = Drone(log_notifications=True)
# Send the mission to the drone and start it
d.mission.load_and_run(mission)
# Wait until the mission state becomes MISSION_STATE_COMPLETED
while d.mission.get_status().state != bp.MissionState.MISSION_STATE_COMPLETED:
time.sleep(0.1)
print("Mission completed successfully!")
Go to seabed
Another simple example outlining how to create some simple instructions and run them on the drone. This example goes to the seabed, takes a picture with the main camera, and returns to the surface.
import logging
import logging.handlers
import time
import blueye.protocol as bp
from blueye.sdk import Drone
from blueye.sdk.mission import prepare_new_mission
# Set up logging
logger = logging.getLogger("blueye.sdk")
logger.setLevel(logging.DEBUG)
socket_handler = logging.handlers.SocketHandler(
"localhost", logging.handlers.DEFAULT_TCP_LOGGING_PORT
)
logger.addHandler(socket_handler)
# Create some instructions for the mission
go_to_seabed = bp.Instruction(go_to_seabed_command={"desired_speed": 0.3})
take_picture = bp.Instruction(
camera_command={"camera_action": bp.CameraAction.CAMERA_ACTION_TAKE_PHOTO}
)
go_to_surface = bp.Instruction(go_to_surface_command={"desired_speed": 0.3})
# Create a mission with the instructions
mission = prepare_new_mission(
instruction_list=[go_to_seabed, take_picture, go_to_surface],
mission_id=0,
mission_name="Go to seabed and take a picture",
)
# Establish a connection to the drone
d = Drone(log_notifications=True)
# Send the mission to the drone and start it
d.mission.load_and_run(mission)
# Wait until the mission state becomes MISSION_STATE_COMPLETED
while d.mission.get_status().state != bp.MissionState.MISSION_STATE_COMPLETED:
time.sleep(0.1)
print("Mission completed successfully!")
Go to waypoints
This example shows how one can create multiple waypoints and have the drone go to each of them in sequence.
import logging
import logging.handlers
import time
import blueye.protocol as bp
from blueye.sdk import Drone
from blueye.sdk.mission import create_waypoint_instruction, prepare_new_mission
# Publish runtime logs over TCP (including mission status notifications)
logger = logging.getLogger("blueye.sdk")
logger.setLevel(logging.DEBUG)
socket_handler = logging.handlers.SocketHandler(
"localhost", logging.handlers.DEFAULT_TCP_LOGGING_PORT
)
logger.addHandler(socket_handler)
# Create some waypoints in a (roughly) square pattern
# 10.3840°E 10.3841°E
# B ------------------ C 63.4612°N
# | |
# | |
# | |
# A ------------------ D 63.4610°N
wp_a = create_waypoint_instruction("Point A", 63.4610, 10.3840, 10)
wp_b = create_waypoint_instruction("Point B", 63.4612, 10.3840, 10)
wp_c = create_waypoint_instruction("Point C", 63.4612, 10.3842, 10)
wp_d = create_waypoint_instruction("Point D", 63.4610, 10.3842, 10)
# Create a mission with the instructions
mission = prepare_new_mission(
instruction_list=[wp_a, wp_b, wp_c, wp_d, wp_a],
mission_id=0,
mission_name="Go to waypoints",
)
# Establish a connection to the drone
d = Drone(log_notifications=True)
# Send the mission to the drone and start it
d.mission.load_and_run(mission)
# Wait until the mission state becomes MISSION_STATE_COMPLETED
while d.mission.get_status().state != bp.MissionState.MISSION_STATE_COMPLETED:
time.sleep(0.1)
print("Mission completed successfully!")