Skip to content

Commit

Permalink
store callbacks as std::function to allow lambda callbacks
Browse files Browse the repository at this point in the history
  • Loading branch information
christianrauch committed Jan 3, 2018
1 parent ca706cf commit 3ccee5b
Show file tree
Hide file tree
Showing 4 changed files with 56 additions and 18 deletions.
16 changes: 15 additions & 1 deletion examples/client_async_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,21 @@ int main(int argc, char *argv[]) {
client.connect(device, baudrate);
client.start();

client.subscribe(&SubCallbacks::onImu, &subs, 0.1);
// using class method callback
// client.subscribe(&SubCallbacks::onImu, &subs, 0.1);

// using lambda callback with stored lambda object
// const auto imu_cb1 = [](const msp::msg::ImuRaw& imu){
// std::cout<<msp::msg::ImuSI(imu, 512.0, 1.0/4.096, 0.92f/10.0f, 9.80665f);
// };
// client.subscribe<msp::msg::ImuRaw>(imu_cb1, 0.1);

// using lambda callback with stored function object
const std::function<void(const msp::msg::ImuRaw&)> imu_cb2 = [](const msp::msg::ImuRaw& imu){
std::cout<<msp::msg::ImuSI(imu, 512.0, 1.0/4.096, 0.92f/10.0f, 9.80665f);
};
client.subscribe(imu_cb2, 0.1);

client.subscribe(&SubCallbacks::onIdent, &subs, 10);
client.subscribe(&SubCallbacks::onStatus, &subs, 1);
client.subscribe(&SubCallbacks::onServo, &subs, 0.1);
Expand Down
13 changes: 9 additions & 4 deletions examples/fcu_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,10 @@ class App {
}

void onIdent(const msp::msg::Ident& ident) {
std::cout<<"Name: "<<name<<std::endl;
std::cout<<ident;
}

void onStatus(const msp::msg::Status& status) {
std::cout<<"Name: "<<name<<std::endl;
std::cout<<status;
}

Expand Down Expand Up @@ -115,8 +113,15 @@ int main(int argc, char *argv[]) {
// define subscriptions with specific period
fcu.subscribe(&App::onIdent, &app, 10);
fcu.subscribe(&App::onStatus, &app, 1);
// no period => requested Imu each time callbacks are checked
fcu.subscribe(&App::onImu, &app, 0.1);

// using class method callback
//fcu.subscribe(&App::onImu, &app, 0.1);

// using lambda callback
fcu.subscribe<msp::msg::ImuRaw>([](const msp::msg::ImuRaw& imu){
std::cout<<msp::msg::ImuSI(imu, 512.0, 1.0/4.096, 0.92f/10.0f, 9.80665f);
}, 0.1);

fcu.subscribe(&App::onServo, &app, 0.1);
fcu.subscribe(&App::onMotor, &app, 0.1);
fcu.subscribe(&App::onRc, &app, 0.1);
Expand Down
32 changes: 20 additions & 12 deletions inc/msp/Client.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -97,28 +97,25 @@ class SubscriptionBase {
PeriodicTimer *timer;
};

template<typename T, typename C>
template<typename T>
class Subscription : public SubscriptionBase {
public:
typedef void(C::*Callback)(const T&);
typedef std::function<void(const T&)> Callback;

Subscription(const Callback caller, C *const context_class)
: funct(caller), context(context_class) {
}
Subscription(const Callback &callback) : callback(callback) { }

Subscription(const Callback caller, C *const context_class, PeriodicTimer *timer)
: SubscriptionBase(timer), funct(caller), context(context_class)
Subscription(const Callback &callback, PeriodicTimer *timer)
: SubscriptionBase(timer), callback(callback)
{
this->timer->start();
}

void call(const msp::Request &req) {
(*context.*funct)( dynamic_cast<const T&>(req) );
callback( dynamic_cast<const T&>(req) );
}

private:
Callback funct;
C *const context;
Callback callback;
};

enum MessageStatus {
Expand Down Expand Up @@ -251,11 +248,22 @@ class Client {
* @brief subscribe register callback function that is called when type is received
* @param callback pointer to callback function (class method)
* @param context class with callback method
* @param tp period at a timer will send subscribed requests (in seconds), by default this is 0 and requests are not sent periodically
* @param tp period of timer that will send subscribed requests (in seconds), by default this is 0 and requests are not sent periodically
* @return pointer to subscription that is added to internal list
*/
template<typename T, typename C>
SubscriptionBase* subscribe(void (C::*callback)(const T&), C *context, const double tp = 0.0) {
return subscribe<T>(std::bind(callback, context, std::placeholders::_1), tp);
}

/**
* @brief subscribe register callback function that is called when type is received
* @param callback function (e.g. lambda, class method, function pointer)
* @param tp period of timer that will send subscribed requests (in seconds), by default this is 0 and requests are not sent periodically
* @return pointer to subscription that is added to internal list
*/
template<typename T>
SubscriptionBase* subscribe(const std::function<void(const T&)> &callback, const double tp = 0.0) {

if(!std::is_base_of<msp::Request, T>::value)
throw std::runtime_error("Callback parameter needs to be of Request type!");
Expand All @@ -272,7 +280,7 @@ class Client {
subscribed_requests[id] = new T();

// register subscription
subscriptions[id] = new Subscription<T,C>(callback, context,
subscriptions[id] = new Subscription<T>(callback,
new PeriodicTimer(
std::bind(static_cast<bool(Client::*)(msp::ID)>(&Client::sendRequest), this, id),
tp
Expand Down
13 changes: 12 additions & 1 deletion inc/msp/FlightController.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,14 +37,25 @@ class FlightController {
* @brief subscribe register callback function that is called when type is received
* @param callback pointer to callback function (class method)
* @param context class with callback method
* @param tp period at a timer will send subscribed requests (in seconds), by default this is 0 and requests are not sent periodically
* @param tp period of timer that will send subscribed requests (in seconds), by default this is 0 and requests are not sent periodically
* @return pointer to subscription that is added to internal list
*/
template<typename T, typename C>
msp::client::SubscriptionBase* subscribe(void (C::*callback)(const T&), C *context, const double tp = 0.0) {
return client.subscribe(callback, context, tp);
}

/**
* @brief subscribe register callback function that is called when type is received
* @param callback function (e.g. lambda, class method, function pointer)
* @param tp period of timer that will send subscribed requests (in seconds), by default this is 0 and requests are not sent periodically
* @return pointer to subscription that is added to internal list
*/
template<typename T>
msp::client::SubscriptionBase* subscribe(const std::function<void(const T&)> &callback, const double tp = 0.0) {
return client.subscribe(callback, tp);
}

/**
* @brief hasSubscription check if message ID is subscribed
* @param id message ID
Expand Down

0 comments on commit 3ccee5b

Please sign in to comment.