Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/develop' into feature/aggressive…
Browse files Browse the repository at this point in the history
…_goalie
  • Loading branch information
HansRobo committed Feb 22, 2024
2 parents fde7ad8 + 14bc3fc commit a31d073
Show file tree
Hide file tree
Showing 13 changed files with 359 additions and 7 deletions.
7 changes: 5 additions & 2 deletions crane_bringup/launch/play_switcher.launch.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
<arg name="vision_port" default="10006" description="Set multicast port to connect SSL-Vision."/>
<arg name="referee_addr" default="224.5.23.1" description="Set multicast address to connect Game Controller."/>
<arg name="referee_port" default="11003" description="Set multicast port to connect Game Controller."/>
<arg name="team" default="ibis" description="team name"/>

<!-- Nodes -->
<node pkg="crane_session_controller" exec="crane_session_controller_node" output="screen">
Expand Down Expand Up @@ -37,11 +38,13 @@

<node pkg="crane_world_model_publisher" exec="crane_world_model_publisher_node">
<param name="initial_team_color" value="YELLOW"/>
<param name="team_name" value="ibis"/>
<param name="team_name" value="$(var team)"/>
<!-- <on_exit type="shutdown" reason="normal"/>-->
</node>

<node pkg="crane_play_switcher" exec="play_switcher_node" output="screen"/>
<node pkg="crane_play_switcher" exec="play_switcher_node" output="screen">
<param name="team_name" value="$(var team)"/>
</node>

<node pkg="consai_visualizer" exec="consai_visualizer"/>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#include <crane_msgs/msg/world_model.hpp>
#include <rclcpp/rclcpp.hpp>
#include <robocup_ssl_msgs/msg/referee.hpp>
#include <string>

#include "visibility_control.h"

Expand Down Expand Up @@ -90,6 +91,8 @@ class PlaySwitcher : public rclcpp::Node

BallAnalyzer ball_analyzer;

std::string team_name = "ibis";

struct LastCommandChangedState
{
rclcpp::Time stamp;
Expand Down
13 changes: 9 additions & 4 deletions crane_play_switcher/src/play_switcher.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@ PlaySwitcher::PlaySwitcher(const rclcpp::NodeOptions & options)

play_situation_pub = create_publisher<crane_msgs::msg::PlaySituation>("/play_situation", 10);

declare_parameter<std::string>("team_name", "ibis");
team_name = get_parameter("team_name").as_string();

decoded_referee_sub = create_subscription<robocup_ssl_msgs::msg::Referee>(
"/referee", 10, [this](const robocup_ssl_msgs::msg::Referee & msg) { referee_callback(msg); });

Expand Down Expand Up @@ -97,7 +100,7 @@ void PlaySwitcher::referee_callback(const robocup_ssl_msgs::msg::Referee & msg)
//-----------------------------------//
// raw command -> crane command
std::map<int, int> command_map;
bool is_yellow = msg.yellow.name == "ibis";
bool is_yellow = msg.yellow.name == team_name;

command_map[Referee::COMMAND_HALT] = PlaySituation::HALT;
command_map[Referee::COMMAND_STOP] = PlaySituation::STOP;
Expand Down Expand Up @@ -125,11 +128,13 @@ void PlaySwitcher::referee_callback(const robocup_ssl_msgs::msg::Referee & msg)
play_situation_msg.command == PlaySituation::THEIR_KICKOFF_START or
play_situation_msg.command == PlaySituation::THEIR_DIRECT_FREE or
play_situation_msg.command == PlaySituation::THEIR_INDIRECT_FREE or
play_situation_msg.command == PlaySituation::THEIR_PENALTY_START or
// 敵PKのINPLAYはOUR_PENALTY_STARTとして実装しているのでINPLAY遷移はしない
// play_situation_msg.command == PlaySituation::THEIR_PENALTY_START or
play_situation_msg.command == PlaySituation::OUR_KICKOFF_START or
play_situation_msg.command == PlaySituation::OUR_DIRECT_FREE or
play_situation_msg.command == PlaySituation::OUR_INDIRECT_FREE or
play_situation_msg.command == PlaySituation::OUR_PENALTY_START) {
// 味方PKのINPLAYはOUR_PENALTY_STARTとして実装しているのでINPLAY遷移はしない
// play_situation_msg.command == PlaySituation::OUR_PENALTY_START or
play_situation_msg.command == PlaySituation::OUR_INDIRECT_FREE) {
if (0.05 <= (last_command_changed_state.ball_position - world_model->ball.pos).norm()) {
next_play_situation = PlaySituation::INPLAY;
inplay_command_info.reason =
Expand Down
130 changes: 130 additions & 0 deletions crane_robot_skills/include/crane_robot_skills/penalty_kick.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
// Copyright (c) 2024 ibis-ssl
//
// Use of this source code is governed by an MIT-style
// license that can be found in the LICENSE file or at
// https://opensource.org/licenses/MIT.

#ifndef CRANE_ROBOT_SKILLS__PENALTY_KICK_HPP_
#define CRANE_ROBOT_SKILLS__PENALTY_KICK_HPP_

#include <crane_geometry/eigen_adapter.hpp>
#include <crane_geometry/interval.hpp>
#include <crane_robot_skills/skill_base.hpp>
#include <memory>
#include <utility>

namespace crane::skills
{
enum class PenaltyKickState {
PREPARE,
KICK,
DONE,
};

class PenaltyKick : public SkillBase<PenaltyKickState>
{
private:
std::optional<Point> start_ball_point = std::nullopt;

public:
explicit PenaltyKick(uint8_t id, const std::shared_ptr<WorldModelWrapper> & wm)
: SkillBase<PenaltyKickState>("PenaltyKick", id, wm, PenaltyKickState::PREPARE)
{
setParameter("start_from_kick", false);
setParameter("prepare_margin", 0.6);
addStateFunction(
PenaltyKickState::PREPARE, [this](ConsaiVisualizerWrapper::SharedPtr visualizer) -> Status {
Point target = world_model->ball.pos;
auto margin = getParameter<double>("prepare_margin");
target.x() += world_model->getOurGoalCenter().x() > 0 ? margin : -margin;
command->setTargetPosition(target);
command->lookAtBall();
return Status::RUNNING;
});

addTransition(PenaltyKickState::PREPARE, PenaltyKickState::KICK, [this]() {
if (getParameter<bool>("start_from_kick")) {
return true;
} else {
return world_model->play_situation.getSituationCommandID() ==
crane_msgs::msg::PlaySituation::OUR_PENALTY_START;
}
});
addStateFunction(
PenaltyKickState::KICK, [this](ConsaiVisualizerWrapper::SharedPtr visualizer) -> Status {
if (not start_ball_point) {
start_ball_point = world_model->ball.pos;
}

auto [best_target, goal_angle_width] = getBestShootTargetWithWidth();

// 経由ポイント
Point intermediate_point =
world_model->ball.pos + (world_model->ball.pos - best_target).normalized() * 0.2;

double dot = (robot->pose.pos - world_model->ball.pos)
.normalized()
.dot((world_model->ball.pos - best_target).normalized());
double target_theta = getAngle(best_target - world_model->ball.pos);
// ボールと敵ゴールの延長線上にいない && 角度があってないときは,中間ポイントを経由
if (dot < 0.95 || std::abs(getAngleDiff(target_theta, robot->pose.theta)) > 0.05) {
command->setTargetPosition(intermediate_point);
command->enableCollisionAvoidance();
} else {
command->setTargetPosition(world_model->ball.pos);
command->kickStraight(0.7).disableCollisionAvoidance();
command->enableCollisionAvoidance();
command->disableBallAvoidance();
}

command->setTargetTheta(getAngle(best_target - world_model->ball.pos));
return Status::RUNNING;
});

addTransition(PenaltyKickState::KICK, PenaltyKickState::DONE, [this]() {
return world_model->isDefenseArea(world_model->ball.pos);
});

addStateFunction(
PenaltyKickState::DONE, [this](ConsaiVisualizerWrapper::SharedPtr visualizer) -> Status {
command->stopHere();
return Status::RUNNING;
});
}

// SimpleAttackerからコピー
auto getBestShootTargetWithWidth() -> std::pair<Point, double>
{
const auto & ball = world_model->ball.pos;

Interval goal_range;

auto goal_posts = world_model->getTheirGoalPosts();
goal_range.append(getAngle(goal_posts.first - ball), getAngle(goal_posts.second - ball));

for (auto & enemy : world_model->theirs.getAvailableRobots()) {
double distance = enemy->getDistance(ball);
constexpr double MACHINE_RADIUS = 0.1;

double center_angle = getAngle(enemy->pose.pos - ball);
double diff_angle =
atan(MACHINE_RADIUS / std::sqrt(distance * distance - MACHINE_RADIUS * MACHINE_RADIUS));

goal_range.erase(center_angle - diff_angle, center_angle + diff_angle);
}

auto largest_interval = goal_range.getLargestInterval();

double target_angle = (largest_interval.first + largest_interval.second) / 2.0;

return {
ball + getNormVec(target_angle) * 0.5, largest_interval.second - largest_interval.first};
}

void print(std::ostream & os) const override
{
os << "[Idle] stop_by_position: " << getParameter<bool>("stop_by_position") ? "true" : "false";
}
};
} // namespace crane::skills
#endif // CRANE_ROBOT_SKILLS__PENALTY_KICK_HPP_
Original file line number Diff line number Diff line change
Expand Up @@ -192,7 +192,7 @@ class SkillBase : public SkillInterface

crane_msgs::msg::RobotCommand getRobotCommand() override { return command->getMsg(); }

// std::shared_ptr<RobotCommandWrapper> commander() const { return command; }
std::shared_ptr<RobotCommandWrapper> commander() const { return command; }

void addStateFunction(const StatesType & state, StateFunctionType function)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ extern "C" {
#include <chrono>
#include <cmath>
#include <crane_msgs/msg/ball_info.hpp>
#include <crane_msgs/msg/play_situation.hpp>
#include <crane_msgs/msg/robot_info.hpp>
#include <crane_msgs/msg/world_model.hpp>
#include <functional>
Expand Down Expand Up @@ -114,6 +115,10 @@ class WorldModelPublisherComponent : public rclcpp::Node

rclcpp::Subscription<robocup_ssl_msgs::msg::Referee>::SharedPtr sub_referee;

rclcpp::Subscription<crane_msgs::msg::PlaySituation>::SharedPtr sub_play_situation;

crane_msgs::msg::PlaySituation latest_play_situation;

rclcpp::Publisher<crane_msgs::msg::WorldModel>::SharedPtr pub_world_model;

rclcpp::TimerBase::SharedPtr timer;
Expand Down
7 changes: 7 additions & 0 deletions crane_world_model_publisher/src/world_model_publisher.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,10 @@ WorldModelPublisherComponent::WorldModelPublisherComponent(const rclcpp::NodeOpt
visionGeometryCallback(msg);
});

sub_play_situation = create_subscription<crane_msgs::msg::PlaySituation>(
"/play_situation", 1,
[this](const crane_msgs::msg::PlaySituation::SharedPtr msg) { latest_play_situation = *msg; });

pub_world_model = create_publisher<crane_msgs::msg::WorldModel>("/world_model", 1);

using std::chrono::operator""ms;
Expand Down Expand Up @@ -70,6 +74,7 @@ WorldModelPublisherComponent::WorldModelPublisherComponent(const rclcpp::NodeOpt
their_color = Color::BLUE;
}
}

void WorldModelPublisherComponent::visionDetectionsCallback(
const robocup_ssl_msgs::msg::TrackedFrame::SharedPtr msg)
{
Expand Down Expand Up @@ -196,6 +201,8 @@ void WorldModelPublisherComponent::publishWorldModel()
wm.our_goalie_id = our_goalie_id;
wm.their_goalie_id = their_goalie_id;

wm.play_situation = latest_play_situation;

pub_world_model->publish(wm);
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
// Copyright (c) 2024 ibis-ssl
//
// Use of this source code is governed by an MIT-style
// license that can be found in the LICENSE file or at
// https://opensource.org/licenses/MIT.

#ifndef CRANE_PLANNER_PLUGINS__OUR_PENALTY_KICK_PLANNER_HPP_
#define CRANE_PLANNER_PLUGINS__OUR_PENALTY_KICK_PLANNER_HPP_

#include <crane_geometry/boost_geometry.hpp>
#include <crane_msg_wrappers/world_model_wrapper.hpp>
#include <crane_msgs/srv/robot_select.hpp>
#include <crane_planner_base/planner_base.hpp>
#include <crane_robot_skills/penalty_kick.hpp>
#include <functional>
#include <memory>
#include <rclcpp/rclcpp.hpp>
#include <utility>
#include <vector>

#include "visibility_control.h"

namespace crane
{
class OurPenaltyKickPlanner : public PlannerBase
{
private:
std::shared_ptr<skills::PenaltyKick> kicker = nullptr;

std::vector<std::shared_ptr<RobotCommandWrapper>> other_robots;

public:
COMPOSITION_PUBLIC
explicit OurPenaltyKickPlanner(
WorldModelWrapper::SharedPtr & world_model, ConsaiVisualizerWrapper::SharedPtr visualizer)
: PlannerBase("OurPenaltyKickPlanner", world_model, visualizer)
{
}

std::pair<Status, std::vector<crane_msgs::msg::RobotCommand>> calculateRobotCommand(
const std::vector<RobotIdentifier> & robots) override
{
std::vector<crane_msgs::msg::RobotCommand> robot_commands;

for (auto & robot_command : other_robots) {
// 関係ないロボットはボールより1m以上下がる(ルール5.3.5.3)
Point target{};
target << (world_model->getOurGoalCenter().x() + world_model->ball.pos.x()) / 2,
robot_command->robot->pose.pos.y();
robot_command->setTargetPosition(target);
robot_command->setMaxVelocity(0.5);
robot_commands.push_back(robot_command->getMsg());
}
if (kicker) {
auto status = kicker->run(visualizer);
robot_commands.emplace_back(kicker->getRobotCommand());
if (status == skills::Status::SUCCESS) {
return {PlannerBase::Status::SUCCESS, robot_commands};
}
}
return {PlannerBase::Status::RUNNING, robot_commands};
}

auto getSelectedRobots(
uint8_t selectable_robots_num, const std::vector<uint8_t> & selectable_robots)
-> std::vector<uint8_t> override
{
auto robots_sorted = this->getSelectedRobotsByScore(
selectable_robots_num, selectable_robots, [&](const std::shared_ptr<RobotInfo> & robot) {
// ボールに近いほうが先頭
return 100. / robot->getDistance(world_model->ball.pos);
});
if (robots_sorted.size() > 0) {
// 一番ボールに近いロボットがキッカー
kicker = std::make_shared<skills::PenaltyKick>(robots_sorted.front(), world_model);
}
if (robots_sorted.size() > 1) {
for (auto it = robots_sorted.begin() + 1; it != robots_sorted.end(); it++) {
other_robots.emplace_back(std::make_shared<RobotCommandWrapper>(*it, world_model));
}
}
return robots_sorted;
}
};
} // namespace crane
#endif // CRANE_PLANNER_PLUGINS__OUR_PENALTY_KICK_PLANNER_HPP_
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,11 @@
#include "formation_planner.hpp"
#include "marker_planner.hpp"
#include "our_kickoff_planner.hpp"
#include "our_penalty_kick_planner.hpp"
#include "receive_planner.hpp"
#include "skill_planner.hpp"
#include "temporary/ball_placement_planner.hpp"
#include "their_penalty_kick_planner.hpp"
#include "tigers_goalie_planner.hpp"
#include "waiter_planner.hpp"

Expand Down Expand Up @@ -49,6 +51,10 @@ auto generatePlanner(const std::string & planner_name, Ts... ts) -> PlannerBase:
return std::make_unique<WaiterPlanner>(ts...);
} else if (planner_name == "our_kickoff") {
return std::make_unique<OurKickOffPlanner>(ts...);
} else if (planner_name == "our_penalty_kick") {
return std::make_unique<OurPenaltyKickPlanner>(ts...);
} else if (planner_name == "their_penalty_kick") {
return std::make_unique<TheirPenaltyKickPlanner>(ts...);
} else {
throw std::runtime_error("Unknown planner name: " + planner_name);
}
Expand Down
Loading

0 comments on commit a31d073

Please sign in to comment.