I want to have different OpenCV functions running with std::async()
As an example, I'm trying to acquire and display images using my webcam.
I did a class called camHandler to encapsulate this.
This example is made asynchronous on purpose, I know I could just display the image after acquiring it :)
I first use the open() function in a member cap:
auto camHandler::initCamera(int deviceID) -> camHandler::CamState {
this->deviceID = deviceID;
this->apiID = cv::CAP_ANY;
cap.open(deviceID, apiID);
if (!cap.isOpened()) {
this->currentState = error;
return this->currentState;
}
return Ready;
}
I have a function for acquisition and another one for displaying:
auto camHandler::imageStreaming() -> void{
this->currentState = streaming;
while(true)
{
std::cout << "Acc " << std::endl;
cap.read(this->frame);
this->acquired++;
if (this->frame.empty()) {
this->currentState = error;
break;
}
};
}
and
auto camHandler::displayImage() -> void {
while(true){
std::cout << "Disp " << std::endl;
cv::imshow("Live", this->frame);
this->displayed++;
if (cv::waitKey(5) >= 0){
this->currentState = paused;
break;
}
};
}
finally, I did a function that will call these 2 functions inside a std::async():
auto camHandler::startStreaming() -> void {
auto stream = std::async(&camHandler::imageStreaming, this);
auto disp = std::async(&camHandler::displayImage, this);
}
The problem
In my main I only call:
camHandler ch;
ch.initCamera();
ch.startStreaming();
And I get:
Acc Disp
Acc
Acc
Acc
Acc
Acc
Which means that display was only called once and acquisition kept running.
How can I make sure both are running?
Like this I don't even see the image window from OpenCV.
My camera and display work properly when I do the normal capturing as shown in OpenCV's Site
If you try to call cv::imshow with an empty cv::Mat, it will throw an exception, and async will end.
Since it's running in async, cv::imshow("Live", this->frame) can be called before cap.read(this->frame).
You should check cv::Mat is not empty before displaying.
Related
I wanted to perform hashing of a stream of input messages in multithreading, so was trying to implement
std::vector<std::future<HashData>> futures;
but the program aborts from abort.h when debugging in Visual Studio 2019.
Code Snippet:
std::vector<std::future<HashData>> futures;
std::vector<std::string> messages;
for (int i = 0; i < messages.size(); i++)
{
std::promise<HashData> promiseHashData;
std::future<HashData> futureHashData = promiseHashData.get_future();
futures.emplace_back(std::move(futureHashData));
std::async(std::launch::async, [&]() {PerformHash(std::move(promiseHashData), messages[i]);});
}
std::vector<HashData> vectorOfHashData;
// wait for all async tasks to complete
for (auto& futureObj : futures)
{
vectorOfHashData.push_back(futureObj.get());
}
void PerformHash(std::promise<HashData>&& promObject, std::string& message)
{
ComputeHashUsingSHA256(message);
HashData data;
// set data for HashData object
data.i = i;
data.blocks = blocks;
data.blocksize = blocksize;
data.blockbufs = blockbufs;
data.secs = secs;
memcpy(data.digest, digest, SHA256_DIGEST_SIZE);
data.has_hashdata = has_hashdata;
memcpy(data.hashdata_buf, hashdata_buf, c_hashsize);
promObject.set_value(data);
}
while debugging the code, observed as only few threads were created using async and post that, the program aborts from abort.h as shown in this
image
The problem is that you capture promiseHashData by reference. At each loop iteration it gets invalidated while the async thread performs computation on it.
You need to capture the instance of the promise by moving it into the lambda, like:
std::async(std::launch::async, [promiseHashData2=std::move(promiseHashData)] ()mutable{PerformHash(std::move(promiseHashData2), messages[i]);});
Or use std::async's feature of returning std::future while changing performHash to return hashData. Using both async and promise is redundant.
To build on the good answer from #ALX23z and answer your comments there:
The reason you get that error is that PerformHash (and your lambda) returns void. The return value from std::async is std::future<X>, where X is the return value of the function you give std::async. Here is a small toy example:
struct HashData {std::size_t h;};
HashData performHash(const std::string &msg) // <- returns HashData
{
HashData hd = {msg.size()};
return hd;
}
int main()
{
std::vector<std::string> messages = {"Bla", "klaf", "this is a message"};
std::vector<std::future<HashData>> futures;
for (const auto &msg : messages)
{
auto fut = std::async(std::launch::async, [&]()
{ return performHash(msg); }); // <- also returns HashData
futures.emplace_back(std::move(fut));
}
std::vector<HashData> results;
for (auto &fut : futures)
results.push_back(fut.get());
for (const auto &hash : results)
std::cout << hash.h << '\n';
}
Also note that you can skip the lambda, and call std::async like this:
auto fut = std::async(std::launch::async, performHash, msg); // performHash is a free function
// If performHash is a method of class HashCalculator - included for completeness sake
HashCalculator calc; // Need an instance somewhere
auto fut = std::async(std::launch::async, &HashCalculator::performHash, calc, msg);
I am writing unit tests for one of the classes I want to test. Function infFooLoop() what I want to test is executed in endless loop (request to stop it comes externally). My problem is I want to change the private variable state_ via setter in setState when function executes in separate thread asynchronously. Some simplified code example is here:
enum class State : int
{
Success = 1,
Failure = 2
};
class Foo
{
private:
State state_{State::Success};
bool stop_flag_{false};
public:
void setState(State state) { state_ = state; }
void infFooLoop(bool &start)
{
while (start)
{
std::cout << "While loop executes \n";
if (state_ == State::Failure)
{
stop_flag_ = true;
}
else if (stop_flag_)
{
std::cout << "Program stopped\n";
// Report error but for this example break
break;
}
std::this_thread::sleep_for(std::chrono::milliseconds(200));
}
}
};
int main()
{
Foo obj;
bool flag{true};
std::future<void> future = std::async(std::launch::async, [&](){ obj.infFooLoop(flag);});
// Try to change the data:
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
// I want to change data for `Failure` so stop_flag condition will be used
obj.setState(State::Failure);
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
// terminate loop
flag = false;
return 0;
}
state_ will be taken from external component and stop_flag_ is used to handle some corner-case here (in real it wont break the loop, just report error to different component).
I assume infFooLoop executes on a separate thread so I can't just call another function in a different thread to change this data. stop_flag_ is some internal variable used only in this one function so I want to leave it as simple as possible (do not introduce mutexes/atomic in Foo class only for tests). Can you give me some suggestions on what should I do here?
void Callback (XPointer, XRecordInterceptData *pRecord) { std::cout << "my logs\n"; }
int main ()
{
if(auto* const pDisplay = XOpenDisplay(nullptr))
{
XRecordClientSpec clients = XRecordAllClients;
auto* pRange = ::XRecordAllocRange();
pRange->device_events = XRecordRange8{KeyPress, ButtonRelease};
auto context = ::XRecordCreateContext(pDisplay, 0, &clients, 1, &pRange, 1);
::XRecordEnableContextAsync(pDisplay, context, Callback, nullptr); // use with/without `...Async()`
::XRecordDisableContext(pDisplay, context);
::XRecordFreeContext(pDisplay, context);
::XFree(pRange);
::XFlush(pDisplay);
::XSync(pDisplay, true);
}
}
I am noticing that even after XRecordDisableContext(), the Callback() continues to be invoked.
How can we disable the recording, so that the callback isn't invoked anymore?
Note:
Have taken example from this site.
Don't know how to use XRecordEnableContext(), so using XRecordEnableContextAsync(). Is that the source of problem?
One way is to move below statement into the Callback() or some equivalent other thread. For testing purpose, I changed the code as below where after few event raised, I disable from the Callback() and it works.
::Display* pDisplay;
XRecordRange* pRange;
XRecordContext context;
#define CHECK(EVENT) if(*pDatum == EVENT) qDebug() << #EVENT
void Handle (XPointer, XRecordInterceptData *pRecord)
{
std::cout << "my logs\n";
static int i = 0;
if(++i < 10)
return;
::XRecordDisableContext(pDisplay, context);
::XRecordFreeContext(pDisplay, context);
::XFree(pRange);
::XFlush(pDisplay);
::XSync(pDisplay, true);
}
// other code same, except 3 variables are global and "Free"-up functions are not required
The following problem originates from https://github.com/cycfi/elements/issues/144 which is me struggling to find a way in elements GUI library to invoke a callback once per frame.
So far in every library I have seen, there is some callback/explicit loop that continuously processes user input, measures time since last frame and performs the render.
In the elements library, such loop is a platform-specific implementation detail and instead, the library-using code is given access to boost::asio::io_context object to which any callable can be posted. poll is invoked inside platform-specific event loop.
I had no problems changing code from typical waterfall update(time_since_last_frame) to posting functors that do it, however this is where the real problem begins:
Posted functors are only invoked once. The answer from the library author is "just post again".
If I post again immediately from the functor, I create an endless busy loop because as soon as one functor from the poll is completed, boost asio runs the newly posted one. This completely freezes the thread that runs the GUI because of an infinite self-reposting callback loop. The answer from the library author is "post with a timer".
If I post with a timer, I don't fix anything:
If the time is too small, it runs out before the callback finishes so the newly posted callback copy is invoked again ... which brings infinite loop again.
If the time is too large to cause an infinite loop, but small enough to fit in multiple times within one frame, it is run multiple times per frame ... which is a waste because there is no point in calculating UI/animation/input state multiple times per frame.
If the time is too large, the callback is not invoked on each frame. The application renders multiple times without processing user-generated events ... which is a waste because identical state is rendered multiple times for each logic update.
There is no way to calculate FPS because library-using code does not even know how many frames have been rendered between posted callbacks (if any).
In other words:
In a typical update+input+render loop the loop runs as fast as possible, yielding as many frames as it can (or to a specified cap thanks to sleeps). If the code is slow, it's just FPS loss.
In elements library, if the callback is too fast it is repeated multiple times per frame because registered timer may finish multiple times within one frame. If the code is too slow, it's a "deadlock" callback loop that never gets out of asio's poll.
I do not want my code to be invoked every X time (or more-than-X because of OS-scheduler). I want my code to be invoked once per frame (preferably with the time delta argument, but I can also measure it myself from previous invokation).
Is such usage of asio in the elements library a bad design? I find the "post with a timer" solution to be an antipattern. It feels to me like fixing a deadlock between 2 threads by adding a sleep in one of them and hoping they will never collide after such change - in case of elements I'm posting a timed callback and hoping it's not too fast to waste CPU but also not to slow to cause infinite timed-callback loop. The ideal time is too hard to calculate because of so many factors that can affect it, including user actions - basically a lose-lose situation.
Extra note 1: I have tried defer instead of poll, no difference.
Extra note 2: I have already created 100+ issues/PRs for the library so it's very likely that a motivating answer will end in another PR. In other words, solutions that attempt to modify library are fine too.
Extra note 3: MCVE (here without a timer, which causes almost-infinite loop until the counter finishes, during coutning the GUI thread is frozen):
#include <elements.hpp>
using namespace cycfi::elements;
bool func()
{
static int x = 0;
if (++x == 10'000'000)
return true;
return false;
}
void post_func(view& v)
{
if (!func())
v.post([&v](){ post_func(v); });
}
int main(int argc, char* argv[])
{
app _app(argc, argv);
window _win(_app.name());
_win.on_close = [&_app]() { _app.stop(); };
view view_(_win);
view_.content(box(rgba(35, 35, 37, 255)));
view_.post([&view_](){ post_func(view_); });
_app.run();
return 0;
}
So, finally found time to look at this.
In the back-end it seems that Elements already integrates with Asio. Therefore, when you post tasks to the view with they become async tasks.
You can give them a delay, so you don't have to busy loop.
Let's do a demo
Defining A Task
Let's define a task that has fake progress and a fixed deadline for completion:
#include <utility>
#include <chrono>
using namespace std::chrono_literals;
auto now = std::chrono::high_resolution_clock::now;
struct Task {
static constexpr auto deadline = 2.0s;
std::chrono::high_resolution_clock::time_point _start = now();
bool _done = false;
void reset() { *this = {}; }
auto elapsed() const { return now() - _start; } // fake progress
auto done() { return std::exchange(_done, elapsed() > deadline); }
};
How To Self-Chain?
As you noticed, this is tricky. You can stoop and just type-erase your handler:
std::function<void()> cheat;
cheat = [&cheat]() {
// do something
cheat(); // self-chain
};
However, just to humor you, let me introduce what functional programming calls the Y combinator.
#include
template<class Fun> struct ycombi {
Fun fun_;
explicit ycombi(Fun fun): fun_(std::move(fun)) {}
template<class ...Args> void operator()(Args &&...args) const {
return fun_(*this, std::forward<Args>(args)...);
}
};
With that, we can create a generic handler posting chainer:
auto chain = [&view_](auto f) {
return ycombi{ [=, &view_](auto self) {
view_.post(10ms, [=] {
if (f())
self();
});
} };
};
I opted for 10ms delay, but you don't have to. Doing no delay means "asap" which would amount to every frame, given the resources.
A Reporter Task
Let's update a progress-bar:
auto prog_bar = share(progress_bar(rbox(colors::black), rbox(pgold)));
auto make_reporter = [=, &view_](Task& t) {
static int s_reporter_id = 1;
return [=, id=s_reporter_id++, &t, &view_] {
std::clog << "reporter " << id << " task at " << (t.elapsed() / 1.0ms) << "ms " << std::endl;
prog_bar->value(t.elapsed() / Task::deadline);
view_.refresh(*prog_bar);
if (t.done()) {
std::clog << "done" << std::endl;
return false;
}
return true;
};
};
Now. let's add a button to start updating the progress bar.
auto task_btn = button("Task #1");
task_btn.on_click = [=,&task1](bool) {
if (task1.done())
task1.reset();
auto progress = chain(make_reporter(task1));
progress();
};
Let's put the button and the bar in the view and run the app:
view_.content(task_btn, prog_bar);
view_.scale(8);
_app.run();
Full Listing
Used current Elements master (a7d1348ae81f7c)
File test.cpp
#include <utility>
#include <chrono>
using namespace std::chrono_literals;
auto now = std::chrono::high_resolution_clock::now;
struct Task {
static constexpr auto deadline = 2.0s;
std::chrono::high_resolution_clock::time_point _start = now();
bool _done = false;
void reset() { *this = {}; }
auto elapsed() const { return now() - _start; } // fake progress
auto done() { return std::exchange(_done, elapsed() > deadline); }
};
#include <functional>
template<class Fun> struct ycombi {
Fun fun_;
explicit ycombi(Fun fun): fun_(std::move(fun)) {}
template<class ...Args> void operator()(Args &&...args) const {
return fun_(*this, std::forward<Args>(args)...);
}
};
#include <elements.hpp>
#include <iostream>
using namespace cycfi::elements;
constexpr auto bred = colors::red.opacity(0.4);
constexpr auto bgreen = colors::green.level(0.7).opacity(0.4);
constexpr auto bblue = colors::blue.opacity(0.4);
constexpr auto brblue = colors::royal_blue.opacity(0.4);
constexpr auto pgold = colors::gold.opacity(0.8);
int main(int argc, char* argv[]) {
app _app(argc, argv);
window _win(_app.name());
_win.on_close = [&_app]() { _app.stop(); };
view view_(_win);
Task task1;
auto chain = [&view_](auto f) {
return ycombi{ [=, &view_](auto self) {
view_.post(10ms, [=] {
if (f())
self();
});
} };
};
auto prog_bar = share(progress_bar(rbox(colors::black), rbox(pgold)));
auto make_reporter = [=, &view_](Task& t) {
static int s_reporter_id = 1;
return [=, id=s_reporter_id++, &t, &view_] {
std::clog << "reporter " << id << " task at " << (t.elapsed() / 1.0ms) << "ms " << std::endl;
prog_bar->value(t.elapsed() / Task::deadline);
view_.refresh(*prog_bar);
if (t.done()) {
std::clog << "done" << std::endl;
return false;
}
return true;
};
};
auto task_btn = button("Task #1");
task_btn.on_click = [=,&task1](bool) {
if (task1.done())
task1.reset();
auto progress = chain(make_reporter(task1));
progress();
};
view_.content(task_btn, prog_bar);
view_.scale(8);
_app.run();
}
I'm coding a plugin for XPLANE10 which gets a MSG from ROS.
My IDE is QTcreator 4.1.0 based QT 5.7.0 for Ubuntu 64 Bit. I would like to use C++11 Standards
My code explained
The main initializes ROS and creates a map -> container.
ROS spins in a loop till my GUI sends a MSG where my AirPlane should fly.
The MSG contains 3 floats(phi, theta, psi) where "phi" is the AirPlane ID, theta contains the ID for my ETA(Estimated Time of Arrival)
and psi contains the ID for my pose All of the IDs are saved in the ParameterServer(lookuptable).
So at the beginning i look up the activeAirplanes which returns a vector . I would like to store them in a map where the key is the AirCraft ID and the second param is an instance of the Object.
So i have initialized the for example(looked in container while debugging):
[0] first = 1 // Airplane ID1
[0] second = new CObject(freq)
[1] first = 2 // Airplane ID2
[1] second = new CObject(freq)
If i get a MSG from GUI
phi = 1
theta=2
psi=3
,
ROS will callback
MSG(....std::map<i32, CObject> &container)
// if phi is 1 so use the mapkey 1 and trigger the method do_stuff from CObject
do_stuff(phi, theta, psi,freq)
I would like to call the in a function from main
int getPlanes(std::map<i32,CObject>& container)
{
...
getActiveAirplanesFromServer(activePlanes);
}
First Question:
How do i pass the container to my callback?
Second Question:
How do i parallelize do_stuff() so my callback will return to main and i'm able to command more aircrafts while the others are calculated?
Third Question:
How would be the correct syntax for getPlanes to pass the container by reference so getPlanes() can edit it?
Fourth Question:
Is there a difference between
std::map<i32,CObject*> map
std::map<i32,CObject>* map
and
std::map<i32,CObject*>::iterator it=container->begin();
std::map<i32,CObject*>::iterator* it=container->begin();
If yes, what do i want ? #4Solved
// I have to edit stuff 'cause of some restrictions in my company.
#include "Header.h"
int main()
{
f64 freq = 10;
std::map<i32, CObject>* container;
std::map<i32,CObject>::iterator* it=container->begin();
// ROS
if(!ros::isInitialized())
{
int rosargc = 0;
char** rosargv = NULL;
ros::init(rosargc, rosargv, "MainNode");//), ros::init_options::AnonymousName);
}
else
{
printf("Ros has already been initialized.....\n");
}
ros::NodeHandle* mainNodeHandle=new ros::NodeHandle;
ros::AsyncSpinner spinner(2);
ParameterServer * ptrParam= new ParameterServer(mainNodeHandle);
ros::Subscriber airSub=mainNodeHandle->subscribe<own_msgs::ownStruct>("/MSG",
1000,
boost::bind(MSG,
_1,
freq,
container));
std::vector<i32> activePlanes;
i32 retVal=0;
retVal += ptrParam-> ParameterServer::getActiveAirplanesFromServer(activePlanes);
if (retVal == 0 && activePlanes.size()>0)
{
for (u32 j =0; j <activePlanes.size(); j++)
{
container->insert (std::pair<i32,CObject> (activePlanes[j] , new CObject(freq)));
}
}
while (ros::ok())
{
spinner.start(); //spinnt sehr viel :-)
ros::waitForShutdown ();
}
std::cout<<"ENDE"<<std::endl;
int retval = 1;
return retval;
}
void MSG(const own_msgs::ownStruct<std::allocator<void> >::ConstPtr &guiMSG,
f64 freq,
std::map<i32, CObject> &container)
{
if ((guiMSG->phi != 0) && (guiMSG->theta != 0) && (guiMSG->psi != 0))
{
std::string alpha = std::to_string(guiMSG->phi)+std::to_string(guiMSG->theta)+to_string(guiMSG->psi);
container.at(guiMSG->phi) -> do_stuff(guiMSG->phi,guiMSG->theta,guiMSG->psi, freq);
}
else
{
std::cout<<" Did not receive anything\n"<<endl;
}
}
void do_stuff(...)
{
//copy the IDs to private Member of this single Object
//setROS() for this single Object
//callback the current AC pose via ID from XPLANE
//callback the wished AC pose via ID from ParamServer
// do some calculations for optimum flight path
// publish the Route to XPlane
}
EDIT::
Problem is i get it to compile now and if debug it and set a breakpoint at :
void MSG(const own_msgs::ownStruct<std::allocator<void> >::ConstPtr &guiMSG,f64 freq,std::map<i32, CObject*> &container)
{
..
/*->*/ container.at(guiMSG->)...
}
The Container remains empty.
So i read some stuff about pointers and i saw my errors..
I confused * and &
if i want to pass the adress of a variable i have to write like
int main()
{
int a = 0;
AddTwo(&a)
cout<<a<<endl; // Output: 2
}
void AddTwo(int* a)
{
a+=2;
}