rm_control
Loading...
Searching...
No Matches
power_limit.h
Go to the documentation of this file.
1/*******************************************************************************
2 * BSD 3-Clause License
3 *
4 * Copyright (c) 2021, Qiayuan Liao
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions are met:
9 *
10 * * Redistributions of source code must retain the above copyright notice, this
11 * list of conditions and the following disclaimer.
12 *
13 * * Redistributions in binary form must reproduce the above copyright notice,
14 * this list of conditions and the following disclaimer in the documentation
15 * and/or other materials provided with the distribution.
16 *
17 * * Neither the name of the copyright holder nor the names of its
18 * contributors may be used to endorse or promote products derived from
19 * this software without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
22 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE
25 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
28 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
29 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
30 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 *******************************************************************************/
33
34//
35// Created by bruce on 2021/7/28.
36//
37
38#pragma once
39
40#include <algorithm>
41#include <cmath>
42
43#include <ros/ros.h>
44#include <rm_msgs/ChassisCmd.h>
45#include <rm_msgs/GameStatus.h>
46#include <rm_msgs/GameRobotStatus.h>
47#include <rm_msgs/PowerHeatData.h>
48#include <rm_msgs/PowerManagementSampleAndStatusData.h>
49
50namespace rm_common
51{
53{
54public:
55 PowerLimit(ros::NodeHandle& nh)
56
57 {
58 if (!nh.getParam("safety_power", safety_power_))
59 ROS_ERROR("Safety power no defined (namespace: %s)", nh.getNamespace().c_str());
60 if (!nh.getParam("capacitor_threshold", capacitor_threshold_))
61 ROS_ERROR("Capacitor threshold no defined (namespace: %s)", nh.getNamespace().c_str());
62 if (!nh.getParam("disable_cap_gyro_threshold", disable_cap_gyro_threshold_))
63 ROS_ERROR("Disable cap gyro threshold no defined (namespace: %s)", nh.getNamespace().c_str());
64 if (!nh.getParam("enable_cap_gyro_threshold", enable_cap_gyro_threshold_))
65 ROS_ERROR("Enable cap gyro threshold no defined (namespace: %s)", nh.getNamespace().c_str());
66 if (!nh.getParam("disable_use_cap_threshold", disable_use_cap_threshold_))
67 ROS_ERROR("Disable use cap threshold no defined (namespace: %s)", nh.getNamespace().c_str());
68 if (!nh.getParam("enable_use_cap_threshold", enable_use_cap_threshold_))
69 ROS_ERROR("Enable use cap threshold no defined (namespace: %s)", nh.getNamespace().c_str());
70 if (!nh.getParam("charge_power", charge_power_))
71 ROS_ERROR("Charge power no defined (namespace: %s)", nh.getNamespace().c_str());
72 if (!nh.getParam("extra_power", extra_power_))
73 ROS_ERROR("Extra power no defined (namespace: %s)", nh.getNamespace().c_str());
74 if (!nh.getParam("burst_power", burst_power_))
75 ROS_ERROR("Burst power no defined (namespace: %s)", nh.getNamespace().c_str());
76 if (!nh.getParam("standard_power", standard_power_))
77 ROS_ERROR("Standard power no defined (namespace: %s)", nh.getNamespace().c_str());
78 if (!nh.getParam("max_power_limit", max_power_limit_))
79 ROS_ERROR("max power limit no defined (namespace: %s)", nh.getNamespace().c_str());
80 if (!nh.getParam("power_gain", power_gain_))
81 ROS_ERROR("power gain no defined (namespace: %s)", nh.getNamespace().c_str());
82 if (!nh.getParam("buffer_threshold", buffer_threshold_))
83 ROS_ERROR("buffer threshold no defined (namespace: %s)", nh.getNamespace().c_str());
84 if (!nh.getParam("is_new_capacitor", is_new_capacitor_))
85 ROS_ERROR("is_new_capacitor no defined (namespace: %s)", nh.getNamespace().c_str());
86 if (!nh.getParam("total_burst_time", total_burst_time_))
87 ROS_ERROR("total burst time no defined (namespace: %s)", nh.getNamespace().c_str());
88 }
89 typedef enum
90 {
91 CHARGE = 0,
92 BURST = 1,
93 NORMAL = 2,
94 ALLOFF = 3,
95 TEST = 4,
96 } Mode;
97
98 void updateSafetyPower(int safety_power)
99 {
100 if (safety_power > 0)
101 safety_power_ = safety_power;
102 ROS_INFO("update safety power: %d", safety_power);
103 }
104 void updateState(uint8_t state)
105 {
106 if (!capacitor_is_on_)
107 expect_state_ = ALLOFF;
108 else
109 expect_state_ = state;
110 }
111 void updateCapSwitchState(bool state)
112 {
113 capacitor_is_on_ = state;
114 }
115 void setGameRobotData(const rm_msgs::GameRobotStatus data)
116 {
117 robot_id_ = data.robot_id;
118 chassis_power_limit_ = data.chassis_power_limit;
119 }
120 void setChassisPowerBuffer(const rm_msgs::PowerHeatData data)
121 {
122 chassis_power_buffer_ = data.chassis_power_buffer;
123 power_buffer_threshold_ = chassis_power_buffer_ * 0.8;
124 }
125 void setCapacityData(const rm_msgs::PowerManagementSampleAndStatusData data)
126 {
127 capacity_is_online_ = ros::Time::now() - data.stamp < ros::Duration(0.3);
128 cap_energy_ = data.capacity_remain_charge;
129 cap_state_ = data.state_machine_running_state;
130 }
131 void setRefereeStatus(bool status)
132 {
133 referee_is_online_ = status;
134 }
135 void setStartBurstTime(const ros::Time start_burst_time)
136 {
137 start_burst_time_ = start_burst_time;
138 }
139 inline void setBurstPowerLimit(const double& burst_power_limit)
140 {
141 burst_power_ = burst_power_limit;
142 }
143 ros::Time getStartBurstTime() const
144 {
145 return start_burst_time_;
146 }
147 uint8_t getState()
148 {
149 return expect_state_;
150 }
151 void setGyroPower(rm_msgs::ChassisCmd& chassis_cmd)
152 {
153 if (!allow_gyro_cap_ && cap_energy_ >= enable_cap_gyro_threshold_)
154 allow_gyro_cap_ = true;
155 if (allow_gyro_cap_ && cap_energy_ <= disable_cap_gyro_threshold_)
156 allow_gyro_cap_ = false;
157 if (allow_gyro_cap_ && chassis_power_limit_ < 80)
158 chassis_cmd.power_limit = chassis_power_limit_ + extra_power_;
159 else
160 normal(chassis_cmd);
161 // expect_state_ = NORMAL;
162 }
163 void setBurstPower(rm_msgs::ChassisCmd& chassis_cmd)
164 {
165 if (!allow_use_cap_ && cap_energy_ >= enable_use_cap_threshold_)
166 allow_use_cap_ = true;
167 if (allow_use_cap_ && cap_energy_ <= disable_use_cap_threshold_)
168 allow_use_cap_ = false;
169 if (allow_use_cap_)
170 {
171 if (ros::Time::now() - start_burst_time_ < ros::Duration(total_burst_time_))
172 chassis_cmd.power_limit = burst_power_;
173 else
174 chassis_cmd.power_limit = standard_power_;
175 }
176 else
177 normal(chassis_cmd);
178 // expect_state_ = NORMAL;
179 }
180 void setLimitPower(rm_msgs::ChassisCmd& chassis_cmd, bool is_gyro)
181 {
182 if (robot_id_ == rm_msgs::GameRobotStatus::BLUE_ENGINEER || robot_id_ == rm_msgs::GameRobotStatus::RED_ENGINEER)
183 chassis_cmd.power_limit = 400;
184 else
185 { // standard and hero
186 if (referee_is_online_)
187 {
188 if (capacity_is_online_ && expect_state_ != ALLOFF)
189 {
190 if (chassis_power_limit_ > burst_power_)
191 chassis_cmd.power_limit = burst_power_;
192 else
193 {
194 switch (is_new_capacitor_ ? expect_state_ : cap_state_)
195 {
196 case NORMAL:
197 normal(chassis_cmd);
198 break;
199 case BURST:
200 burst(chassis_cmd, is_gyro);
201 break;
202 case CHARGE:
203 charge(chassis_cmd);
204 break;
205 default:
206 zero(chassis_cmd);
207 break;
208 }
209 }
210 }
211 else
212 normal(chassis_cmd);
213 }
214 else
215 chassis_cmd.power_limit = safety_power_;
216 }
217 applyPosturePowerScale(chassis_cmd);
218 }
219
220private:
221 void charge(rm_msgs::ChassisCmd& chassis_cmd)
222 {
223 allow_use_cap_ = false;
224 chassis_cmd.power_limit = chassis_power_limit_ * 0.70;
225 }
226 void normal(rm_msgs::ChassisCmd& chassis_cmd)
227 {
228 if (is_new_capacitor_)
229 {
230 chassis_cmd.power_limit = chassis_power_limit_;
231 return;
232 }
233 allow_use_cap_ = false;
234 double buffer_energy_error = chassis_power_buffer_ - buffer_threshold_;
235 double plus_power = buffer_energy_error * power_gain_;
236 chassis_cmd.power_limit = chassis_power_limit_ + plus_power;
237 // TODO:Add protection when buffer<5
238 if (chassis_cmd.power_limit > max_power_limit_)
239 chassis_cmd.power_limit = max_power_limit_;
240 }
241 void zero(rm_msgs::ChassisCmd& chassis_cmd)
242 {
243 chassis_cmd.power_limit = 0.0;
244 }
245 void burst(rm_msgs::ChassisCmd& chassis_cmd, bool is_gyro)
246 {
247 if (cap_state_ != ALLOFF && cap_energy_ > capacitor_threshold_ && chassis_power_buffer_ > power_buffer_threshold_)
248 {
249 if (is_new_capacitor_)
250 chassis_cmd.power_limit = burst_power_;
251 else if (is_gyro)
252 setGyroPower(chassis_cmd);
253 else
254 setBurstPower(chassis_cmd);
255 }
256 else
257 normal(chassis_cmd);
258 // expect_state_ = NORMAL;
259 }
260
261 void applyPosturePowerScale(rm_msgs::ChassisCmd& chassis_cmd) const
262 {
263 if (std::abs(posture_power_scale_ - 1.0) < 1e-6)
264 return;
265 chassis_cmd.power_limit = std::max(0.0, std::floor(chassis_cmd.power_limit * posture_power_scale_));
266 }
267
268 int chassis_power_buffer_;
269 int robot_id_, chassis_power_limit_;
270 int max_power_limit_{ 70 };
271 float cap_energy_;
272 double safety_power_{};
273 double capacitor_threshold_{};
274 double power_buffer_threshold_{ 50.0 };
275 double enable_cap_gyro_threshold_{}, disable_cap_gyro_threshold_{}, enable_use_cap_threshold_{},
276 disable_use_cap_threshold_{};
277 double charge_power_{}, extra_power_{}, burst_power_{}, standard_power_{};
278 double buffer_threshold_{};
279 double power_gain_{};
280 bool is_new_capacitor_{ false };
281 uint8_t expect_state_{}, cap_state_{};
282 bool capacitor_is_on_{ true };
283 bool allow_gyro_cap_{ false }, allow_use_cap_{ false };
284 double posture_power_scale_{ 1.0 };
285
286 ros::Time start_burst_time_{};
287 int total_burst_time_{};
288
289 bool referee_is_online_{ false };
290 bool capacity_is_online_{ false };
291};
292} // namespace rm_common
Definition power_limit.h:53
PowerLimit(ros::NodeHandle &nh)
Definition power_limit.h:55
void updateState(uint8_t state)
Definition power_limit.h:104
void setRefereeStatus(bool status)
Definition power_limit.h:131
void setCapacityData(const rm_msgs::PowerManagementSampleAndStatusData data)
Definition power_limit.h:125
void setChassisPowerBuffer(const rm_msgs::PowerHeatData data)
Definition power_limit.h:120
void setGameRobotData(const rm_msgs::GameRobotStatus data)
Definition power_limit.h:115
Mode
Definition power_limit.h:90
@ BURST
Definition power_limit.h:92
@ ALLOFF
Definition power_limit.h:94
@ CHARGE
Definition power_limit.h:91
@ NORMAL
Definition power_limit.h:93
@ TEST
Definition power_limit.h:95
ros::Time getStartBurstTime() const
Definition power_limit.h:143
void setBurstPower(rm_msgs::ChassisCmd &chassis_cmd)
Definition power_limit.h:163
uint8_t getState()
Definition power_limit.h:147
void setLimitPower(rm_msgs::ChassisCmd &chassis_cmd, bool is_gyro)
Definition power_limit.h:180
void updateCapSwitchState(bool state)
Definition power_limit.h:111
void setStartBurstTime(const ros::Time start_burst_time)
Definition power_limit.h:135
void setBurstPowerLimit(const double &burst_power_limit)
Definition power_limit.h:139
void setGyroPower(rm_msgs::ChassisCmd &chassis_cmd)
Definition power_limit.h:151
void updateSafetyPower(int safety_power)
Definition power_limit.h:98
Definition calibration_queue.h:44