Hi I'm a newbie in Qt and C++17 but I have to update a some private data from within a nested lambda function. These values are used to update the ui trough a timer:
This's the main window class:
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
private slots:
void on_connectButton_clicked();
protected:
void timerEvent(QTimerEvent *event);
private:
Ui::MainWindow *ui;
mavsdk::Mavsdk mavsdk;
std::shared_ptr<mavsdk::Telemetry> telemetry;
std::shared_ptr<mavsdk::System> system;
int timerId;
double roll;
double pitch;
double yaw;
double heading;
double latitude;
double longitude;
double altitude;
int messages;
const QString mavURI = "udp://0.0.0.0:14550";
const int telemetryFreq = 5;
const int timerFreq = 33;
void connectMAV();
};
And these are relevant methods:
void MainWindow::connectMAV()
{
mavsdk::ConnectionResult conn_result = mavsdk.add_any_connection(mavURI.toStdString());
setWindowTitle("Listening on: " + mavURI);
mavsdk.subscribe_on_new_system
(
[&]()
{
setWindowTitle("Connected: " + mavURI);
system = mavsdk.systems()[0];
telemetry = std::shared_ptr<mavsdk::Telemetry>(new mavsdk::Telemetry(system));
mavsdk::Telemetry::Result tel_action = mavsdk::Telemetry::Result::Unknown;
do
{
tel_action = telemetry->set_rate_position(5);
std::this_thread::sleep_for(std::chrono::seconds(telemetryFreq));
} while(tel_action == mavsdk::Telemetry::Result::Timeout);
do
{
tel_action = telemetry->set_rate_attitude_euler(telemetryFreq);
std::this_thread::sleep_for(std::chrono::seconds(1));
} while(tel_action == mavsdk::Telemetry::Result::Timeout);
telemetry->subscribe_position([&] (mavsdk::Telemetry::Position position) {
latitude = position.latitude_deg;
longitude = position.longitude_deg;
altitude = position.absolute_altitude_m;
});
telemetry->subscribe_attitude_euler([&] (mavsdk::Telemetry::EulerAngle attitude) {
roll = attitude.roll_deg;
pitch = attitude.pitch_deg;
yaw = attitude.yaw_deg;
});
}
);
}
void MainWindow::timerEvent(QTimerEvent *event){
ui->eadi->setRoll(roll);
ui->eadi->setPitch(pitch);
ui->eadi->setAltitude(altitude);
ui->eadi->redraw();
}
It seems that the main window is never updated. And debugging the code breakpoints inside inner lambdas are never triggered.
I finally managed to fix this issue through Qt features. First of all I need to clarify that this problem needed a minimalistic solution since lambdas are the only way to manage callbacks for this specific API (mavsdk for instance). In short I cannot change the way the callbacks are invoked.
The above code should be modified in this way:
mavsdk.subscribe_on_new_system
(
[&]()
{
emit newSystem();
}
);
of course somewhere I defined:
signals:
void newSystem();
and:
private slots:
void onNewSystem();
And connected it to the signal above the standard way:
connect(this, &MainWindow::newSystem, this, &MainWindow::onNewSystem)
The same schema apply also to nested lambdas.
So we got:
signals:
void updatePosition(mavsdk::Telemetry::Position position);
void updateAttitude(mavsdk::Telemetry::EulerAngle attitude);
private slots:
void onPositionUpdate(mavsdk::Telemetry::Position position);
void onAttitudeUpdate(mavsdk::Telemetry::EulerAngle attitude);
It was not so difficult after all..