SDK Tutorial
A quick start guide for the Flyby SDK.
Download & Setup
The latest SDK release can be found here, and an example project can be found here.
The simplest way to get starting is by copying the example project structure and CMake file.
For this example, we will assume we have a payload that is composed of a single camera on a gimbal, and the camera produces one video stream.
Getting Started
The main entry point into the drone ecosystem is through the Drone
object. This object is how our new payload register itself with the drone and make itself available to the controller.
To create a new Drone
object, we use the DroneFactory::create_drone()
method. This returns a new shared_ptr
to the Drone
object.
auto drone = DroneFactory::create_drone();
Now that we have access to the drone, the next step is creating the Payload
object.
Payload
Every payload has to inherit from the flyby::Payload
object. Our new payload class should call the following base constructor:
Payload(const std::string& name, const std::string& version);
The Payload
object will contain all of our payload components, is solely responsible for creating these components. Payloads are composed of streams and components such as gimbals.
class SimplePayload : public Payload {
public:
SimplePayload() : Payload { "Simple Payload", "1.0.0" } {
// Construct payload components
}
~SimplePayload() override = default;
};
We can now register our payload object with the drone.
auto payload = std::make_shared<SimplePayload>();
drone->register_payload(payload);
Since our payload does not contain any components, we have no way of interacting with it through the controller. Let's fix that.
Components
Every payload component should inherit from its corresponding class. For example, cameras should inherit from Camera
, and gimbals should inherit from Gimbal
. The main responsibility of these objects is to connect the controller to the hardware, and we do so by overriding functionality that the hardware can provide. For example, a camera that can take pictures should override the take_picture
function, and that function should take a picture on the corresponding camera.
Gimbal
All gimbals should inherit from the Gimbal
object. Gimbals are controlled through the controller, which sends roll, pitch, and yaw values for the gimbal. The controller displays the current gimbal pitch, and so the gimbal class should override the get_pitch
function. In order for the controller to control the gimbal's movements, it should also override the set_roll_pitch_yaw_speed
function.
class SimpleGimbal : public Gimbal {
public:
SimpleGimbal() : Gimbal() {}
~SimpleGimbal() override = default;
void set_roll_pitch_yaw_speed(double roll, double pitch, double yaw) override {
// Set the speed on the gimbal
}
double get_pitch() const override {
// Return the current pitch of the gimbal
}
};
We can now revisit the SimplePayload
constructor to include our new gimbal.
SimplePayload() : Payload { "Simple Payload", "1.0.0" } {
auto m_gimbal = std::make_shared<SimpleGimbal>();
register_gimbal(m_gimbal);
// Construct payload components
}
Camera & Stream
Streams are composed of cameras, so let us focus on the camera object first. Similar to gimbals, cameras should inherit from the Camera
object and implement the functionality that they provide.
Suppose our camera can take videos, but does not have any picture functionality or zoom functionality. For video controls, we will set m_video = true
, and set the other two to false. Since our camera is mounted on our gimbal, we will set m_gimbal = true
so that, while viewing this camera's stream, we will be able to control the gimbal through the controller. These settings correspond to the UI visibility on the controller.
class SimpleCamera : public Camera {
public:
SimpleCamera() : Camera("Simple Camera") {
m_picture = false;
m_video = true;
m_zoom = false;
m_gimbal = true;
}
~SimpleCamera() override = default;
void start_video_recording() override {
m_is_recording = true; // Only set if the camera started recording
// Initiate video recording
}
void stop_video_recording() override {
m_is_recording = false; // Only set if the camera stopped recording
// Stop video recording
}
};
This camera object tells the controller that this camera is mounted on a gimbal and can take videos, and when the user presses the video buttons the controller they trigger the overriden functions that are present above.
With our camera object implemented, we can now focus on the stream. Streams are responsible for creating and owning their own camera objects, and starting some streaming method. For the former, we create our camera object in the constructor and register it with the stream.
class SimpleStream : public Stream {
public:
explicit SimpleStream() : Stream("Simple Stream") {
auto m_camera = std::make_shared<SimpleCamera>();
register_camera(m_camera);
}
~SimpleStream() override = default;
// Other functionality
}
With our stream object configured and our cameras set up, all that is left is to start an actual stream. The stream object will get a new endpoint to publish a stream to, and is responsible to specify when the stream is alive. We do this by overriding the start_stream
function.
void start_stream(
unsigned int endpoint_idx,
std::function<void(std::string)> set_alive_callback
) override {
// Publish a stream to rtsp://0.0.0.0:8554/<endpoint_idx>
// Can use any library, such as gstreamer or ffmpeg
set_alive_callback(get_uuid()); // Call when the stream is alive
}
Lastly, we update the payload constructor to register this stream as follows:
SimplePayload() : Payload { "Simple Payload", "1.0.0" } {
auto m_gimbal = std::make_shared<SimpleGimbal>();
register_gimbal(m_gimbal);
auto m_stream = std::mak_shared<SimpleStream>();
register_stream(m_stream);
}
Finally, we have created and registered all of the relevant payload components. All that is left to do is to start the payload server.
int main(int argc, char** argv) {
auto drone = DroneFactory::create_drone();
auto payload = std::make_shared<SimplePayload>();
drone->register_payload(payload);
drone->start_server();
}
Last updated
Was this helpful?