Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Split player and role numbers #1021

Closed
wants to merge 7 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 21 additions & 26 deletions crates/argument_parsers/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ use color_eyre::{
use regex::Regex;

use nao::{Network, SystemctlAction};
use spl_network_messages::PlayerNumber;
use spl_network_messages::bindings::MAX_NUM_PLAYERS;

pub const SYSTEMCTL_ACTION_POSSIBLE_VALUES: &[&str] =
&["disable", "enable", "restart", "start", "status", "stop"];
Expand Down Expand Up @@ -151,61 +151,56 @@ impl TryFrom<NaoAddress> for NaoNumber {
#[derive(Clone, Copy, Debug)]
pub struct NaoAddressPlayerAssignment {
pub nao_address: NaoAddress,
pub player_number: PlayerNumber,
pub jersey_number: u8,
}

impl FromStr for NaoAddressPlayerAssignment {
type Err = Report;

fn from_str(input: &str) -> Result<Self> {
let (prefix, player_number) = parse_assignment(input)?;
let (prefix, jersey_number) = parse_assignment(input)?;
Ok(Self {
nao_address: prefix.parse()?,
player_number,
jersey_number,
})
}
}

#[derive(Clone, Copy, Debug)]
pub struct NaoNumberPlayerAssignment {
pub struct NaoNumberJerseyAssignment {
pub nao_number: NaoNumber,
pub player_number: PlayerNumber,
pub jersey_number: u8,
}

impl FromStr for NaoNumberPlayerAssignment {
impl FromStr for NaoNumberJerseyAssignment {
type Err = Report;

fn from_str(input: &str) -> Result<Self> {
let (prefix, player_number) = parse_assignment(input)?;
let (prefix, jersey_number) = parse_assignment(input)?;
Ok(Self {
nao_number: prefix.parse()?,
player_number,
jersey_number,
})
}
}

impl Display for NaoNumberPlayerAssignment {
impl Display for NaoNumberJerseyAssignment {
fn fmt(&self, formatter: &mut Formatter<'_>) -> fmt::Result {
write!(formatter, "{}:{}", self.nao_number, self.player_number)
write!(formatter, "{}:{}", self.nao_number, self.jersey_number)
}
}

fn parse_assignment(input: &str) -> Result<(&str, PlayerNumber)> {
let (prefix, player_number) = input.rsplit_once(':').ok_or_else(|| eyre!("missing `:`"))?;
let player_number = match player_number {
"1" => PlayerNumber::One,
"2" => PlayerNumber::Two,
"3" => PlayerNumber::Three,
"4" => PlayerNumber::Four,
"5" => PlayerNumber::Five,
"6" => PlayerNumber::Six,
"7" => PlayerNumber::Seven,
_ => bail!("unexpected player number {player_number}"),
};
Ok((prefix, player_number))
fn parse_assignment(input: &str) -> Result<(&str, u8)> {
let (prefix, jersey_number) = input.rsplit_once(':').ok_or_else(|| eyre!("missing `:`"))?;
let jersey_number = jersey_number.parse()?;
if !(1..=MAX_NUM_PLAYERS).contains(&jersey_number) {
bail!("Unexpected jersey number {jersey_number}")
}

Ok((prefix, jersey_number))
}

impl TryFrom<NaoAddressPlayerAssignment> for NaoNumberPlayerAssignment {
impl TryFrom<NaoAddressPlayerAssignment> for NaoNumberJerseyAssignment {
type Error = Report;

fn try_from(assignment: NaoAddressPlayerAssignment) -> Result<Self> {
Expand All @@ -214,7 +209,7 @@ impl TryFrom<NaoAddressPlayerAssignment> for NaoNumberPlayerAssignment {
.nao_address
.try_into()
.wrap_err("failed to convert NAO address into NAO number")?,
player_number: assignment.player_number,
jersey_number: assignment.jersey_number,
})
}
}
100 changes: 100 additions & 0 deletions crates/control/src/active_player_filter.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
use color_eyre::Result;
use context_attribute::context;
use framework::MainOutput;
use itertools::Itertools;
use serde::{Deserialize, Serialize};
use types::filtered_game_controller_state::FilteredGameControllerState;

#[derive(Deserialize, Serialize)]
pub struct ActivePlayerFilter {}

#[context]
pub struct CreationContext {}

#[context]
pub struct CycleContext {
filtered_game_controller_state:
Input<Option<FilteredGameControllerState>, "filtered_game_controller_state?">,

jersey_number: Parameter<usize, "jersey_number">,
}

#[context]
#[derive(Default)]
pub struct MainOutputs {
pub walk_in_position_index: MainOutput<usize>,
pub replacement_keeper_priority: MainOutput<Option<usize>>,
pub striker_priority: MainOutput<Option<usize>>,
}

impl ActivePlayerFilter {
pub fn new(_context: CreationContext) -> Result<Self> {
Ok(Self {})
}

pub fn cycle(&mut self, context: CycleContext) -> Result<MainOutputs> {
let penalties = context
.filtered_game_controller_state
.map(|game_controller_state| &game_controller_state.penalties);
let mut walk_in_position_index = if let Some(list) = penalties {
list.keys()
.sorted()
.position(|&key| key == *context.jersey_number)
} else {
None
}
.unwrap_or(7);

let goalkeeper_jersey_number = context
.filtered_game_controller_state
.map(|game_controller_state| game_controller_state.goal_keeper_number);
if let Some(goalkeeper_number) = goalkeeper_jersey_number {
if goalkeeper_number == *context.jersey_number {
walk_in_position_index = 0;
} else if goalkeeper_number > *context.jersey_number {
walk_in_position_index += 1;
}
}

let available_field_players = if let Some(game_controller_state) =
context.filtered_game_controller_state
{
game_controller_state
.penalties
.iter()
.filter(|(&jersey_number, penalty)| {
penalty.is_none() && jersey_number != game_controller_state.goal_keeper_number
})
.map(|(&jersey_number, _)| jersey_number)
.sorted()
.collect::<Vec<_>>()
} else {
Vec::new()
};
let mut replacement_keeper_priority = available_field_players
.iter()
.position(|&jersey_number| jersey_number == *context.jersey_number);
if let (Some(game_controller_state), Some(keeper_priority)) = (
context.filtered_game_controller_state,
replacement_keeper_priority,
) {
match game_controller_state
.penalties
.get(&game_controller_state.goal_keeper_number)
{
Some(_penalty) => {}
None => replacement_keeper_priority = Some(keeper_priority + 1),
}
}
let striker_priority = available_field_players
.iter()
.rev()
.position(|&jersey_number| jersey_number == *context.jersey_number);

Ok(MainOutputs {
walk_in_position_index: walk_in_position_index.into(),
replacement_keeper_priority: replacement_keeper_priority.into(),
striker_priority: striker_priority.into(),
})
}
}
7 changes: 3 additions & 4 deletions crates/control/src/behavior/initial.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
use coordinate_systems::Field;
use linear_algebra::Point2;
use spl_network_messages::PlayerNumber;
use types::{
camera_position::CameraPosition,
filtered_game_state::FilteredGameState,
Expand Down Expand Up @@ -57,11 +56,11 @@ fn look_at_referee(
};

match (
world_state.robot.player_number,
world_state.walk_in_position_index,
filtered_game_controller_state.own_team_is_home_after_coin_toss,
) {
(PlayerNumber::Four | PlayerNumber::Seven, true) => {}
(PlayerNumber::Two | PlayerNumber::Six, false) => {}
(3 | 5, true) => {}
(4 | 6, false) => {}
_ => return None,
}

Expand Down
8 changes: 4 additions & 4 deletions crates/control/src/behavior/node.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use context_attribute::context;
use coordinate_systems::Field;
use framework::{AdditionalOutput, MainOutput};
use linear_algebra::{point, Point2};
use spl_network_messages::{GamePhase, PlayerNumber, SubState, Team};
use spl_network_messages::{GamePhase, SubState, Team};
use types::{
action::Action,
cycle_time::CycleTime,
Expand Down Expand Up @@ -62,7 +62,7 @@ pub struct CycleContext {
world_state: Input<WorldState, "world_state">,
cycle_time: Input<CycleTime, "cycle_time">,
is_localization_converged: Input<bool, "is_localization_converged">,

//todo! filtered_game_controller_state
parameters: Parameter<BehaviorParameters, "behavior">,
in_walk_kicks: Parameter<InWalkKicksParameters, "in_walk_kicks">,
field_dimensions: Parameter<FieldDimensions, "field_dimensions">,
Expand Down Expand Up @@ -158,8 +158,8 @@ impl Behavior {
}
}

if matches!(world_state.robot.player_number, PlayerNumber::One)
&& matches!(world_state.robot.role, Role::Keeper)
if matches!(world_state.robot.jersey_number, 1)
//#todo! context.filtered_game_controller_state.goalkeeper_jersey_number
{
actions.push(Action::WideStance);
}
Expand Down
4 changes: 2 additions & 2 deletions crates/control/src/behavior/search.rs
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,7 @@ fn assign_search_role(world_state: &WorldState) -> Option<SearchRole> {
let penalties = world_state
.filtered_game_controller_state
.as_ref()
.map(|state| state.penalties)?;
.map(|state| state.penalties.clone())?;
let available_players = penalties
.iter()
.filter_map(|(number, penalty)| match penalty {
Expand All @@ -160,7 +160,7 @@ fn assign_search_role(world_state: &WorldState) -> Option<SearchRole> {
available_players
.zip(search_roles)
.find_map(|(number, position)| {
let is_my_player_number = number == world_state.robot.player_number;
let is_my_player_number = *number == world_state.robot.jersey_number;
is_my_player_number.then_some(position)
})
}
88 changes: 39 additions & 49 deletions crates/control/src/filtered_game_controller_state_timer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,9 @@ use color_eyre::Result;
use context_attribute::context;
use framework::MainOutput;
use serde::{Deserialize, Serialize};
use spl_network_messages::Penalty;
use types::{
cycle_time::CycleTime, filtered_game_controller_state::FilteredGameControllerState,
last_filtered_game_controller_state_change::LastFilteredGameControllerStateChanges,
players::Players,
};

#[derive(Deserialize, Serialize)]
Expand Down Expand Up @@ -82,58 +80,50 @@ impl FilteredGameControllerStateTimer {
&mut self.filtered_game_controller_state_changes.kicking_team,
cycle_start_time,
);

if context.filtered_game_controller_state.penalties
!= self.last_filtered_game_controller_state.penalties
{
fn update_player_penalty(
new_penalty: Option<Penalty>,
current_penalty: Option<SystemTime>,
cycle_start_time: SystemTime,
) -> Option<SystemTime> {
if new_penalty.is_some() {
Some(cycle_start_time)
} else {
current_penalty
for (jersey_number, penalty) in &context.filtered_game_controller_state.penalties {
match (
penalty,
self.filtered_game_controller_state_changes
.penalties
.contains_key(jersey_number),
) {
(None, false) => {
self.filtered_game_controller_state_changes
.penalties
.insert(*jersey_number, None);
}
(Some(_), _) => {
self.filtered_game_controller_state_changes
.penalties
.insert(*jersey_number, Some(cycle_start_time));
}
_ => (),
}
}
self.filtered_game_controller_state_changes.penalties = Players {
one: update_player_penalty(
context.filtered_game_controller_state.penalties.one,
self.filtered_game_controller_state_changes.penalties.one,
cycle_start_time,
),
two: update_player_penalty(
context.filtered_game_controller_state.penalties.two,
self.filtered_game_controller_state_changes.penalties.two,
cycle_start_time,
),
three: update_player_penalty(
context.filtered_game_controller_state.penalties.three,
self.filtered_game_controller_state_changes.penalties.three,
cycle_start_time,
),
four: update_player_penalty(
context.filtered_game_controller_state.penalties.four,
self.filtered_game_controller_state_changes.penalties.four,
cycle_start_time,
),
five: update_player_penalty(
context.filtered_game_controller_state.penalties.five,
self.filtered_game_controller_state_changes.penalties.five,
cycle_start_time,
),
six: update_player_penalty(
context.filtered_game_controller_state.penalties.six,
self.filtered_game_controller_state_changes.penalties.six,
cycle_start_time,
),
seven: update_player_penalty(
context.filtered_game_controller_state.penalties.seven,
self.filtered_game_controller_state_changes.penalties.seven,
cycle_start_time,
),
};
let players_to_remove: Vec<usize> = self
.filtered_game_controller_state_changes
.penalties
.keys()
.filter(|&&player_number| {
!&context
.filtered_game_controller_state
.penalties
.contains_key(&player_number)
})
.cloned()
.collect();

for player_number in players_to_remove {
self.last_filtered_game_controller_state
.penalties
.remove(&player_number);
}
}

if context.filtered_game_controller_state.sub_state
!= self.last_filtered_game_controller_state.sub_state
{
Expand All @@ -144,7 +134,7 @@ impl FilteredGameControllerStateTimer {

Ok(MainOutputs {
last_filtered_game_controller_state_changes: Some(
self.filtered_game_controller_state_changes,
self.filtered_game_controller_state_changes.clone(),
)
.into(),
})
Expand Down
Loading
Loading