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