5 #include <spdlog/spdlog.h>
15 constexpr
size_t kLoopFreq = 1000;
18 constexpr
double kLoopPeriod = 0.001;
21 constexpr
double kSwingAmp = 0.1;
24 constexpr
double kSwingFreq = 0.3;
27 std::atomic<bool> g_stop_sched = {
false};
30 std::vector<unsigned int> loop_counter_buf = {};
31 std::vector<double> target_x_buf = {};
32 std::vector<double> actual_x_buf = {};
39 std::cout <<
"Required arguments: [robot SN]" << std::endl;
40 std::cout <<
" robot SN: Serial number of the robot to connect to. "
41 "Remove any space, for example: Rizon4s-123456" << std::endl;
42 std::cout << std::endl;
48 flexiv::rdk::Robot& robot,
const std::array<double, flexiv::rdk::kPoseSize>& init_pose)
51 static uint64_t loop_counter = 0;
56 throw std::runtime_error(
57 "PeriodicTask: Fault occurred on the connected robot, exiting ...");
61 auto target_pose = init_pose;
64 double w = 2 * M_PI * kSwingFreq;
65 double t = loop_counter * kLoopPeriod;
66 target_pose[0] = init_pose[0] + kSwingAmp * sin(w * t);
69 std::array<double, flexiv::rdk::kCartDoF> target_acc = {};
70 target_acc[0] = -kSwingAmp * w * w * sin(w * t);
73 std::array<double, flexiv::rdk::kCartDoF> target_wrench = {};
79 loop_counter_buf.emplace_back(loop_counter);
80 target_x_buf.emplace_back(target_pose[0]);
84 if (++loop_counter > 10000) {
88 }
catch (
const std::exception& e) {
89 spdlog::error(e.what());
94 int main(
int argc,
char* argv[])
99 if (argc < 2 || flexiv::rdk::utility::ProgramArgsExistAny(argc, argv, {
"-h",
"--help"})) {
104 std::string robot_sn = argv[1];
114 spdlog::warn(
"Fault occurred on the connected robot, trying to clear ...");
117 spdlog::error(
"Fault cannot be cleared, exiting ...");
120 spdlog::info(
"Fault on the connected robot is cleared");
124 spdlog::info(
"Enabling robot ...");
129 std::this_thread::sleep_for(std::chrono::seconds(1));
131 spdlog::info(
"Robot is now operational");
134 spdlog::info(
"Moving to home pose");
135 robot.
SwitchMode(flexiv::rdk::Mode::NRT_PRIMITIVE_EXECUTION);
139 while (robot.
busy()) {
140 std::this_thread::sleep_for(std::chrono::seconds(1));
147 robot.
SwitchMode(flexiv::rdk::Mode::RT_CARTESIAN_MOTION_FORCE);
151 spdlog::info(
"Initial TCP pose set to [position 3x1, rotation (quaternion) 4x1]: "
152 + flexiv::rdk::utility::Arr2Str(init_pose));
157 scheduler.
AddTask(std::bind(PeriodicTask, std::ref(robot), std::ref(init_pose)),
163 while (!g_stop_sched) {
164 std::this_thread::sleep_for(std::chrono::milliseconds(1));
172 std::ofstream csv_file;
173 std::string csv_file_name =
"test_data.csv";
174 csv_file.open(csv_file_name);
175 if (csv_file.is_open()) {
176 spdlog::info(
"Created new log file: {}", csv_file_name);
178 spdlog::error(
"Failed to create log file: {}", csv_file_name);
183 if (loop_counter_buf.size() != target_x_buf.size()
184 || target_x_buf.size() != actual_x_buf.size()) {
186 "Size mismatch: loop_counter_buf.size() = {}, target_x_buf.size() = {}, "
187 "actual_x_buf.size() = {}",
188 loop_counter_buf.size(), target_x_buf.size(), actual_x_buf.size());
193 for (
size_t i = 0; i < loop_counter_buf.size(); i++) {
194 csv_file << loop_counter_buf[i] <<
"," << target_x_buf[i] <<
"," << actual_x_buf[i]
200 spdlog::info(
"Saved {} data points to log file {}", target_x_buf.size(), csv_file_name);
202 }
catch (
const std::exception& e) {
203 spdlog::error(e.what());
Main interface with the robot, containing several function categories and background services.
void StreamCartesianMotionForce(const std::array< double, kPoseSize > &pose, const std::array< double, kCartDoF > &wrench={}, const std::array< double, kCartDoF > &acceleration={})
[Non-blocking] Continuously stream Cartesian motion and/or force command for the robot to track using...
const RobotStates states() const
[Non-blocking] Access the current robot states.
bool operational(bool verbose=true) const
[Non-blocking] Whether the robot is normally operational, which requires the following conditions to ...
void ExecutePrimitive(const std::string &pt_cmd)
[Blocking] Execute a primitive by specifying its name and parameters, which can be found in the Flexi...
void SwitchMode(Mode mode)
[Blocking] Switch to a new control mode and wait until mode transition is finished.
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 of the robot without a power cycle.
bool busy() const
[Non-blocking] Whether the robot is currently executing a task. This includes any user commanded oper...
Real-time scheduler that can simultaneously run multiple periodic tasks. Parameters for each task are...
int max_priority() const
[Non-blocking] Get 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::array< double, kPoseSize > tcp_pose