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 ros::Time getStartBurstTime() const
140 {
141 return start_burst_time_;
142 }
143 uint8_t getState()
144 {
145 return expect_state_;
146 }
147 void setGyroPower(rm_msgs::ChassisCmd& chassis_cmd)
148 {
149 if (!allow_gyro_cap_ && cap_energy_ >= enable_cap_gyro_threshold_)
150 allow_gyro_cap_ = true;
151 if (allow_gyro_cap_ && cap_energy_ <= disable_cap_gyro_threshold_)
152 allow_gyro_cap_ = false;
153 if (allow_gyro_cap_ && chassis_power_limit_ < 80)
154 chassis_cmd.power_limit = chassis_power_limit_ + extra_power_;
155 else
156 normal(chassis_cmd);
157 // expect_state_ = NORMAL;
158 }
159 void setBurstPower(rm_msgs::ChassisCmd& chassis_cmd)
160 {
161 if (!allow_use_cap_ && cap_energy_ >= enable_use_cap_threshold_)
162 allow_use_cap_ = true;
163 if (allow_use_cap_ && cap_energy_ <= disable_use_cap_threshold_)
164 allow_use_cap_ = false;
165 if (allow_use_cap_)
166 {
167 if (ros::Time::now() - start_burst_time_ < ros::Duration(total_burst_time_))
168 chassis_cmd.power_limit = burst_power_;
169 else
170 chassis_cmd.power_limit = standard_power_;
171 }
172 else
173 normal(chassis_cmd);
174 // expect_state_ = NORMAL;
175 }
176 void setLimitPower(rm_msgs::ChassisCmd& chassis_cmd, bool is_gyro)
177 {
178 if (robot_id_ == rm_msgs::GameRobotStatus::BLUE_ENGINEER || robot_id_ == rm_msgs::GameRobotStatus::RED_ENGINEER)
179 chassis_cmd.power_limit = 400;
180 else
181 { // standard and hero
182 if (referee_is_online_)
183 {
184 if (capacity_is_online_ && expect_state_ != ALLOFF)
185 {
186 if (chassis_power_limit_ > burst_power_)
187 chassis_cmd.power_limit = burst_power_;
188 else
189 {
190 switch (is_new_capacitor_ ? expect_state_ : cap_state_)
191 {
192 case NORMAL:
193 normal(chassis_cmd);
194 break;
195 case BURST:
196 burst(chassis_cmd, is_gyro);
197 break;
198 case CHARGE:
199 charge(chassis_cmd);
200 break;
201 default:
202 zero(chassis_cmd);
203 break;
204 }
205 }
206 }
207 else
208 normal(chassis_cmd);
209 }
210 else
211 chassis_cmd.power_limit = safety_power_;
212 }
213 applyPosturePowerScale(chassis_cmd);
214 }
215
216private:
217 void charge(rm_msgs::ChassisCmd& chassis_cmd)
218 {
219 allow_use_cap_ = false;
220 chassis_cmd.power_limit = chassis_power_limit_ * 0.70;
221 }
222 void normal(rm_msgs::ChassisCmd& chassis_cmd)
223 {
224 if (is_new_capacitor_)
225 {
226 chassis_cmd.power_limit = chassis_power_limit_;
227 return;
228 }
229 allow_use_cap_ = false;
230 double buffer_energy_error = chassis_power_buffer_ - buffer_threshold_;
231 double plus_power = buffer_energy_error * power_gain_;
232 chassis_cmd.power_limit = chassis_power_limit_ + plus_power;
233 // TODO:Add protection when buffer<5
234 if (chassis_cmd.power_limit > max_power_limit_)
235 chassis_cmd.power_limit = max_power_limit_;
236 }
237 void zero(rm_msgs::ChassisCmd& chassis_cmd)
238 {
239 chassis_cmd.power_limit = 0.0;
240 }
241 void burst(rm_msgs::ChassisCmd& chassis_cmd, bool is_gyro)
242 {
243 if (cap_state_ != ALLOFF && cap_energy_ > capacitor_threshold_ && chassis_power_buffer_ > power_buffer_threshold_)
244 {
245 if (is_new_capacitor_)
246 chassis_cmd.power_limit = burst_power_;
247 else if (is_gyro)
248 setGyroPower(chassis_cmd);
249 else
250 setBurstPower(chassis_cmd);
251 }
252 else
253 normal(chassis_cmd);
254 // expect_state_ = NORMAL;
255 }
256
257 void applyPosturePowerScale(rm_msgs::ChassisCmd& chassis_cmd) const
258 {
259 if (std::abs(posture_power_scale_ - 1.0) < 1e-6)
260 return;
261 chassis_cmd.power_limit = std::max(0.0, std::floor(chassis_cmd.power_limit * posture_power_scale_));
262 }
263
264 int chassis_power_buffer_;
265 int robot_id_, chassis_power_limit_;
266 int max_power_limit_{ 70 };
267 float cap_energy_;
268 double safety_power_{};
269 double capacitor_threshold_{};
270 double power_buffer_threshold_{ 50.0 };
271 double enable_cap_gyro_threshold_{}, disable_cap_gyro_threshold_{}, enable_use_cap_threshold_{},
272 disable_use_cap_threshold_{};
273 double charge_power_{}, extra_power_{}, burst_power_{}, standard_power_{};
274 double buffer_threshold_{};
275 double power_gain_{};
276 bool is_new_capacitor_{ false };
277 uint8_t expect_state_{}, cap_state_{};
278 bool capacitor_is_on_{ true };
279 bool allow_gyro_cap_{ false }, allow_use_cap_{ false };
280 double posture_power_scale_{ 1.0 };
281
282 ros::Time start_burst_time_{};
283 int total_burst_time_{};
284
285 bool referee_is_online_{ false };
286 bool capacity_is_online_{ false };
287};
288} // 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:139
void setBurstPower(rm_msgs::ChassisCmd &chassis_cmd)
Definition power_limit.h:159
uint8_t getState()
Definition power_limit.h:143
void setLimitPower(rm_msgs::ChassisCmd &chassis_cmd, bool is_gyro)
Definition power_limit.h:176
void updateCapSwitchState(bool state)
Definition power_limit.h:111
void setStartBurstTime(const ros::Time start_burst_time)
Definition power_limit.h:135
void setGyroPower(rm_msgs::ChassisCmd &chassis_cmd)
Definition power_limit.h:147
void updateSafetyPower(int safety_power)
Definition power_limit.h:98
Definition calibration_queue.h:44