4.2 Simple Depth Reader¶
Time Required: ~10 minutes
Thirsting for more knowledge after finishing the Hello World Tutorial? Now that you’ve mastered some of the basic concepts of Astra, let’s read the depth stream from our Astra using another Astra feature.
By the end of this tutorial you should be familiar with:
- The purpose of the
FrameListener
class - How to define a
FrameListener
- Using a
FrameListener
to process a depth stream
Before We Begin¶
- Download and decompress the latest Astra SDK, if you haven’t already.
- Using your favorite IDE, set up a new console application project and create a new source file called “main.cpp”.
- Copy the following into your main.cpp file:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | #include <astra/astra.hpp>
// for std::printf
#include <cstdio>
int main(int argc, char** argv)
{
astra::initialize();
astra::StreamSet streamSet;
astra::StreamReader reader = streamSet.create_reader();
reader.stream<astra::DepthStream>().start();
// Your code will go here
astra::terminate();
return 0;
}
|
- Line 7 - Initializes Astra
- Line 9 - Constructs a
StreamSet
- Line 10 - Creates a
StreamReader
- Line 12 - Starts a depth stream
- Line 16 - Terminates Astra
Listening to Streams¶
In the Hello World tutorial, we processed a stream of frames by looping over a call to our StreamReader
’s get_latest_frame
function. This solution works perfectly fine in a simple case such as our Hello World application. But, what if we wanted to register for a number of streams and work with them? Or, what if we were working with more than one StreamSet
, or possibly more than one StreamReader
per StreamSet
? In all of those cases, the code within the loop could quickly become complex, cluttered and cumbersome.
To alleviate these issues, Astra provides us with a framework to define and create FrameListener
s. A FrameListener
has one function called on_frame_ready
that (you guessed it!) is called when a new frame of a specific type is ready for processing. So, instead of looping over our StreamReader
’s get_latest_frame
function, our listener will have the latest frame automatically delivered to it as soon as the frame is ready. Neato!
In order to use a FrameListener
with our example…
- We need to define a listener class that implements
FrameListener
. This class will give us access to the actual frames that are coming from the Astra sensor. We’ll get those frames in theon_frame_ready
function. Copy the following code below your#include
directives and above yourmain
function:
7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 | class DepthFrameListener : public astra::FrameListener
{
public:
DepthFrameListener(int maxFramesToProcess)
: maxFramesToProcess_(maxFramesToProcess)
{}
bool is_finished() const { return isFinished_; }
private:
void on_frame_ready(astra::StreamReader& reader,
astra::Frame& frame) override
{
const astra::DepthFrame depthFrame = frame.get<astra::DepthFrame>();
if (depthFrame.is_valid())
{
print_depth_frame(depthFrame);
++framesProcessed_;
}
isFinished_ = framesProcessed_ >= maxFramesToProcess_;
}
void print_depth_frame(const astra::DepthFrame& depthFrame) const
{
const int frameIndex = depthFrame.frame_index();
const short middleValue = get_middle_value(depthFrame);
std::printf("Depth frameIndex: %d value: %d \n", frameIndex, middleValue);
}
short get_middle_value(const astra::DepthFrame& depthFrame) const
{
const int width = depthFrame.width();
const int height = depthFrame.height();
const size_t middleIndex = ((width * (height / 2.f)) + (width / 2.f));
const short* frameData = depthFrame.data();
const short middleValue = frameData[middleIndex];
return middleValue;
}
bool isFinished_{false};
int framesProcessed_{0};
int maxFramesToProcess_{0};
};
int main(int argc, char** argv)
{
|
- Line 10 - Constructor parameter specifies the total number of frames we’re going to process before exiting our loop
- Line 14 -
is_finished
will be used in a later step to check whether we’ve looped the maximum number of times or not - Line 20 - Gets the depth frame data from our frame
- Line 22 - Check to verify that we received a valid frame
- Line 24 - Prints depth frame information to the console
- Line 44 - Calculates the index of the middle pixel in our depth frame’s data
- Line 47 - Gets the value of the middle depth frame pixel
Note
The only required function is the on_frame_ready
function. The other functions in this class support what we do within that function.
- With the
DepthFrameListener
defined, let’s construct our listener in themain
function and add it to theStreamReader
that we created in a previous step.
63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 | int main(int argc, char** argv)
{
astra::initialize();
astra::StreamSet streamSet;
astra::StreamReader reader = streamSet.create_reader();
reader.stream<astra::DepthStream>().start();
int maxFramesToProcess = 100;
DepthFrameListener listener(maxFramesToProcess);
reader.add_listener(listener);
// More of your code will go here
reader.remove_listener(listener);
astra::terminate();
return 0;
}
|
- Line 73 - Constructs a
DepthFrameListener
that will loop 100 times - Line 75 - Adds the listener to our reader
- Line 79 - Removes the listener from our reader
Updating our listener¶
We’ve got Astra and the StreamSet
running, and we’re listening to depth frames as they stream in through the StreamSet
’s StreamReader
. We don’t know when frames are going to arrive from our Astra, so we need to continuously update those listeners by calling astra_update
in a loop.
63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 | int main(int argc, char** argv)
{
astra::initialize();
astra::StreamSet streamSet;
astra::StreamReader reader = streamSet.create_reader();
reader.stream<astra::DepthStream>().start();
const int maxFramesToProcess = 100;
DepthFrameListener listener(maxFramesToProcess);
reader.add_listener(listener);
do {
astra_update();
} while (!listener.is_finished());
reader.remove_listener(listener);
astra::terminate();
return 0;
}
|
- Line 77-79 - The Astra update loop.
Let’s compile and run our solution. After you’ve watched some depth frame information print to the console, revel in the knowledge that you’ve mastered the listener along with other core Astra functionality. Now, go forth, let your imagination run wild and use Astra to do all sorts of innovative things!