Skip to content
Draft
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
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,12 @@ def get_seconds_since_unpenalized(self) -> float:

def get_is_penalized(self) -> bool:
return self.gamestate.penalized

def get_penalized_team_mates(self) -> int:
return self.gamestate.team_mates_with_penalty

def get_penalized_rivals(self) -> int:
return self.gamestate.rivals_with_penalty

def received_gamestate(self) -> bool:
return self.last_update != 0.0
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
from bitbots_blackboard.body_blackboard import BodyBlackboard
from dynamic_stack_decider.abstract_decision_element import AbstractDecisionElement
from game_controller_hsl_interfaces.msg import GameState


class NumberPenalizedTeamMates(AbstractDecisionElement):
blackboard: BodyBlackboard

def __init__(self, blackboard, dsd, parameters):
super().__init__(blackboard, dsd, parameters)

def perform(self, reevaluate=False):
"""
Return number of penalized team mates
:param reevaluate:
:return:
"""
game_state_penalized_team_mates = self.blackboard.gamestate.get_penalized_team_mates()

if game_state_penalized_team_mates == 4:
return "FOUR"
elif game_state_penalized_team_mates == 3:
return "THREE"
elif game_state_penalized_team_mates == 2:
return "TWO"
elif game_state_penalized_team_mates == 1:
return "ONE"
else:
return "ZERO"

def get_reevaluate(self):
"""
Game state can change during the game
"""
return True

class NumberPenalizedRivals(AbstractDecisionElement):
blackboard: BodyBlackboard

def __init__(self, blackboard, dsd, parameters):
super().__init__(blackboard, dsd, parameters)

def perform(self, reevaluate=False):
"""
Return number of penalized rivals
:param reevaluate:
:return:
"""
game_state_penalized_rivals = self.blackboard.gamestate.get_penalized_rivals()

if game_state_penalized_rivals == 4:
return "FOUR"
elif game_state_penalized_rivals == 3:
return "THREE"
elif game_state_penalized_rivals == 2:
return "TWO"
elif game_state_penalized_rivals == 1:
return "ONE"
else:
return "ZERO"

def get_reevaluate(self):
"""
Game state can change during the game
"""
return True
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,27 @@ $DoOnce
SECOND --> @ChangeAction + action:positioning, @LookAtFieldFeatures, @AvoidBallActive, @GoToDefensePosition + mode:freekick_second
THIRD --> @ChangeAction + action:positioning, @LookAtFieldFeatures, @AvoidBallActive, @GoToDefensePosition

#PlacingWithoutTeamCom
$DoOnce
NOT_DONE --> @ForgetBall, @LookAtFieldFeatures
DONE --> $ConfigRole
GOALIE --> @ChangeAction + action:positioning, @LookAtFieldFeatures, @GoToBlockPosition
ELSE --> $BallSeen
NO --> $SecondaryStateTeamDecider
OUR --> #SearchBall
OTHER --> @AvoidBallActive, @LookAtFieldFeatures, @WalkInPlace + duration:2, @GoToRelativePosition + x:1 + y:0 + t:0, @Stand
//TODO
YES --> $NumberPenalizedTeamMates
ZERO
ONE
TWO
THREE
FOUR
YES --> $RankToBallNoGoalieWithoutTeamCom
FIRST --> @ChangeAction + action:positioning, @LookAtFieldFeatures, @AvoidBallActive, @GoToDefensePosition + mode:freekick_first
SECOND --> @ChangeAction + action:positioning, @LookAtFieldFeatures, @AvoidBallActive, @GoToDefensePosition + mode:freekick_second
THIRD --> @ChangeAction + action:positioning, @LookAtFieldFeatures, @AvoidBallActive, @GoToDefensePosition

#Init
@Stand + duration:0.1 + r:false, @ChangeAction + action:waiting, @LookForward, @Stand

Expand All @@ -130,15 +151,43 @@ $BallSeen
SECOND --> #SupporterRole
THIRD --> #DefensePositioning

#NormalBehaviorWithoutTeamCom
$BallSeen
NO --> $ConfigRole
GOALIE --> #RolePositionWithPause
ELSE --> #SearchBall
YES --> $KickOffTimeUp
NO_NORMAL --> #StandAndLook
NO_FREEKICK --> #PlacingWithoutTeamCom
YES --> $ConfigRole
GOALIE --> #GoalieBehavior
ELSE --> $CountActiveRobotsWithoutGoalie
ONE --> $RankToBallNoGoalie
FIRST --> #StrikerRole
SECOND --> #DefensePositioning
ELSE --> $RankToBallNoGoalie
FIRST --> #StrikerRole
SECOND --> #SupporterRole
THIRD --> #DefensePositioning

#PlayingBehavior
$SecondaryStateDecider
PENALTYSHOOT --> #PenaltyShootoutBehavior
TIMEOUT --> #StandAndLook
ELSE --> $SecondaryStateTeamDecider
OUR --> #NormalBehavior
OTHER --> #Placing
NORMAL --> #NormalBehavior
OVERTIME --> #NormalBehavior
$TeamComLimitReached
YES --> $SecondaryStateDecider
PENALTYSHOOT --> #PenaltyShootoutBehavior
TIMEOUT --> #StandAndLook
ELSE --> $SecondaryStateTeamDecider
OUR --> #NormalBehaviorWithoutTeamCom
OTHER --> #PlacingWithoutTeamCom
NORMAL --> #NormalBehaviorWithoutTeamCom
OVERTIME --> #NormalBehaviorWithoutTeamCom
NO --> $SecondaryStateDecider
PENALTYSHOOT --> #PenaltyShootoutBehavior
TIMEOUT --> #StandAndLook
ELSE --> $SecondaryStateTeamDecider
OUR --> #NormalBehavior
OTHER --> #Placing
NORMAL --> #NormalBehavior
OVERTIME --> #NormalBehavior

-->BodyBehavior
$IsPenalized
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,10 @@ def __init__(self):
self.socket_communication = SocketCommunication(self.node, self.logger, self.team_id, self.player_id)

self.rate: int = self.node.get_parameter("rate").value
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add a parameter reduced_rate and use that instead of hardcoded 1

self.reduced_rate: int = self.node.get_parameter("reduced_rate").value
self.lifetime: int = self.node.get_parameter("lifetime").value
self.avg_walking_speed: float = self.node.get_parameter("avg_walking_speed").value
self.rate_is_reduced: bool = False

self.topics = get_parameter_dict(self.node, "topics")
self.map_frame: str = self.node.get_parameter("map_frame").value
Expand All @@ -66,7 +68,7 @@ def __init__(self):
self.run_spin_in_thread()
self.try_to_establish_connection()

self.node.create_timer(1 / self.rate, self.send_message, callback_group=MutuallyExclusiveCallbackGroup())
self.create_timer(self.rate)
self.receive_forever()

def spin(self):
Expand Down Expand Up @@ -263,6 +265,11 @@ def handle_message(self, string_message: bytes):
self.team_data_publisher.publish(team_data)

def send_message(self):

if not self.rate_is_reduced:
if self.gamestate is not None and self.gamestate.secs_remaining > 180 and (self.gamestate.message_budget / self.gamestate.secs_remaining) < 11.2:
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please move this logic to a method should_reduce_rate(self, ...) -> bool

Please add some reasoning for the magic values.

self.reduce_rate()

if not self.is_robot_allowed_to_send_message():
self.logger.debug("Robot is not allowed to send message")
return
Expand Down Expand Up @@ -301,7 +308,15 @@ def should_message_be_discarded(self, message: Proto.Message) -> bool:
return is_own_message or is_message_from_oposite_team

def is_robot_allowed_to_send_message(self) -> bool:
return self.gamestate is not None and not self.gamestate.penalized
#a penalized robot doesn't need to publish
if self.gamestate is not None and not self.gamestate.penalized:
return False
#if we are close to our message budget, we dont want to continue publishing
#the budget smaller 40 as stop definition makes sure we have 10 msg per robot left in case of some delay in the communication with the game controller
if self.gamestate is not None and (self.gamestate.message_budget < 40):
return False

return True

def get_current_time(self) -> Time:
return self.node.get_clock().now()
Expand All @@ -313,7 +328,29 @@ def extract_orientation_yaw_angle(self, quaternion: Quaternion):

def convert_to_euler(self, quaternion: Quaternion):
return transforms3d.euler.quat2euler([quaternion.w, quaternion.x, quaternion.y, quaternion.z])


def reduce_rate(self):
self.timer.cancel()
self.create_timer(self.reduced_rate)
self.rate_is_reduced = True
self.logger.warning("Team communication: message sending rate is reduced now")

def create_timer(self, rate: int):
self.timer = self.node.create_timer(1 / rate, self.send_message, callback_group=MutuallyExclusiveCallbackGroup())

def should_reduce_rate(self):
# we are allowed to send 2.5 msg per second on average with each robot (12000 with 4 robots in a 1200 sekonds game)
# the msg_left_linear_rate is the amount of messages we would send if we send exactly with this 2.5 msg per sec per robot rate
# once our actual msg budget is below this linear rate we tend to send more msg then allowed and should reduce our sending rate
if self.game_started_recently():
return False

msg_left_linear_rate = (self.gamestate.first_half * 600 + self.gamestate.secs_remaining) * 4 * 2.5
return msg_left_linear_rate > self.gamestate.message_budget

def game_started_recently(self):
#true in the first 60 seconds of the game
return self.gamestate.first_half and self.gamestate.secs_remaining > 540

def main():
rclpy.init(args=None)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ team_comm:

# Rate of published messages in Hz
rate: 2
# Rate of published messages in Hz, when rate is reduced
reduced_rate: 2

# average walking speed in [m/s]
avg_walking_speed: 0.2
Expand Down
Loading