Welcome to the YADrone tutorial !
This tutorial will guide you through the first steps setting up a Java (not Android) project, connecting to the drone and getting the drone to do something.
Attention ! The API changed with version 0.3 ! The tutorial for YADrone 0.2.1 can be found [ here ].
0. Start
Before we get to the actual programming part, we need to set up our development environment, i.e. the YADrone project. This tutorial assumes you are working with eclipse, hence all steps refer to that IDE. Nevertheless, you might use an alternative IDE of your choice, because Section 1 onwards is independent of any IDE.
So, to create an eclipse Java project, follow these steps:
- Open eclipse
- Go to "File -> New ... -> Java Project" and give your project a nice name, e.g. "YADroneTutorial"
- Now download the "jar-file (Library only)" from the download section (you only need the jar, not the sources. The additional 3rd party libraries are mainly for the control center plugins). You may then proceed with Section 1 of this tutorial.
- Create a new directory, called "libs" in your Eclipse project and put the library in that directory.
- In order to add the library to your project's classpath, right-click on the jar in your lib-folder and choose "Build Path -> Add to Build Path" (see figure below)
- We're done with the first step. Your YADrone project is ready. In the next Section, we will create our first class and establish a connection with the drone.
1. Connecting your Application with the Drone
Connecting to the drone is no big deal IF and only if your Wifi is connected to the drone. The drone acts as a Wifi access point. Hence you need to establish a Wifi connection with your PC. Note, the connection in not encrypted (e.g. with WEP or WPA) and the drone assignes an IP address to your PC via DHCP. Hence you need no special configuration for the connection. If you have problems with the connection, please have a look at the [ FAQ ] !
- At first, we need to create a main class. Let's name it "TutorialMain".
- Then, simply add the following code snippet to your class. An explanation follows below.
public static void main(String[] args)
{
IARDrone drone = null;
try
{
drone = new ARDrone();
drone.start();
}
catch (Exception exc)
{
exc.printStackTrace();
}
finally
{
if (drone != null)
drone.stop();
System.exit(0);
}
}
-
Within this snippet, a new ARDrone object is instantiated. Upon calling start all managers (i.e. Command-, Configuration, NavData- and VideoManager) will begin their work: the CommandManager will continuously send commands to the drone to keep the connection upright, the drone in return will send NavData and a video stream. Moreover, the drone is configured to use default settings for max. altitude (10m) and speed.
Using this ARDrone object you may register listeners for NavData and video and exceptions (which will be explained in the next section) and you can control the real drone. Hence you can think of the ARDrone object as some kind of virtual counterpart or representative of your real drone.
2. Listening for NavData
NavData contains information about the current state of the drone, like battery level, altitude, pitch, roll, yaw, velocity and a lot of other flags used internally.
This data is sent by the drone quite frequently (~ 25 ms).
YADrone provides several listeners for different aspects, which are very easy to use as you will see in the following self-explanatory examples:
-
drone.getNavDataManager().addAttitudeListener(new AttitudeListener() {
public void attitudeUpdated(float pitch, float roll, float yaw)
{
System.out.println("Pitch: " + pitch + " Roll: " + roll + " Yaw: " + yaw);
}
public void attitudeUpdated(float pitch, float roll) { }
public void windCompensation(float pitch, float roll) { }
});
-
drone.getNavDataManager().addBatteryListener(new BatteryListener() {
public void batteryLevelChanged(int percentage)
{
System.out.println("Battery: " + percentage + " %");
}
public void voltageChanged(int vbat_raw) { }
});
- Note, all listeners are registered with the NavDataManager. You can get this instance via drone.getNavDataManager(). Have a look at all the add...Listener() methods to get an overview over all supported listeners. Some listener provide several callback methods (e.g. see the BatteryListener above) and some are for more experienced users (e.g. see voltageChanged above). Hence it is suggested to initially print out all variables upon callback to see what they look like.
3. Displaying Video
Listening for video frames is as easy as listening for NavData. You just have to register a listener which will receive individual images of the overall stream. You then have to draw these images onto whatever you want.
- At first, we need a new class, e.g. "TutorialVideoListener"
- This class shall paint the images received from the drone, hence it needs to extend JFrame and override the paint()-method as shown below
public class TutorialVideoListener extends JFrame
{
private BufferedImage image = null;
public TutorialVideoListener(final ARDrone drone)
{
super("YADrone Tutorial");
setSize(640,360);
setVisible(true);
}
public void paint(Graphics g)
{
if (image != null)
g.drawImage(image, 0, 0, image.getWidth(), image.getHeight(), null);
}
}
- Next, we only need to register this class as an ImageListener and repaint the frame's pane every time a new image is received:
drone.getVideoManager().addImageListener(new ImageListener() {
public void imageUpdated(BufferedImage newImage)
{
image = newImage;
SwingUtilities.invokeLater(new Runnable() {
public void run()
{
repaint();
}
});
}
});
Note, that the repaint()-method should be called from the GUI-thread, therefore we use SwingUtilities.invokeLater(...). That's all we need to do in order to display the drone's video stream.
-
The ARDrone has two cameras, one pointing forward and one pointing downwards. We can easily switch between those two streams as the following example shows:
addMouseListener(new MouseAdapter() {
public void mouseClicked(MouseEvent e)
{
drone.getCommandManager().setVideoChannel(VideoChannel.NEXT);
}
});
Now, when you click on the video, the camera is toggled (from horizontal to vertical and vice versa). Note: we use the CommandManager to toggle camera view, because switching the streams is a command which is processed by the drone !
-
And finally, when you close the window, the drone shall land and the connections to the drone shall be closed:
addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e)
{
drone.stop();
System.exit(0);
}
});
4. Listening for Exceptions
Exceptions may always occur for whatever reason, e.g. you forgot to establish a Wifi connection to the drone and hence no commands can be sent or navdata received. All communication with the drone is handled by threads, that's why a simple try-catch around statements is often not feasible. In order to cope with exceptions you need to register an ExceptionListener, which is called back once an exception occurs.
drone.addExceptionListener(new IExceptionListener() {
public void exeptionOccurred(ARDroneException exc)
{
exc.printStackTrace();
}
});
The ARDroneException is just a super class of possible exception types, e.g. CommandException, ConfigurationException, NavDataException or VideoException. Note: you might see some more errors be printed on the console. These mainly stem from the Xuggler video codec, which sometimes struggles with the drone's proprietary PaVE-header for video frames. You can ignore these.
5. Controlling the Drone
Controlling the drone is of course the most important part. YADrone offers several commands to achieve this. However, YADrone is an experimental framework and gives no guarantee to operate flawlessly !
Therefore, take responsible precautions when using YADrone !
The drone can be controlled via the CommandManager, which offers several methods not only for moving the drone up, down, left and right, spin the drone etc. but also for setting certain configuration options (e.g. toggling the camera view as seen above).
-
At first, we want to animate the LED lights of the drone:
drone.getCommandManager().setLedsAnimation(LEDAnimation.BLINK_ORANGE, 3, 10);
-
Now, let the drone takeoff, hover for 5 seconds and land again.
drone.getCommandManager().takeOff();
drone.getCommandManager().waitFor(5000);
drone.getCommandManager().landing();
-
And finally, we want to orchestrate the drone's flight:
CommandManager cmd = drone.getCommandManager();
int speed = 30; // percentage of max speed
cmd.takeOff().doFor(5000);
cmd.goLeft(speed).doFor(1000);
cmd.hover().doFor(2000);
cmd.goRight(speed).doFor(1000);
cmd.hover().doFor(2000);
cmd.forward(speed).doFor(2000);
cmd.hover().doFor(1000);
cmd.backward(speed).doFor(2000);
cmd.hover().doFor(2000);
cmd.landing();
Note: certain commands (e.g. all commands for movement) are continuously executed. They are called sticky. Therefore, if you e.g. want to fly forward for one second, the calling Thread needs to sleep for a certain amount of time, before the next command is issued. This is achieved by calling methods like doFor(ms), waitFor(ms) or after(ms). These three methods have the exact same semantics, only the names differ.
Sometimes, blocking the calling thread (i.e. sleep) is not desirable. In order to orchestrate the drone's flight asynchronously, you can use the schedule(ms, Runnable) command instead. Here is an example:
cmd.takeOff();
cmd.schedule(5000, new Runnable() {
public void run()
{
cmd.goLeft(speed);
// [...]
}
});
This way, takeoff() is called so the drone immediately takes off and five seconds later, the drone shall go left. The point is that no threads are blocked, after calling schedule you immediately get the control flow back.
One last aspect to mention is the possibility of command chaining. You are able to build arbitrary command sequences like cmd.takeOff().doFor(5000).goLeft(speed).doFor(1000).hover() ....
If you successfully finished this tutorial, you may now want to play around with all the other features of YADrone. The [ architecture overview ] and the [ API documentation ] are good starting points to proceed.
[ Back ]
|