Flexiv RDK APIs  1.6.0
test_dynamics_engine.cpp
1 
8 #include <flexiv/rdk/robot.hpp>
9 #include <flexiv/rdk/model.hpp>
10 #include <flexiv/rdk/tool.hpp>
11 #include <flexiv/rdk/utility.hpp>
12 #include <spdlog/spdlog.h>
13 #include <Eigen/Eigen>
14 
15 #include <iostream>
16 #include <iomanip>
17 #include <thread>
18 #include <chrono>
19 
20 namespace {
22 struct GroundTruth
23 {
25  Eigen::Matrix<double, 6, 7> J;
27  Eigen::Matrix<double, 7, 7> M;
29  Eigen::Matrix<double, 7, 1> G;
30 };
31 }
32 
34 void StepDynamics(flexiv::rdk::Robot& robot, flexiv::rdk::Model& model, const GroundTruth& ref)
35 {
36  // Mark timer start point
37  auto tic = std::chrono::high_resolution_clock::now();
38 
39  // Update robot model in dynamics engine
40  model.Update(robot.states().q, robot.states().dtheta);
41 
42  // Get J, M, G from dynamic engine
43  Eigen::MatrixXd J = model.J("flange");
44  Eigen::MatrixXd M = model.M();
45  Eigen::VectorXd G = model.g();
46 
47  // Get and print computation time
48  auto toc = std::chrono::high_resolution_clock::now();
49  auto computation_time
50  = std::chrono::duration_cast<std::chrono::microseconds>(toc - tic).count();
51  std::cout << "===================================================================" << std::endl;
52  std::cout << "Computation time = " << computation_time << " us" << std::endl;
53 
54  // Evaluate J, M, G with true value
55  auto delta_J = J - ref.J;
56  auto delta_M = M - ref.M;
57  auto delta_G = G - ref.G;
58 
59  std::cout << std::fixed << std::setprecision(5);
60  std::cout << "Difference of J between ground truth (MATLAB) and integrated dynamics engine = "
61  << std::endl
62  << delta_J << std::endl;
63  std::cout << "Norm of delta J: " << delta_J.norm() << '\n' << std::endl;
64 
65  std::cout << "Difference of M between ground truth (MATLAB) and integrated dynamics engine = "
66  << std::endl
67  << delta_M << std::endl;
68  std::cout << "Norm of delta M: " << delta_M.norm() << '\n' << std::endl;
69 
70  std::cout << "Difference of G between ground truth (MATLAB) and integrated dynamics engine = "
71  << std::endl
72  << delta_G.transpose() << std::endl;
73  std::cout << "Norm of delta G: " << delta_G.norm() << '\n' << std::endl;
74 }
75 
76 void PrintHelp()
77 {
78  // clang-format off
79  std::cout << "Required arguments: [robot_sn]" << std::endl;
80  std::cout << " robot_sn: Serial number of the robot to connect. Remove any space, e.g. Rizon4s-123456" << std::endl;
81  std::cout << "Optional arguments: None" << std::endl;
82  std::cout << std::endl;
83  // clang-format on
84 }
85 
86 int main(int argc, char* argv[])
87 {
88  // Parse Parameters
89  //==============================================================================================
90  if (argc < 2 || flexiv::rdk::utility::ProgramArgsExistAny(argc, argv, {"-h", "--help"})) {
91  PrintHelp();
92  return 1;
93  }
94 
95  // Serial number of the robot to connect to. Remove any space, for example: Rizon4s-123456
96  std::string robot_sn = argv[1];
97 
98  try {
99  // RDK Initialization
100  //==========================================================================================
101  // Instantiate robot interface
102  flexiv::rdk::Robot robot(robot_sn);
103 
104  // Clear fault on the connected robot if any
105  if (robot.fault()) {
106  spdlog::warn("Fault occurred on the connected robot, trying to clear ...");
107  // Try to clear the fault
108  if (!robot.ClearFault()) {
109  spdlog::error("Fault cannot be cleared, exiting ...");
110  return 1;
111  }
112  spdlog::info("Fault on the connected robot is cleared");
113  }
114 
115  // Enable the robot, make sure the E-stop is released before enabling
116  spdlog::info("Enabling robot ...");
117  robot.Enable();
118 
119  // Wait for the robot to become operational
120  while (!robot.operational()) {
121  std::this_thread::sleep_for(std::chrono::seconds(1));
122  }
123  spdlog::info("Robot is now operational");
124 
125  // Set mode after robot is operational
126  robot.SwitchMode(flexiv::rdk::Mode::NRT_PLAN_EXECUTION);
127 
128  // Bring Robot To Home
129  //==========================================================================================
130  robot.ExecutePlan("PLAN-Home");
131 
132  // Wait for the execution to finish
133  do {
134  std::this_thread::sleep_for(std::chrono::seconds(1));
135  } while (robot.busy());
136 
137  // Put mode back to IDLE
138  robot.SwitchMode(flexiv::rdk::Mode::IDLE);
139 
140  // Test Dynamics Engine without Tool
141  //==========================================================================================
142  spdlog::info(">>>>> Test 1: no end-effector tool <<<<<");
143 
144  // Instantiate dynamics engine
145  flexiv::rdk::Model model(robot);
146 
147  // Ground truth from MATLAB without robot tool
148  GroundTruth ref;
149  // clang-format off
150  ref.J <<
151  0.110000000000000, 0.078420538028673, 0.034471999940354, -0.368152340866938, -0.064278760968654, 0.136000000000000, -0.000000000000000,
152  0.687004857483100, -0.000000000000000, 0.576684003660457, 0.000000000000000, 0.033475407198662, -0.000000000000000, -0.000000000000000,
153  0.000000000000000, 0.687004857483100, -0.028925442435894, -0.417782862794537, -0.076604444311898, 0.110000000000000, -0.000000000000000,
154  0.000000000000000, -0.000000000000000, 0.642787609686539, 0.000000000000000, 0.766044443118978, -0.000000000000000, 0.000000000000000,
155  0, -1.000000000000000, -0.000000000000000, 1.000000000000000, 0.000000000000000, -1.000000000000000, 0.000000000000000,
156  1.000000000000000, -0.000000000000000, 0.766044443118978, 0.000000000000000, -0.642787609686539, -0.000000000000000, -1.000000000000000;
157  ref.M <<
158  2.480084579964625, -0.066276150278304, 1.520475428405090, -0.082258763257690, -0.082884472612488, 0.008542255000000, -0.000900000000000,
159  -0.066276150278304, 2.778187401738267, 0.067350373889147, -1.100953424157635, -0.129191018084721, 0.165182543869134, -0.000000000000000,
160  1.520475428405090, 0.067350373889147, 1.074177611590570, -0.000410055889147, -0.043572229972025, -0.001968185110853, -0.000689439998807,
161  -0.082258763257690, -1.100953424157635, -0.000410055889147, 0.964760218577003, 0.123748338084721, -0.125985653288502, 0.000000000000000,
162  -0.082884472612488, -0.129191018084721, -0.043572229972025, 0.123748338084721, 0.038006882479315, -0.020080821084721, 0.000578508848718,
163  0.008542255000000, 0.165182543869134, -0.001968185110853, -0.125985653288502, -0.020080821084721, 0.034608170000000, 0,
164  -0.000900000000000, -0.000000000000000, -0.000689439998807, 0.000000000000000, 0.000578508848718, 0, 0.000900000000000;
165  ref.G <<
166  0.000000000000000, 46.598931189891374, 1.086347692836129, -19.279904969860052, -2.045058704525489, 2.300886450000000, 0;
167  // clang-format on
168 
169  // Step the dynamics engine
170  int i = 0;
171  while (++i <= 3) {
172  StepDynamics(robot, model, ref);
173  std::this_thread::sleep_for(std::chrono::milliseconds(100));
174  }
175 
176  // Test Dynamics Engine with Tool
177  //==========================================================================================
178  spdlog::info(">>>>> Test 2: with end-effector tool <<<<<");
179 
180  // Ground truth from MATLAB with robot tool
181  // clang-format off
182  ref.M <<
183  2.916316686749461, -0.052869517013466, 1.903540434220357, -0.124348845003517, -0.041914639740668, 0.027649255000000, -0.001464000000000,
184  -0.052869517013466, 3.222619358431081, 0.053667041477633, -1.414236317529289, -0.184390078851855, 0.259867572215541, -0.000000000000000,
185  1.903540434220357, 0.053667041477633, 1.416023230140298, -0.002724223477633, 0.000093550780077, 0.001155982477633, -0.001121489064726,
186  -0.124348845003517, -1.414236317529289, -0.002724223477633, 1.287676548627496, 0.177147398851855, -0.244344118313748, 0.000000000000000,
187  -0.041914639740668, -0.184390078851855, 0.000093550780077, 0.177147398851855, 0.054219756143365, -0.038829881851855, 0.000941041060581,
188  0.027649255000000, 0.259867572215541, 0.001155982477633, -0.244344118313748, -0.038829881851855, 0.082171270000000, 0,
189  -0.001464000000000, -0.000000000000000, -0.001121489064726, 0.000000000000000, 0.000941041060581, 0, 0.001464000000000;
190 
191  // Matlab value is the joint torque to resist gravity
192  ref.G <<
193  -0.000000000000001, 52.664497076609663, 0.830964961569619, -22.968509865473024, -2.721399343355234, 3.272076450000000, 0;
194  // clang-format on
195 
196  // Instantiate tool interface
197  flexiv::rdk::Tool tool(robot);
198 
199  // Set name and parameters for the test tool
200  std::string tool_name = "DynamicsTestTool";
201  flexiv::rdk::ToolParams tool_params;
202  tool_params.mass = 0.9;
203  tool_params.CoM = {0.0, 0.0, 0.057};
204  tool_params.inertia = {2.768e-03, 3.149e-03, 5.64e-04, 0.0, 0.0, 0.0};
205  tool_params.tcp_location = {0.0, -0.207, 0.09, 0.7071068, 0.7071068, 0.0, 0.0};
206 
207  // Remove any existing tool with the same name
208  if (tool.exist(tool_name)) {
209  spdlog::warn("Tool with the same name [{}] already exists, removing it now", tool_name);
210  // Switch to other tool or no tool (Flange) before removing the current tool
211  tool.Switch("Flange");
212  tool.Remove(tool_name);
213  }
214 
215  // Add the test tool
216  spdlog::info("Adding test tool [{}] to the robot", tool_name);
217  tool.Add(tool_name, tool_params);
218 
219  // Switch to the newly added test tool, i.e. set it as the active tool
220  spdlog::info("Switching to test tool [{}]", tool_name);
221  tool.Switch(tool_name);
222 
223  // Get and print the current active tool, should be the test tool
224  spdlog::info("Current active tool: {}", tool.name());
225 
226  // Reload robot + tool model using the latest data synced from the connected robot
227  model.Reload();
228 
229  // Step the dynamics engine again
230  i = 0;
231  while (++i <= 3) {
232  StepDynamics(robot, model, ref);
233  std::this_thread::sleep_for(std::chrono::milliseconds(100));
234  }
235 
236  // Switch to other tool or no tool (Flange) before removing the current tool
237  tool.Switch("Flange");
238 
239  // Clean up by removing the test tool
240  spdlog::info("Removing tool [{}]", tool_name);
241  tool.Remove(tool_name);
242 
243  spdlog::info("Program finished");
244  } catch (const std::exception& e) {
245  spdlog::error(e.what());
246  return 1;
247  }
248 
249  return 0;
250 }
Interface to access certain robot kinematics and dynamics data.
Definition: model.hpp:21
const Eigen::MatrixXd M()
[Non-blocking] Compute and get the mass matrix for the generalized coordinates, i....
void Reload()
[Blocking] Reload robot model using the latest data synced from the connected robot....
const Eigen::MatrixXd J(const std::string &link_name)
[Non-blocking] Compute and get the Jacobian matrix at the frame of the specified link ,...
const Eigen::VectorXd g()
[Non-blocking] Compute and get the gravity force vector for the generalized coordinates,...
void Update(const std::vector< double > &positions, const std::vector< double > &velocities)
[Non-blocking] Update robot model using new joint states data.
Main interface with the robot, containing several function categories and background services.
Definition: robot.hpp:25
void ExecutePlan(unsigned int index, bool continue_exec=false, bool block_until_started=true)
[Blocking] Execute a plan by specifying its index.
const RobotStates states() const
[Non-blocking] Current states data of the robot.
bool operational(bool verbose=true) const
[Non-blocking] Whether the robot is ready to be operated, which requires the following conditions to ...
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...
Interface to online update and interact with the robot tools. All updates will take effect immediatel...
Definition: tool.hpp:42
std::vector< double > dtheta
Definition: data.hpp:158
std::vector< double > q
Definition: data.hpp:136
Data structure containing robot tool parameters.
Definition: tool.hpp:20
std::array< double, kPoseSize > tcp_location
Definition: tool.hpp:33
std::array< double, 3 > CoM
Definition: tool.hpp:25
std::array< double, 6 > inertia
Definition: tool.hpp:28