0

I have a c++ issue which I am not sure what to ask and what might be the best solution for it given my few weeks of c++ experience.

Given a c++ class, in one of it's functions I initialize the following object:

franka::Robot robot(robot_ip);

and after some other lines I reach to:

robot.control(callback);

which starts a non-stopping internal While loop that and keeps the code blocked on this line. However, I want to still continue using another function of this class which is not possible now since the code is blocked in that last line.

Is there a way that I tell C++ to execute that last line in a non-blocking way in the background or in a separate process or thread and continue with the remaining lines?

I am not sure what might be the advantage of each way also. For example I can imagine it may be possible to do this in a separate process or separate thread or other ways while not knowing which might be the best, and hope that their syntax is easy. I know however the speed can be crucial and that we don't want to have this internal loop interrupted.

I looked at some other questions for example in this thread but I'm confused how I can modify my syntax if I were to use them or not sure even if it's possible.

------edit::

I tried std::thread([](){ robot.control(torque_control_cb); }).detach(); as the answer from here suggests but got the following error:

5: error: ‘robot’ is not captured
       std::thread([](){ robot.control(callback); }).detach();

Changing that line to std::thread t1(robot.control, callback); also gave the error:

 error: no matching function for call to ‘std::thread::thread(<unresolved overloaded function type>, std::function<franka::Torques(const franka::RobotState&, franka::Duration)>&)’
       std::thread t1(robot.control, callback)

Similarly:

   error: ‘async’ is not a member of ‘std’
     auto result = std::async(std::launch::async, [](){robot.control(callback);});
Alejandro
  • 879
  • 11
  • 27
  • 2
    The "best" solution depends entirely on what your requirements are. You can remove the internal loop and make it an update function which you call from the "outside", thus controlling the time slice you allocate to this function, if you want to keep it single-threaded. You can spawn a new thread and let it run there. You can run it in an entirely separate process etc. Difficult to recommend something without a deeper understanding of what problem this is meant to solve. – odyss-jii Oct 15 '20 at 11:04
  • @odyss-jii removing the internal loop won't be a good solution for me since it will require changing the source code of a package and will also be hard. A separate thread or process sounds better, which one has an easier code modification? – Alejandro Oct 15 '20 at 11:08
  • 1
    You should open your C++ textbook to the chapter that explains how to use `std::thread`, and you will find all the information you need in that chapter. – Sam Varshavchik Oct 15 '20 at 11:08

1 Answers1

1

This is an example on how to run a function in the background:

#include <chrono>
#include <functional>
#include <iostream>
#include <thread>

void run(int& status) noexcept
{
  while (true) {
    ++status;
    std::this_thread::sleep_for(std::chrono::seconds(1));
  }
}

int main()
{
  int x = 0;
  std::cout << "Lauch new thread" << std::endl;
  std::thread newthread(std::function<void(int&)>(run), std::ref(x));
  std::cout << "x = " << x << std::endl;
  std::string s;
  std::cout << "Enter to continue";
  std::cin.ignore();
  std::cout << "x = " << x << std::endl;
  newthread.detach();

  return 0;
}

After the initialization, run(int&) runs in background, increasing x once every second. Depending on how much time you wait after pressing Enter, you get a different current value of x.

Note: I wrapped run into a std::function to be able to pass it to the constructor of std::thread, but you could also write a lambda in place

std::thread newthread([](int &s) { run(s); }, std::ref(x));

Also, notice that I had to wrap x with std::ref to be able to pass it to the constructor of std::thread, see here.

Alternatively, if you want to use a lambda that directly uses x you need to capture it:

#include <chrono>
#include <iostream>
#include <thread>

int main()
{
  int x = 0;
  std::cout << "Lauch new thread" << std::endl;
  std::thread newthread([&]() {
    while (true) {
      ++x;
      std::this_thread::sleep_for(std::chrono::seconds(1));
    }
  });
  std::cout << "x = " << x << std::endl;
  std::string s;
  std::cout << "Enter to continue";
  std::cin.ignore();
  std::cout << "x = " << x << std::endl;
  newthread.detach();

  return 0;
}
francesco
  • 7,189
  • 7
  • 22
  • 49