11 #include <spdlog/spdlog.h> 
   19 using namespace flexiv;
 
   23 constexpr 
double kLoopPeriod = 0.001;
 
   26 constexpr 
double kSineAmp = 0.035;
 
   27 constexpr 
double kSineFreq = 0.3;
 
   30 std::atomic<bool> g_stop_sched = {
false};
 
   37     std::cout << 
"Required arguments: [robot_sn]" << std::endl;
 
   38     std::cout << 
"    robot_sn: Serial number of the robot to connect. Remove any space, e.g. Rizon4s-123456" << std::endl;
 
   39     std::cout << 
"Optional arguments: [--hold]" << std::endl;
 
   40     std::cout << 
"    --hold: robot holds current joint positions, otherwise do a sine-sweep" << std::endl;
 
   41     std::cout << std::endl;
 
   47     rdk::Robot& robot, 
const std::string& motion_type, 
const std::vector<double>& init_pos)
 
   50     static unsigned int loop_counter = 0;
 
   55             throw std::runtime_error(
 
   56                 "PeriodicTask: Fault occurred on the connected robot, exiting ...");
 
   60         std::vector<double> target_pos(robot.
info().
DoF);
 
   61         std::vector<double> target_vel(robot.
info().
DoF);
 
   62         std::vector<double> target_acc(robot.
info().
DoF);
 
   65         if (motion_type == 
"hold") {
 
   66             target_pos = init_pos;
 
   67         } 
else if (motion_type == 
"sine-sweep") {
 
   68             for (
size_t i = 0; i < target_pos.size(); ++i) {
 
   69                 target_pos[i] = init_pos[i]
 
   70                                 + kSineAmp * sin(2 * M_PI * kSineFreq * loop_counter * kLoopPeriod);
 
   73             throw std::invalid_argument(
 
   74                 "PeriodicTask: Unknown motion type. Accepted motion types: hold, sine-sweep");
 
   78         if (loop_counter == 5000) {
 
   80             for (
auto& v : new_Kq) {
 
   84             spdlog::info(
"Joint stiffness set to [{}]", rdk::utility::Vec2Str(new_Kq));
 
   88         if (loop_counter == 10000) {
 
   90             spdlog::info(
"Joint impedance properties are reset");
 
   99     } 
catch (
const std::exception& e) {
 
  100         spdlog::error(e.what());
 
  105 int main(
int argc, 
char* argv[])
 
  110     if (argc < 2 || rdk::utility::ProgramArgsExistAny(argc, argv, {
"-h", 
"--help"})) {
 
  115     std::string robot_sn = argv[1];
 
  119         ">>> Tutorial description <<<\nThis tutorial runs real-time joint impedance control to " 
  120         "hold or sine-sweep all robot joints.\n");
 
  123     std::string motion_type = 
"";
 
  124     if (rdk::utility::ProgramArgsExist(argc, argv, 
"--hold")) {
 
  125         spdlog::info(
"Robot holding current pose");
 
  126         motion_type = 
"hold";
 
  128         spdlog::info(
"Robot running joint sine-sweep");
 
  129         motion_type = 
"sine-sweep";
 
  140             spdlog::warn(
"Fault occurred on the connected robot, trying to clear ...");
 
  143                 spdlog::error(
"Fault cannot be cleared, exiting ...");
 
  146             spdlog::info(
"Fault on the connected robot is cleared");
 
  150         spdlog::info(
"Enabling robot ...");
 
  155             std::this_thread::sleep_for(std::chrono::seconds(1));
 
  157         spdlog::info(
"Robot is now operational");
 
  160         spdlog::info(
"Moving to home pose");
 
  161         robot.
SwitchMode(rdk::Mode::NRT_PLAN_EXECUTION);
 
  164         while (robot.
busy()) {
 
  165             std::this_thread::sleep_for(std::chrono::seconds(1));
 
  171         robot.
SwitchMode(rdk::Mode::RT_JOINT_IMPEDANCE);
 
  174         auto init_pos = robot.
states().
q;
 
  175         spdlog::info(
"Initial joint positions set to: {}", rdk::utility::Vec2Str(init_pos));
 
  181             std::bind(PeriodicTask, std::ref(robot), std::ref(motion_type), std::ref(init_pos)),
 
  187         while (!g_stop_sched) {
 
  188             std::this_thread::sleep_for(std::chrono::milliseconds(1));
 
  193     } 
catch (
const std::exception& e) {
 
  194         spdlog::error(e.what());
 
Main interface to control the robot, containing several function categories and background services.
 
void ExecutePlan(unsigned int index, bool continue_exec=false, bool block_until_started=true)
[Blocking] Execute a plan by specifying its index.
 
RobotInfo info() const
[Non-blocking] General information about the robot.
 
RobotStates states() const
[Non-blocking] Current states data of the robot.
 
void SetJointImpedance(const std::vector< double > &K_q, const std::vector< double > &Z_q={})
[Blocking] Set impedance properties of the robot's joint motion controller used in the joint impedanc...
 
void SwitchMode(Mode mode)
[Blocking] Switch the robot to a new control mode and wait for the mode transition to finish.
 
bool operational() const
[Non-blocking] Whether the robot is ready to be operated, which requires the following conditions to ...
 
void StreamJointPosition(const std::vector< double > &positions, const std::vector< double > &velocities, const std::vector< double > &accelerations)
[Non-blocking] Continuously stream joint position, velocity, and acceleration commands to the robot....
 
void Enable()
[Blocking] Enable the robot. If E-stop is released and there's no fault, the robot will release brake...
 
bool fault() const
[Non-blocking] Whether the robot is in fault state.
 
bool ClearFault(unsigned int timeout_sec=30)
[Blocking] Try to clear minor or critical fault for the robot without a power cycle.
 
bool busy() const
[Non-blocking] Whether the robot is busy. This includes any user commanded operations that requires t...
 
Real-time scheduler that can simultaneously run multiple periodic tasks. Parameters for each task are...
 
int max_priority() const
[Non-blocking] Maximum available priority for user tasks.
 
void AddTask(std::function< void(void)> &&callback, const std::string &task_name, int interval, int priority, int cpu_affinity=-1)
[Non-blocking] Add a new periodic task to the scheduler's task pool. Each task in the pool is assigne...
 
void Stop()
[Blocking] Stop all added tasks. The periodic execution will stop and all task threads will be closed...
 
void Start()
[Blocking] Start all added tasks. A dedicated thread will be created for each added task and the peri...
 
std::vector< double > K_q_nom