Skip to content

Commit 106da54

Browse files
Attackerスキルに CUT_THEIR_PASS / STEAL_BALL を追加 (#506)
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
1 parent 7178c82 commit 106da54

13 files changed

Lines changed: 190 additions & 144 deletions

File tree

crane_bringup/launch/crane.launch.xml

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,12 +56,14 @@
5656
<node pkg="crane_sender" exec="sim_sender_node" output="screen">
5757
<param name="no_movement" value="false"/>
5858
<param name="latency_ms" value="0.0"/>
59-
<param name="k_gain" value="2.0"/>
59+
<param name="k_gain" value="1.5"/>
6060
<param name="i_gain" value="0.0"/>
61-
<param name="d_gain" value="0.1"/>
61+
<param name="d_gain" value="1.5"/>
6262
<param name="theta_k_gain" value="2.0"/>
6363
<param name="theta_i_gain" value="0.0"/>
6464
<param name="theta_d_gain" value="0.1"/>
65+
<param name="kick_power_limit_straight" value="0.6"/>
66+
<param name="kick_power_limit_chip" value="1.0"/>
6567
<param name="sim_mode" value="true"/>
6668
</node>
6769
</group>
@@ -74,6 +76,8 @@
7476
<param name="theta_ki" value="0.0"/>
7577
<param name="theta_kd" value="0.5"/>
7678
<param name="sim_mode" value="$(var sim)"/>
79+
<param name="kick_power_limit_straight" value="1.0"/>
80+
<param name="kick_power_limit_chip" value="1.0"/>
7781
</node>
7882
</group>
7983

crane_robot_skills/include/crane_robot_skills/attacker.hpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
#include <crane_robot_skills/receive.hpp>
1515
#include <crane_robot_skills/redirect.hpp>
1616
#include <crane_robot_skills/skill_base.hpp>
17+
#include <crane_robot_skills/steal_ball.hpp>
1718
#include <memory>
1819
#include <utility>
1920
#include <vector>
@@ -23,6 +24,8 @@ namespace crane::skills
2324
enum class AttackerState {
2425
ENTRY_POINT,
2526
FORCED_PASS,
27+
CUT_THEIR_PASS,
28+
STEAL_BALL,
2629
REDIRECT_GOAL_KICK,
2730
GOAL_KICK,
2831
CLEARING_KICK,
@@ -55,6 +58,8 @@ class Attacker : public SkillBaseWithState<AttackerState, RobotCommandWrapperPos
5558
Receive receive_skill;
5659

5760
Redirect redirect_skill;
61+
62+
StealBall steal_ball_skill;
5863
};
5964
} // namespace crane::skills
6065
#endif // CRANE_ROBOT_SKILLS__ATTACKER_HPP_

crane_robot_skills/include/crane_robot_skills/ball_nearby_positioner.hpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,8 @@ class BallNearByPositioner : public SkillBase<RobotCommandWrapperPosition>
4242
return 0.5;
4343
case crane_msgs::msg::PlaySituation::STOP:
4444
return 0.5;
45+
case crane_msgs::msg::PlaySituation::THEIR_BALL_PLACEMENT:
46+
return 0.5;
4547
default:
4648
return 0.0;
4749
}

crane_robot_skills/include/crane_robot_skills/steal_ball.hpp

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,6 @@ namespace crane::skills
1919
enum class StealBallState {
2020
MOVE_TO_FRONT,
2121
STEAL,
22-
PASS,
23-
INTERCEPT,
2422
};
2523
class StealBall : public SkillBaseWithState<StealBallState, RobotCommandWrapperPosition>
2624
{

crane_robot_skills/src/attacker.cpp

Lines changed: 70 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,8 @@ Attacker::Attacker(RobotCommandWrapperBase::SharedPtr & base)
1717
kick_skill(base),
1818
goal_kick_skill(base),
1919
receive_skill(base),
20-
redirect_skill(base)
20+
redirect_skill(base),
21+
steal_ball_skill(base)
2122
{
2223
setParameter("receiver_id", 0);
2324
addStateFunction(
@@ -83,7 +84,7 @@ Attacker::Attacker(RobotCommandWrapperBase::SharedPtr & base)
8384
Point target =
8485
world_model()->ball.pos +
8586
getVerticalVec(receiver->pose.pos - world_model()->ball.pos).normalized() * 0.3;
86-
command.setTargetPosition(target).lookAtBallFrom(target);
87+
command.setTargetPosition(target).lookAtBallFrom(target).enableBallAvoidance();
8788
if (robot()->getDistance(target) < 0.1) {
8889
forced_pass_phase = 1;
8990
}
@@ -111,6 +112,40 @@ Attacker::Attacker(RobotCommandWrapperBase::SharedPtr & base)
111112
return Status::RUNNING;
112113
});
113114

115+
addTransition(AttackerState::ENTRY_POINT, AttackerState::CUT_THEIR_PASS, [this]() -> bool {
116+
return not world_model()->isOurBallByBallOwnerCalculator() && world_model()->ball.isMoving(0.2);
117+
});
118+
119+
addTransition(AttackerState::CUT_THEIR_PASS, AttackerState::ENTRY_POINT, [this]() -> bool {
120+
return world_model()->isOurBallByBallOwnerCalculator();
121+
});
122+
123+
addStateFunction(
124+
AttackerState::CUT_THEIR_PASS,
125+
[this]([[maybe_unused]] const ConsaiVisualizerWrapper::SharedPtr & visualizer) -> Status {
126+
return receive_skill.run(visualizer);
127+
});
128+
129+
addTransition(AttackerState::ENTRY_POINT, AttackerState::STEAL_BALL, [this]() -> bool {
130+
// 止まっているボールを相手が持っているとき
131+
return not world_model()->isOurBallByBallOwnerCalculator() &&
132+
world_model()->ball.isStopped(0.1) &&
133+
world_model()
134+
->getNearestRobotWithDistanceFromPoint(
135+
world_model()->ball.pos, world_model()->theirs.getAvailableRobots())
136+
.second < 0.5;
137+
});
138+
139+
addTransition(AttackerState::STEAL_BALL, AttackerState::ENTRY_POINT, [this]() -> bool {
140+
return world_model()->isOurBallByBallOwnerCalculator();
141+
});
142+
143+
addStateFunction(
144+
AttackerState::STEAL_BALL,
145+
[this]([[maybe_unused]] const ConsaiVisualizerWrapper::SharedPtr & visualizer) -> Status {
146+
return steal_ball_skill.run(visualizer);
147+
});
148+
114149
addTransition(AttackerState::ENTRY_POINT, AttackerState::REDIRECT_GOAL_KICK, [this]() -> bool {
115150
// ボールが遠くにいる
116151
if (
@@ -129,6 +164,9 @@ Attacker::Attacker(RobotCommandWrapperBase::SharedPtr & base)
129164
// ボールが止まっている
130165
if (world_model()->ball.vel.norm() < 0.5) {
131166
return true;
167+
} else if (not world_model()->isOurBallByBallOwnerCalculator()) {
168+
// 敵にボールを奪われた
169+
return true;
132170
} else {
133171
return false;
134172
}
@@ -163,25 +201,33 @@ Attacker::Attacker(RobotCommandWrapperBase::SharedPtr & base)
163201
addTransition(AttackerState::ENTRY_POINT, AttackerState::GOAL_KICK, [this]() -> bool {
164202
auto [best_angle, goal_angle_width] =
165203
world_model()->getLargestGoalAngleRangeFromPoint(world_model()->ball.pos);
204+
// ボールが近い条件はいらないかも?
166205
return robot()->getDistance(world_model()->ball.pos) < 2.0 &&
167206
goal_angle_width * 180.0 / M_PI > 5.;
168207
});
169208

209+
addTransition(AttackerState::GOAL_KICK, AttackerState::ENTRY_POINT, [this]() -> bool {
210+
// 敵にボールを奪われた
211+
return not world_model()->isOurBallByBallOwnerCalculator();
212+
});
213+
170214
addStateFunction(
171215
AttackerState::GOAL_KICK,
172216
[this]([[maybe_unused]] const ConsaiVisualizerWrapper::SharedPtr & visualizer) -> Status {
173217
return goal_kick_skill.run(visualizer);
174218
});
175219

176-
addTransition(
177-
AttackerState::ENTRY_POINT, AttackerState::CLEARING_KICK, [this]() -> bool { return false; });
220+
addTransition(AttackerState::ENTRY_POINT, AttackerState::CLEARING_KICK, [this]() -> bool {
221+
// 未実装:やばいときに蹴る
222+
return false;
223+
});
178224

179225
addStateFunction(
180226
AttackerState::CLEARING_KICK,
181227
[this]([[maybe_unused]] const ConsaiVisualizerWrapper::SharedPtr & visualizer) -> Status {
182228
kick_skill.setParameter("target", world_model()->getTheirGoalCenter());
183229
kick_skill.setParameter("kick_power", 1.0);
184-
kick_skill.setParameter("dot_threshold", 0.95);
230+
kick_skill.setParameter("dot_threshold", 0.9);
185231
kick_skill.setParameter("kick_with_chip", true);
186232
return kick_skill.run(visualizer);
187233
});
@@ -227,6 +273,11 @@ Attacker::Attacker(RobotCommandWrapperBase::SharedPtr & base)
227273
return best_score > 0.5;
228274
});
229275

276+
addTransition(AttackerState::STANDARD_PASS, AttackerState::ENTRY_POINT, [this]() -> bool {
277+
// 敵にボールを奪われた
278+
return not world_model()->isOurBallByBallOwnerCalculator();
279+
});
280+
230281
addStateFunction(
231282
AttackerState::STANDARD_PASS,
232283
[this]([[maybe_unused]] const ConsaiVisualizerWrapper::SharedPtr & visualizer) -> Status {
@@ -290,6 +341,11 @@ Attacker::Attacker(RobotCommandWrapperBase::SharedPtr & base)
290341
goal_angle_width * 180.0 / M_PI > 1.;
291342
});
292343

344+
addTransition(AttackerState::LOW_CHANCE_GOAL_KICK, AttackerState::ENTRY_POINT, [this]() -> bool {
345+
// 敵にボールを奪われた
346+
return not world_model()->isOurBallByBallOwnerCalculator();
347+
});
348+
293349
addStateFunction(
294350
AttackerState::LOW_CHANCE_GOAL_KICK,
295351
[this]([[maybe_unused]] const ConsaiVisualizerWrapper::SharedPtr & visualizer) -> Status {
@@ -305,6 +361,12 @@ Attacker::Attacker(RobotCommandWrapperBase::SharedPtr & base)
305361
x_diff_with_their_goal >= world_model()->field_size.x() * 0.5;
306362
});
307363

364+
addTransition(
365+
AttackerState::MOVE_BALL_TO_OPPONENT_HALF, AttackerState::ENTRY_POINT, [this]() -> bool {
366+
// 敵にボールを奪われた
367+
return not world_model()->isOurBallByBallOwnerCalculator();
368+
});
369+
308370
addStateFunction(
309371
AttackerState::MOVE_BALL_TO_OPPONENT_HALF,
310372
[this]([[maybe_unused]] const ConsaiVisualizerWrapper::SharedPtr & visualizer) -> Status {
@@ -325,6 +387,9 @@ Attacker::Attacker(RobotCommandWrapperBase::SharedPtr & base)
325387
// ボールが止まっている
326388
if (world_model()->ball.vel.norm() < 0.5) {
327389
return true;
390+
} else if (not world_model()->isOurBallByBallOwnerCalculator()) {
391+
// 敵にボールを奪われた
392+
return true;
328393
} else {
329394
return false;
330395
}

crane_robot_skills/src/steal_ball.cpp

Lines changed: 1 addition & 120 deletions
Original file line numberDiff line numberDiff line change
@@ -44,19 +44,6 @@ StealBall::StealBall(RobotCommandWrapperBase::SharedPtr & base)
4444
return skill_state == Status::SUCCESS;
4545
});
4646

47-
// 敵よりもボールに近い場合はパス
48-
addTransition(StealBallState::MOVE_TO_FRONT, StealBallState::PASS, [this]() {
49-
auto theirs = world_model()->theirs.getAvailableRobots();
50-
if (not theirs.empty()) {
51-
auto [their_attacker, their_distance] =
52-
world_model()->getNearestRobotWithDistanceFromPoint(world_model()->ball.pos, theirs);
53-
double our_distance = robot()->getDistance(world_model()->ball.pos);
54-
return our_distance < their_distance - 0.2;
55-
} else {
56-
return true;
57-
}
58-
});
59-
6047
addStateFunction(
6148
StealBallState::STEAL,
6249
[this]([[maybe_unused]] const ConsaiVisualizerWrapper::SharedPtr & visualizer) -> Status {
@@ -68,7 +55,7 @@ StealBall::StealBall(RobotCommandWrapperBase::SharedPtr & base)
6855
world_model()->ball.pos, getAngle(world_model()->ball.pos - robot()->pose.pos));
6956
command.dribble(0.5);
7057
} else if (method == "side") {
71-
if (robot()->getDistance(world_model()->ball.pos) < (0.085 + 0.000)) {
58+
if (robot()->getDistance(world_model()->ball.pos) < (0.085 - 0.030)) {
7259
// ロボット半径より近くに来れば急回転して刈り取れる
7360
command.setTargetTheta(getAngle(world_model()->ball.pos - robot()->pose.pos) + M_PI / 2);
7461
} else {
@@ -79,111 +66,5 @@ StealBall::StealBall(RobotCommandWrapperBase::SharedPtr & base)
7966
}
8067
return Status::RUNNING;
8168
});
82-
83-
// 敵よりもボールに近い場合はパス
84-
addTransition(StealBallState::STEAL, StealBallState::PASS, [this]() {
85-
auto theirs = world_model()->theirs.getAvailableRobots();
86-
if (not theirs.empty()) {
87-
auto [their_attacker, their_distance] =
88-
world_model()->getNearestRobotWithDistanceFromPoint(world_model()->ball.pos, theirs);
89-
double our_distance = robot()->getDistance(world_model()->ball.pos);
90-
return our_distance < their_distance - 0.2;
91-
} else {
92-
return true;
93-
}
94-
});
95-
96-
addStateFunction(
97-
StealBallState::PASS,
98-
[this]([[maybe_unused]] const ConsaiVisualizerWrapper::SharedPtr & visualizer) -> Status {
99-
if (attacker_skill == nullptr) {
100-
attacker_skill = std::make_shared<skills::SimpleAttacker>(command_base);
101-
}
102-
auto ours = world_model()->ours.getAvailableRobots(robot()->id);
103-
ours.erase(
104-
std::remove_if(
105-
ours.begin(), ours.end(),
106-
[this](auto e) {
107-
return e->getDistance(world_model()->getTheirGoalCenter()) >
108-
robot()->getDistance(world_model()->getTheirGoalCenter());
109-
}),
110-
ours.end());
111-
if (not ours.empty()) {
112-
auto [target_bot, distance] = world_model()->getNearestRobotWithDistanceFromPoint(
113-
world_model()->getTheirGoalCenter(), ours);
114-
attacker_skill->setParameter("receiver_id", target_bot->id);
115-
}
116-
return attacker_skill->run(visualizer);
117-
});
118-
119-
addTransition(StealBallState::PASS, StealBallState::MOVE_TO_FRONT, [this]() {
120-
auto theirs = world_model()->theirs.getAvailableRobots();
121-
if (theirs.empty()) {
122-
return false;
123-
} else {
124-
auto [their_attacker, their_distance] =
125-
world_model()->getNearestRobotWithDistanceFromPoint(world_model()->ball.pos, theirs);
126-
double our_distance = robot()->getDistance(world_model()->ball.pos);
127-
return our_distance > their_distance;
128-
}
129-
});
130-
131-
addTransition(StealBallState::PASS, StealBallState::INTERCEPT, [this]() {
132-
return world_model()->ball.vel.norm() > 0.5;
133-
});
134-
135-
addTransition(StealBallState::STEAL, StealBallState::INTERCEPT, [this]() {
136-
return world_model()->ball.vel.norm() > 0.5;
137-
});
138-
139-
addTransition(StealBallState::MOVE_TO_FRONT, StealBallState::INTERCEPT, [this]() {
140-
return world_model()->ball.vel.norm() > 0.5;
141-
});
142-
143-
addStateFunction(StealBallState::INTERCEPT, [this](const ConsaiVisualizerWrapper::SharedPtr &) {
144-
Point vel_seg = world_model()->ball.vel * 5.0;
145-
if (vel_seg.norm() < 1.0) {
146-
vel_seg = vel_seg.normalized() * 1.0;
147-
}
148-
Segment ball_line{world_model()->ball.pos, world_model()->ball.pos + vel_seg};
149-
150-
Point across_point = [&]() {
151-
const double OFFSET = 0.3;
152-
const double X = world_model()->field_size.x() / 2.0 - OFFSET;
153-
const double Y = world_model()->field_size.y() / 2.0 - OFFSET;
154-
155-
Segment seg1{Point(X, Y), Point(X, -Y)};
156-
Segment seg2{Point(-X, Y), Point(-X, -Y)};
157-
Segment seg3{Point(Y, X), Point(-Y, X)};
158-
Segment seg4{Point(Y, -X), Point(-Y, -X)};
159-
std::vector<Point> intersections;
160-
if (bg::intersection(ball_line, seg1, intersections); not intersections.empty()) {
161-
return intersections.front();
162-
} else if (bg::intersection(ball_line, seg2, intersections); not intersections.empty()) {
163-
return intersections.front();
164-
} else if (bg::intersection(ball_line, seg3, intersections); not intersections.empty()) {
165-
return intersections.front();
166-
} else if (bg::intersection(ball_line, seg4, intersections); not intersections.empty()) {
167-
return intersections.front();
168-
} else {
169-
return ball_line.second;
170-
}
171-
}();
172-
173-
// ゴールとボールの中間方向を向く
174-
auto [goal_angle, width] = world_model()->getLargestGoalAngleRangeFromPoint(across_point);
175-
auto to_goal = getNormVec(goal_angle);
176-
auto to_ball = (world_model()->ball.pos - across_point).normalized();
177-
double intermediate_angle = getAngle(2 * to_goal + to_ball);
178-
command.liftUpDribbler();
179-
command.kickStraight(getParameter<double>("kicker_power"));
180-
command.setDribblerTargetPosition(across_point, intermediate_angle);
181-
182-
return Status::RUNNING;
183-
});
184-
185-
addTransition(StealBallState::INTERCEPT, StealBallState::MOVE_TO_FRONT, [this]() {
186-
return world_model()->ball.vel.norm() < 0.3;
187-
});
18869
}
18970
} // namespace crane::skills

crane_sender/include/crane_sender/sender_base.hpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,12 @@ class SenderBase : public rclcpp::Node
2929
declare_parameter<double>("delay_s", 0.0);
3030
get_parameter("delay_s", delay_s);
3131

32+
declare_parameter<double>("kick_power_limit_straight", 1.0);
33+
get_parameter("kick_power_limit_straight", kick_power_limit_straight);
34+
35+
declare_parameter<double>("kick_power_limit_chip", 1.0);
36+
get_parameter("kick_power_limit_chip", kick_power_limit_chip);
37+
3238
declare_parameter<double>("latency_ms", 0.0);
3339
get_parameter("latency_ms", current_latency_ms);
3440

@@ -57,6 +63,10 @@ class SenderBase : public rclcpp::Node
5763

5864
double current_latency_ms = 0.0;
5965

66+
double kick_power_limit_straight;
67+
68+
double kick_power_limit_chip;
69+
6070
virtual void sendCommands(const crane_msgs::msg::RobotCommands & msg) = 0;
6171

6272
float normalizeAngle(float angle_rad) const

0 commit comments

Comments
 (0)