Skip to content

Commit 211dad4

Browse files
authored
Merge pull request #21 from unitreerobotics/update-g1_arm_action-api
add execute_custom_action api
2 parents 3eb9804 + 2462b61 commit 211dad4

File tree

4 files changed

+110
-80
lines changed

4 files changed

+110
-80
lines changed

example/g1/CMakeLists.txt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,6 @@ target_link_libraries(g1_arm5_sdk_dds_example unitree_sdk2)
77
add_executable(g1_arm7_sdk_dds_example high_level/g1_arm7_sdk_dds_example.cpp)
88
target_link_libraries(g1_arm7_sdk_dds_example unitree_sdk2)
99

10-
add_executable(g1_arm_action_example high_level/g1_arm_action_example.cpp)
11-
target_link_libraries(g1_arm_action_example unitree_sdk2)
12-
1310
add_executable(g1_ankle_swing_example low_level/g1_ankle_swing_example.cpp)
1411
target_link_libraries(g1_ankle_swing_example unitree_sdk2)
1512

@@ -23,6 +20,9 @@ find_package(Boost COMPONENTS program_options)
2320
if(Boost_FOUND)
2421
add_executable(g1_termination low_level/terminations.cpp)
2522
target_link_libraries(g1_termination unitree_sdk2 Boost::program_options)
23+
24+
add_executable(g1_arm_action_example high_level/g1_arm_action_example.cpp)
25+
target_link_libraries(g1_arm_action_example unitree_sdk2 Boost::program_options)
2626
endif()
2727

2828
find_package(yaml-cpp QUIET)

example/g1/high_level/g1_arm_action_example.cpp

Lines changed: 61 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -4,76 +4,81 @@
44
*/
55
#include "unitree/robot/g1/arm/g1_arm_action_error.hpp"
66
#include "unitree/robot/g1/arm/g1_arm_action_client.hpp"
7+
#include <boost/program_options.hpp>
78

9+
namespace po = boost::program_options;
10+
using namespace unitree::robot;
811
using namespace unitree::robot::g1;
912

1013
int main(int argc, const char** argv)
1114
{
1215
std::cout << " --- Unitree Robotics --- \n";
1316
std::cout << " G1 Arm Action Example \n\n";
1417

15-
// Unitree DDS Initialization; arg[1] is the network interface
16-
unitree::robot::ChannelFactory::Instance()->Init(0, argc > 1 ? argv[1] : "");
18+
// Parse command line arguments
19+
po::options_description desc("Unitree G1 Arm Action Example.");
20+
desc.add_options()
21+
("help,h", "show help message")
22+
("network,n", po::value<std::string>()->default_value(""), "dds network interface")
23+
("list,l", "list all supported actions")
24+
("id,i", po::value<int>(), "action id to execute, 0 to list all supported actions")
25+
("name", po::value<std::string>(), "custom action name to execute")
26+
("stop", "stop the current custom action")
27+
;
28+
po::variables_map vm;
29+
po::store(po::parse_command_line(argc, argv, desc), vm);
30+
po::notify(vm);
31+
if(argc < 2 || vm.count("help")) {
32+
std::cout << desc << std::endl;
33+
return 0;
34+
}
1735

18-
auto client = std::make_shared<unitree::robot::g1::G1ArmActionClient>();
19-
client->Init();
20-
client->SetTimeout(10.f); // All actions will last less than 10 seconds.
36+
// DDS Init
37+
ChannelFactory::Instance()->Init(0, vm["network"].as<std::string>());
2138

22-
std::cout << "Usage: \n";
23-
std::cout << " - 0: print supported actions.\n";
24-
std::cout << " - an id: execute an action.\n";
25-
std::cout << "Attention: \n";
26-
std::cout << " Some actions will not be displayed on the APP, \n";
27-
std::cout << " but can be executed by the program.\n";
28-
std::cout << " These actions may cause the robot to fall,\n";
29-
std::cout << " so please execute them with caution.\n";
39+
auto client = std::make_shared<G1ArmActionClient>();
40+
client->Init();
41+
// Attention: unitree actions are all less than 10s,
42+
// but the custom actions may be longer.
43+
client->SetTimeout(10.f);
3044

31-
int32_t action_id = 0;
32-
std::string line;
33-
while (true) {
34-
std::cout << "\nEnter action ID: .\n";
35-
std::getline(std::cin, line);
36-
try {
37-
action_id = std::stoi(line);
38-
} catch (const std::exception&) {
39-
std::cout << "Invalid input. Please enter an integer.\n";
40-
continue;
45+
if(vm.count("list") || (vm.count("id") && vm["id"].as<int>() == 0)){
46+
std::string action_list_data;
47+
int32_t ret = client->GetActionList(action_list_data);
48+
if (ret != 0) {
49+
std::cerr << "Failed to get action list, error code: " << ret << "\n";
4150
}
42-
43-
if (action_id == 0) {
44-
std::string action_list_data;
45-
int32_t ret = client->GetActionList(action_list_data);
46-
if (ret != 0) {
47-
std::cerr << "Failed to get action list, error code: " << ret << "\n";
48-
continue;
49-
}
50-
std::cout << "Available actions:\n" << action_list_data << std::endl;
51-
} else {
52-
int32_t ret = client->ExecuteAction(action_id);
53-
if(ret != 0) {
54-
switch (ret)
55-
{
56-
case UT_ROBOT_ARM_ACTION_ERR_ARMSDK:
57-
std::cout << UT_ROBOT_ARM_ACTION_ERR_ARMSDK_DESC << std::endl;
58-
break;
59-
case UT_ROBOT_ARM_ACTION_ERR_HOLDING:
60-
std::cout << UT_ROBOT_ARM_ACTION_ERR_HOLDING_DESC << std::endl;
61-
break;
62-
case UT_ROBOT_ARM_ACTION_ERR_INVALID_ACTION_ID:
63-
std::cout << UT_ROBOT_ARM_ACTION_ERR_INVALID_ACTION_ID_DESC << std::endl;
64-
break;
65-
case UT_ROBOT_ARM_ACTION_ERR_INVALID_FSM_ID:
66-
std::cout << "The actions are only supported in fsm id {500, 501, 801}" << std::endl;
67-
std::cout << "You can subscribe the topic rt/sportmodestate to check the fsm id." << std::endl;
68-
std::cout << "And in the state 801, the actions are only supported in the fsm mode {0, 3}." << std::endl;
69-
std::cout << "If an error is still returned at this point, ignore this action.";
70-
break;
71-
default:
72-
std::cerr << "Execute action failed, error code: " << ret << std::endl;
73-
break;
74-
}
51+
std::cout << "Available actions:\n" << action_list_data << std::endl;
52+
} else if (vm.count("id")) {
53+
int32_t ret = client->ExecuteAction(vm["id"].as<int>());
54+
if(ret != 0) {
55+
switch (ret)
56+
{
57+
case UT_ROBOT_ARM_ACTION_ERR_ARMSDK:
58+
std::cout << UT_ROBOT_ARM_ACTION_ERR_ARMSDK_DESC << std::endl;
59+
break;
60+
case UT_ROBOT_ARM_ACTION_ERR_HOLDING:
61+
std::cout << UT_ROBOT_ARM_ACTION_ERR_HOLDING_DESC << std::endl;
62+
break;
63+
case UT_ROBOT_ARM_ACTION_ERR_INVALID_ACTION_ID:
64+
std::cout << UT_ROBOT_ARM_ACTION_ERR_INVALID_ACTION_ID_DESC << std::endl;
65+
break;
66+
case UT_ROBOT_ARM_ACTION_ERR_INVALID_FSM_ID:
67+
std::cout << "The actions are only supported in fsm id {500, 501, 801}" << std::endl;
68+
std::cout << "You can subscribe the topic rt/sportmodestate to check the fsm id." << std::endl;
69+
std::cout << "And in the state 801, the actions are only supported in the fsm mode {0, 3}." << std::endl;
70+
std::cout << "If an error is still returned at this point, ignore this action.";
71+
break;
72+
default:
73+
std::cerr << "Execute action failed, error code: " << ret << std::endl;
74+
break;
7575
}
7676
}
77+
} else if (vm.count("name")) {
78+
int32_t ret = client->ExecuteAction(vm["name"].as<std::string>());
79+
if(ret != 0) std::cout << "Execute custom action failed, error code: " << ret << std::endl;
80+
} else if (vm.count("stop")) {
81+
int32_t ret = client->StopCustomAction();
7782
}
7883

7984
return 0;

include/unitree/robot/g1/arm/g1_arm_action_api.hpp

Lines changed: 2 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -15,22 +15,8 @@ const std::string ARM_ACTION_API_VERSION = "1.0.0.14";
1515
/*api id*/
1616
const int32_t ROBOT_API_ID_ARM_ACTION_EXECUTE_ACTION = 7106;
1717
const int32_t ROBOT_API_ID_ARM_ACTION_GET_ACTION_LIST = 7107;
18-
19-
class JsonizeArmActionCommand : public common::Jsonize {
20-
public:
21-
JsonizeArmActionCommand() {}
22-
~JsonizeArmActionCommand() {}
23-
24-
void fromJson(common::JsonMap &json) {
25-
common::FromJson(json["data"], action_id);
26-
}
27-
28-
void toJson(common::JsonMap &json) const {
29-
common::ToJson(action_id, json["data"]);
30-
}
31-
32-
int32_t action_id;
33-
};
18+
const int32_t ROBOT_API_ID_ARM_ACTION_EXECUTE_CUSTOM_ACTION = 7108;
19+
const int32_t ROBOT_API_ID_ARM_ACTION_STOP_CUSTOM_ACTION = 7113;
3420

3521
} // namespace g1
3622
} // namespace robot

include/unitree/robot/g1/arm/g1_arm_action_client.hpp

Lines changed: 44 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,13 @@ namespace g1 {
1313
*
1414
* The arm action server provides some upper body actions.
1515
* The controller is based on the `rt/arm_sdk` interface.
16+
*
17+
* The current state of the arm will be published on the `rt/arm/action/state` topic:
18+
* {
19+
* "holding": false, # Whether to hold the position after the action ends; will release after a maximum of 20 seconds
20+
* "id": 99, # Current action ID
21+
* "name": "release_arm" # Current action name
22+
* }
1623
*/
1724
class G1ArmActionClient : public Client {
1825
public:
@@ -24,19 +31,51 @@ class G1ArmActionClient : public Client {
2431
SetApiVersion(ARM_ACTION_API_VERSION);
2532
UT_ROBOT_CLIENT_REG_API_NO_PROI(ROBOT_API_ID_ARM_ACTION_EXECUTE_ACTION);
2633
UT_ROBOT_CLIENT_REG_API_NO_PROI(ROBOT_API_ID_ARM_ACTION_GET_ACTION_LIST);
34+
UT_ROBOT_CLIENT_REG_API_NO_PROI(ROBOT_API_ID_ARM_ACTION_EXECUTE_CUSTOM_ACTION);
35+
UT_ROBOT_CLIENT_REG_API_NO_PROI(ROBOT_API_ID_ARM_ACTION_STOP_CUSTOM_ACTION);
2736
}
2837

2938
/*API Call*/
39+
/**
40+
* @brief Execute Unitree's internal preset actions
41+
* Indexed by ID, where 99 is to release the action.
42+
* Some actions will hold the position at the last keyframe after completion;
43+
* you can send id = 99 or the same id to release.
44+
*
45+
* Attention:
46+
* Some actions will not be displayed on the APP,
47+
* but can be executed by the program.
48+
* These actions may cause the robot to fall,
49+
* so please execute them with caution.
50+
*/
3051
int32_t ExecuteAction(int32_t action_id) {
3152
std::string parameter, data;
32-
JsonizeArmActionCommand json;
33-
34-
json.action_id = action_id;
35-
parameter = common::ToJsonString(json);
36-
53+
parameter = R"({"action_id":)" + std::to_string(action_id) + R"(})";
3754
return Call(ROBOT_API_ID_ARM_ACTION_EXECUTE_ACTION, parameter, data);
3855
}
3956

57+
/**
58+
* @brief Execute custom teach actions, indexed by name
59+
*
60+
* # rt/arm/action/state
61+
* {
62+
* "holding": false, # teach actions do not include holding
63+
* "id": 100, # Always 100, the action is determined by the name
64+
* "name": "sth" # Current teach action name
65+
* }
66+
*/
67+
int32_t ExecuteAction(const std::string &action_name) {
68+
std::string parameter, data;
69+
parameter = R"({"action_name":")" + action_name + R"("})";
70+
return Call(ROBOT_API_ID_ARM_ACTION_EXECUTE_CUSTOM_ACTION, parameter, data);
71+
}
72+
73+
/* Stop Custom Action */
74+
int32_t StopCustomAction() {
75+
std::string parameter, data;
76+
return Call(ROBOT_API_ID_ARM_ACTION_STOP_CUSTOM_ACTION, parameter, data);
77+
}
78+
4079
int32_t GetActionList(std::string &data) {
4180
std::string parameter;
4281
return Call(ROBOT_API_ID_ARM_ACTION_GET_ACTION_LIST, parameter, data);

0 commit comments

Comments
 (0)