As some of you may know, I have left Tokyo and the world of industrial robotics and am now in the midst of immersing myself in the world of drones in San Francisco. Its a very exciting time in my life! Among other things, I did some research into the different drone platforms out there.
As a sample exercise, I took an in-depth look at how I’d go about integrating a laser altimeter on to the 3DR Pixhawk.
All signs of googling point to the SF02/F laser altimeter as the quickest option to get something working.
Specs:
Pros:
Cons:
Alternatives:
To address some of the SF02’s cons (and given that we’re equipping a fleet), I looked for an alternate sensor on Alibaba. If you’re not familiar with Alibaba, it is basically a way to buy wholesale electronics / components / sub-assemblies directly from Chinese suppliers. The best option I found for a laser rangefinder module is this sensor. It is $100 - $300, so potentially a third of the cost per unit compared to the SF02, which is a massive savings. The range is also much better (says 10 - 800 m). Details on power consumption and how to interface with it are not clear, but I’m sure talking with the manufacturer (which is easy on Alibaba) would clear that up. Finally, the stated minimum distance (10 m) and accuracy (1 m vs. the SF02’s 1 cm) is pretty bad and won’t be useful for landings.
This sensor is intriguing but not yet available. Good to keep an eye on, especially since 3DR seems to be supporting it. Far cheaper and smaller but still only a 40 m range.
So while these other sensors may potentially work, for the sake of this analysis I’m going to with the SF02.
The wiring from the SF02 to the Pixhawk goes like this:
Pixhawk UART pin | SF02/F pin | Comment |
---|---|---|
1 / +5V | 3 / +5V | Power supply |
2 / TX | 9 / RX | 3.3V UART SF02/F receive |
3 / RX | 8 / TX | 3.3V UART SF02/F transmit |
6 / GND | 2 / - | Ground |
Since the SF02 uses screw terminals, depending on how much the aircraft vibrates it may be a good idea to soldier up the leads to the screw terminal. This is the cable / connector you’d use. Plug the SF02 into TELEM2 of the Pixhawk.
You’ll want to put the sensor pointing at the ground obviously, keeping it perpendicular to the aircraft. The sensor should also be mounted in a recessed position so that the optics arn’t scratched during a rough landing. Also, it should be positioned such that it doesn’t mess with the center of gravity for the aircraft otherwise it will affect glide characteristics.
Drivers
The sf0x driver needed for the Pixhawk is already part of the firmware. To start the driver:
Drivers
The sf0x driver needed for the Pixhawk is already part of the firmware. To start the driver:
sf0x start
And to run a test and verify the sensor is working:
sf0x test
Add a file called etc/extras.txt
to your microSD card with this content to autostart the driver:
sf0x start
Receiving sensor data in your PX4 application
PX4 has some great hardware abstraction, so we don’t have to directly interact with the driver at all. Instead, we subscribe to inter-process messages published by the sensor driver. In order to get data from the laser rangefinder, we need to subscribe to the topic that it publishes on. This is a good resource on how to do that. Looking at the source for the sf0x
driver, we need to subscribe to the sensor_range_finder
topic which comes from drivers/drv_range_finder.h
. So in our application we’d subscribe like this:
#include <drivers/drv_range_finder.h>
..
int rangefinder_sub_fd = orb_subscribe(ORB_ID(sensor_range_finder));
To actually get data out of the subscriber, we need to use the poll()
POSIX system call. This approach will sleep the thread (consuming no CPU cycles) until data from the sensor actually gets published. We achieve this like so:
#include <poll.h>
#include <drivers/drv_range_finder.h>
..
int rangefinder_sub_fd = orb_subscribe(ORB_ID(sensor_range_finder));
/* one could wait for multiple topics with this technique, just using one here */
struct pollfd fds[] = {
{ .fd = rangefinder_sub_fd, .events = POLLIN },
};
while (true) {
/* wait for sensor update of 1 file descriptor for 1000 ms (1 second) */
int poll_ret = poll(fds, 1, 1000);
if (fds[0].revents & POLLIN) {
/* obtained data for the first file descriptor */
struct range_finder_report rangefinder_data;
/* copy rangefinder data into local buffer */
orb_copy(ORB_ID(sensor_range_finder), rangefinder_sub_fd, &rangefinder_data);
printf("Rangefinder distance:\t%8.4f\t%8.4f\t%8.4f\n", (double)rangefinder_data.distance[0]);
}
}
The code snippet above isn’t a complete application, but you get the idea. Once the range finder data is copied into that range_finder_report
struct instance, the sky is the limit (pun intended) for what you want to do to it. This is where higher level, application specific things get implemented. Some things I can think of to do with altimeter data:
Without knowing any more details about the exact application, I think this is where I’ll stop.
Written by Lucas Doyle