Hi,
I am trying to implement camera acquisition class with OpenCV and QStateMachine.
I have the following state machine definition:
DriverVideoCapture
::DriverVideoCapture(QObject *parent,
const int camid
) : QObject(parent
){
// configure state machine
m_engine = new QStateMachine(this);
QState *state_idle = new QState(m_engine);
QState *state_acquire = new QState(m_engine);
QState *state_error = new QState(m_engine);
state_idle->addTransition(this, &DriverVideoCapture::start, state_acquire);
state_idle->addTransition(this, &DriverVideoCapture::error, state_error);
state_acquire->addTransition(this, &DriverVideoCapture::grab, state_acquire);
state_acquire->addTransition(this, &DriverVideoCapture::stop, state_idle);
state_acquire->addTransition(this, &DriverVideoCapture::error, state_error);
connect(state_acquire, &QState::entered, this, &DriverVideoCapture::on_stateAcquire);
m_engine->setInitialState(state_idle);
m_engine->start();
m_videoCapture = new cv::VideoCapture(camid);
if (!m_videoCapture->isOpened())
emit error();
}
DriverVideoCapture::DriverVideoCapture(QObject *parent, const int camid) : QObject(parent)
{
// configure state machine
m_engine = new QStateMachine(this);
QState *state_idle = new QState(m_engine);
QState *state_acquire = new QState(m_engine);
QState *state_error = new QState(m_engine);
state_idle->addTransition(this, &DriverVideoCapture::start, state_acquire);
state_idle->addTransition(this, &DriverVideoCapture::error, state_error);
state_acquire->addTransition(this, &DriverVideoCapture::grab, state_acquire);
state_acquire->addTransition(this, &DriverVideoCapture::stop, state_idle);
state_acquire->addTransition(this, &DriverVideoCapture::error, state_error);
connect(state_acquire, &QState::entered, this, &DriverVideoCapture::on_stateAcquire);
m_engine->setInitialState(state_idle);
m_engine->start();
m_videoCapture = new cv::VideoCapture(camid);
if (!m_videoCapture->isOpened())
emit error();
}
To copy to clipboard, switch view to plain text mode
Now inside state_acquire I will do the blocking operation of frame reading
void DriverVideoCapture::on_stateAcquire()
{
cv::Mat frame;
if (!m_videoCapture->isOpened())
return;
if (!m_videoCapture->read(frame))
emit error();
emit grab();
}
void DriverVideoCapture::on_stateAcquire()
{
cv::Mat frame;
if (!m_videoCapture->isOpened())
return;
if (!m_videoCapture->read(frame))
emit error();
emit grab();
}
To copy to clipboard, switch view to plain text mode
And I will connect buttons to start and stop the process:
m_driverVideoCapture = new DriverVideoCapture(this);
connect(ui->pushButton_start, &QPushButton::clicked, m_driverVideoCapture, &DriverVideoCapture::start);
connect(ui->pushButton_stop, &QPushButton::clicked, m_driverVideoCapture, &DriverVideoCapture::stop);
m_driverVideoCapture = new DriverVideoCapture(this);
connect(ui->pushButton_start, &QPushButton::clicked, m_driverVideoCapture, &DriverVideoCapture::start);
connect(ui->pushButton_stop, &QPushButton::clicked, m_driverVideoCapture, &DriverVideoCapture::stop);
To copy to clipboard, switch view to plain text mode
The state machine get's a transition from state_idle to state_acquire after the start signal. Then it continues looping inside state_acquire. Once the stop signal is emitted though, it does not get detected and the state machine fails to do the transition from state_acquire to state_idle again. Any clues?
Second question, the event loop created by QStateMachine should be in the current thread. If I move the DriverVideoCapture to a worker thread, as in http://doc.qt.io/qt-4.8/QThread, is the state machine getting an event loop different from the main GUI event loop?
Thank you in advance for any clarifications and tips!
Bookmarks