Skip to content

Commit 6b72f4e

Browse files
committed
add g1 protect functions
1 parent 811bc77 commit 6b72f4e

File tree

3 files changed

+141
-1
lines changed

3 files changed

+141
-1
lines changed

example/g1/CMakeLists.txt

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
21
add_executable(g1_loco_client high_level/g1_loco_client_example.cpp)
32
target_link_libraries(g1_loco_client unitree_sdk2)
43

@@ -20,6 +19,11 @@ target_link_libraries(g1_audio_client_example unitree_sdk2)
2019
add_executable(g1_dex3_example dex3/g1_dex3_example.cpp)
2120
target_link_libraries(g1_dex3_example unitree_sdk2)
2221

22+
find_package(Boost COMPONENTS program_options)
23+
if(Boost_FOUND)
24+
add_executable(g1_termination low_level/terminations.cpp)
25+
target_link_libraries(g1_termination unitree_sdk2 Boost::program_options)
26+
endif()
2327

2428
find_package(yaml-cpp QUIET)
2529
if(yaml-cpp_FOUND)
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
#include <unitree/robot/g1/common/terminations.hpp>
2+
#include <boost/program_options.hpp>
3+
#include <thread>
4+
5+
namespace po = boost::program_options;
6+
7+
using namespace unitree::robot;
8+
using namespace unitree_hg::msg::dds_;
9+
10+
int main(int argc, char** argv)
11+
{
12+
// Parse command line arguments
13+
po::options_description desc("Unitree G1 termination functions testing.");
14+
desc.add_options()
15+
("network,n", po::value<std::string>()->default_value(""), "dds network interface")
16+
;
17+
po::variables_map vm;
18+
po::store(po::parse_command_line(argc, argv, desc), vm);
19+
po::notify(vm);
20+
std::cout << desc << std::endl;
21+
22+
// DDS Init
23+
ChannelFactory::Instance()->Init(0, vm["network"].as<std::string>());
24+
25+
auto lowstate_subscriber = std::make_shared<ChannelSubscriber<LowState_>>("rt/lowstate");
26+
LowState_ lowstate;
27+
lowstate_subscriber->InitChannel([&lowstate](const void* message) {
28+
lowstate = *(const LowState_*)message;
29+
});
30+
31+
std::cout << "Checking terminations..." << std::endl;
32+
33+
while (true)
34+
{
35+
if (g1::bad_orientation(lowstate, 1.0f)) { // Tip the robot over to test bad orientation
36+
std::cout << "Bad orientation detected!" << std::endl;
37+
}
38+
if (g1::lost_connection(lowstate_subscriber, 1000)) { // Unplug the network cable to test lost connection
39+
std::cout << "Lost connection!" << std::endl;
40+
}
41+
42+
std::this_thread::sleep_for(std::chrono::milliseconds(100));
43+
}
44+
45+
return 0;
46+
}
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
#pragma once
2+
3+
/**
4+
* This file implements some functions used to protect the G1 during runtime.
5+
* When the function returns true, it is recommended to set the motor to passive mode in the lower-level control.
6+
*/
7+
8+
#include <eigen3/Eigen/Dense>
9+
#include <unitree/idl/hg/LowState_.hpp>
10+
#include <unitree/idl/hg/BmsState_.hpp>
11+
#include <unitree/robot/channel/channel_subscriber.hpp>
12+
13+
namespace unitree {
14+
namespace robot {
15+
namespace g1 {
16+
17+
// robot orientation is too far from the desired orientation limits.
18+
inline bool bad_orientation(const unitree_hg::msg::dds_::LowState_ & lowstate, float limit_angle = 1.0)
19+
{
20+
auto & imu = lowstate.imu_state();
21+
Eigen::Quaternionf quat(
22+
imu.quaternion()[0],
23+
imu.quaternion()[1],
24+
imu.quaternion()[2],
25+
imu.quaternion()[3]
26+
);
27+
Eigen::Vector3f projected_gravity_b = quat.conjugate() * Eigen::Vector3f(0, 0, -1);
28+
return std::fabs(std::acos(-projected_gravity_b[2])) > limit_angle;
29+
}
30+
31+
// Joint velocities are outside of the soft joint limits
32+
inline bool joint_vel_out_of_limit(const unitree_hg::msg::dds_::LowState_ & lowstate, float limit_vel = 10.0)
33+
{
34+
auto & motors = lowstate.motor_state();
35+
return std::any_of(motors.begin(), motors.end(), [limit_vel](const auto & motor) {
36+
return std::fabs(motor.dq()) > limit_vel;
37+
});
38+
}
39+
40+
// Agnular velocities are outside of the soft joint limits
41+
inline bool ang_vel_out_of_limit(const unitree_hg::msg::dds_::LowState_ & lowstate, float limit_vel = 6.0)
42+
{
43+
auto & gyroscope = lowstate.imu_state().gyroscope();
44+
return std::any_of(gyroscope.begin(), gyroscope.end(), [limit_vel](const auto & ang_vel) {
45+
return std::fabs(ang_vel) > limit_vel;
46+
});
47+
}
48+
49+
// Motor winding temperature is above the limit
50+
inline bool motor_winding_overheat(const unitree_hg::msg::dds_::LowState_ & lowstate, float limit_temp = 120.0)
51+
{
52+
auto & motors = lowstate.motor_state();
53+
return std::any_of(motors.begin(), motors.end(), [limit_temp](const auto & motor) {
54+
return motor.temperature()[1] > limit_temp;
55+
});
56+
}
57+
58+
// Motor casing temperature is above the limit
59+
inline bool motor_casing_overheat(const unitree_hg::msg::dds_::LowState_ & lowstate, float limit_temp = 85.0)
60+
{
61+
auto & motors = lowstate.motor_state();
62+
return std::any_of(motors.begin(), motors.end(), [limit_temp](const auto & motor) {
63+
return motor.temperature()[0] > limit_temp;
64+
});
65+
}
66+
67+
// State of charge (SOC) is below the limit
68+
inline bool low_battery(const unitree_hg::msg::dds_::BmsState_ & bms_state, float limit_soc = 20.0)
69+
{
70+
return bms_state.soc() < limit_soc;
71+
}
72+
73+
/**
74+
* @brief Lost connection to the robot
75+
* This function checks if the last data available time is older than the specified timeout.
76+
* If the timeout is reached, it indicates a lost connection.
77+
*
78+
* When using a wired connection to the robot, a loose network cable may cause the connection to be interrupted.
79+
* If the program continues to run at this time, it will send a step signal to the motors, causing violent movement.
80+
*/
81+
inline bool lost_connection(unitree::robot::ChannelSubscriberPtr<unitree_hg::msg::dds_::LowState_> & subscriber, int64_t timeout_ms = 1000)
82+
{
83+
auto now = unitree::common::GetCurrentMonotonicTimeNanosecond();
84+
auto elasped_ms = (now - subscriber->GetLastDataAvailableTime()) / 1e6;
85+
return elasped_ms > timeout_ms;
86+
}
87+
88+
}
89+
}
90+
}

0 commit comments

Comments
 (0)