This tutorial executes several basic robot primitives (unit skills). For detailed documentation on all available primitives, please see Flexiv Primitives.
#include <spdlog/spdlog.h>
#include <iostream>
#include <iomanip>
#include <thread>
#include <algorithm>
using namespace flexiv;
void PrintHelp()
{
std::cout << "Required arguments: [robot_sn]" << std::endl;
std::cout << " robot_sn: Serial number of the robot to connect. Remove any space, e.g. Enlight-L-123456" << std::endl;
std::cout << "Optional arguments: None" << std::endl;
std::cout << std::endl;
}
int main(int argc, char* argv[])
{
if (argc < 2 ||
rdk::utility::ProgramArgsExistAny(argc, argv, {
"-h",
"--help"})) {
PrintHelp();
return 1;
}
std::string robot_sn = argv[1];
spdlog::info(
">>> Tutorial description <<<\nThis tutorial executes several basic robot primitives (unit "
"skills). For detailed documentation on all available primitives, please see [Flexiv "
"Primitives](https://www.flexiv.com/primitives/).\n");
try {
rdk::Robot robot(robot_sn);
if (robot.fault()) {
spdlog::warn("Fault occurred on the connected robot, trying to clear ...");
if (!robot.ClearFault()) {
spdlog::error("Fault cannot be cleared, exiting ...");
return 1;
}
spdlog::info("Fault on the connected robot is cleared");
}
spdlog::info("Servo on the robot ...");
robot.ServoOn();
while (!robot.operational()) {
std::this_thread::sleep_for(std::chrono::seconds(1));
}
spdlog::info("Robot is now operational");
const auto& single_arm_groups = robot.info().single_arm_groups;
if (single_arm_groups.empty()) {
throw std::runtime_error("No single-arm joint group found on the connected robot");
}
spdlog::info("Moving to home pose");
robot.Home();
robot.SwitchMode(
rdk::Mode::NRT_PRIMITIVE_EXECUTION);
spdlog::info("Executing primitive: MoveJ");
std::map<rdk::JointGroup, rdk::PrimitiveArgs> pt_args;
for (const auto& [group, _] : single_arm_groups) {
pt_args[group] = rdk::PrimitiveArgs("MoveJ",
{
{"target", rdk::JPos({30, -45, 0, 90, 0, 40, 30}, {-50, 30})},
{"waypoints",
std::vector<rdk::JPos> {rdk::JPos({10, -30, 10, 30, 10, 15, 10}, {-15, 10}),
rdk::JPos({20, -60, -10, 60, -10, 30, 20}, {-30, 20})}},
});
}
robot.ExecutePrimitive(pt_args);
while (true) {
const auto primitive_states = robot.primitive_states();
if (
rdk::utility::PrimitiveStateTrueForGroups(
primitive_states, "reachedTarget")) {
break;
}
spdlog::info("Current primitive states:");
for (const auto& [group, pt_states] : primitive_states) {
std::cout <<
rdk::kJointGroupNames.at(group) <<
":" << std::endl;
std::cout << "primitiveName: " << pt_states.pt_name << std::endl;
for (const auto& [name, value] : pt_states.names_and_values) {
std::cout << name <<
": " <<
rdk::utility::FlexivTypes2Str(value);
std::cout << std::endl;
}
}
std::this_thread::sleep_for(std::chrono::seconds(1));
}
spdlog::info("Executing primitive: MoveL");
pt_args.clear();
for (const auto& [group, _] : single_arm_groups) {
pt_args[group] = rdk::PrimitiveArgs("MoveL",
{{"target",
rdk::Coord({0.3, -0.1, 0.2}, {160, 20, 180}, {"WORLD", "WORLD_ORIGIN"})},
{"waypoints",
std::vector<rdk::Coord> {rdk::Coord({0.1, 0.1, 0.1}, {-160, -20, 180},
{"WORLD", "WORLD_ORIGIN"}),
rdk::Coord({0.3, 0.2, 0.1}, {180, 0, 180}, {"WORLD", "WORLD_ORIGIN"})}},
{"vel", 0.6}, {"zoneRadius", "Z50"}});
}
robot.ExecutePrimitive(pt_args);
while (!rdk::utility::PrimitiveStateTrueForGroups(robot.primitive_states(), "reachedTarget")) {
std::this_thread::sleep_for(std::chrono::seconds(1));
}
spdlog::info("Executing primitive: MoveL");
std::array<double, 4> targetQuat = {0.9185587, 0.1767767, 0.3061862, 0.1767767};
auto targetEulerDeg =
rdk::utility::Rad2Deg(
rdk::utility::Quat2EulerZYX(targetQuat));
pt_args.clear();
for (const auto& [group, _] : single_arm_groups) {
pt_args[group] = rdk::PrimitiveArgs("MoveL",
{
{"target", rdk::Coord({0.0, 0.0, 0.0}, targetEulerDeg, {"TRAJ", "START"})},
{"vel", 0.2},
});
}
robot.ExecutePrimitive(pt_args);
while (!rdk::utility::PrimitiveStateTrueForGroups(robot.primitive_states(), "reachedTarget")) {
std::this_thread::sleep_for(std::chrono::seconds(1));
}
robot.Stop();
} catch (const std::exception& e) {
spdlog::error(e.what());
return 1;
}
return 0;
}