- Last meeting was pretty dense
- We NEED to have 1 on 1 time with each of you, so it is your responsibility to waive us over if you’re stuck!
- Topics Covered:
- Python
- State Machines
- Play/Skill/Tactic Structure
- And today, we’re going into…
- See the previous slide deck and docs for more information, they should be a pretty comprehensive overview of our play system.
- A Behavior is a generic name for any skill, play, or tactic.
- Last meeting we learned about Plays/Skills/Tactics
- How do we put them together?
- Subbehaviors allow you to reuse our behaviors in many plays.
- Example: We have one move play, used by kicker tactics, passing tactics, goalie, etc.
- Offense Play contains Passing Tactics, and Move Skills
- Passing Tactic Contains Move and Kick Skills
Basic122::running
Mark::running[robot=4]
move(0.767296, 6.51286)
endVelocity(0, 0)
face(0.160718, 9.15305)
PivotKick::capturing
Capture::course_approach[robot=2]
face(0.160718, 9.15305)
avoidBall(-1)
move(0.176939, 9.114)
endVelocity(0, 0)
Mark::running[robot=1]
move(-0.829012, 6.03814)
endVelocity(0, 0)
face(0.160718, 9.15305)
- Here we have a tree of all the behaviors running
- We have a basic122 play running
- It is running 2 Marks, and a PivotKick in this frame
- The marks are directly running robot commands, like move, and face.
- The PivotKick is running a capture skill, which is running robot commands, like face, move, etc.
Basic122::running
Defense::defending
SubmissiveDefender::marking
Move::completed[robot=5]
face(0.160718, 9.15305)
SubmissiveDefender::marking
Move::completed[robot=3]
face(0.160718, 9.15305)
SubmissiveGoalie::block
Move::running[robot=0]
face(0.160718, 9.15305)
move(0.290916, 0.14)
endVelocity(0, 0)
- Pretty much same thing here
- We’ve got a Defense tactic running, with SubmissiveDefender and Goalie Skills
- These skills actually run robot commands.
self.add_subbehavior(skill_object,
"Name of Subbehavior",
required=False or True
priority=10) # A higher number is higher priority
- For more docs on this entire section see this link.
- These subbehaviors show up in the behavior tree when you run your program.
- This can be extremely useful when debugging state transitions or subbehavior assignments.
self.remove_subbehavior('string name')
self.remove_all_subbehaviors()
a_subbheavior = self.subbehavior_with_name('string name')
def on_enter_running(self):
receiver = skills.pass_receive.PassReceive()
receiver.receive_point = self.receive_point
self.add_subbehavior(receiver,
'receiver',
required=self.receiver_required)
def on_exit_running(self):
self.remove_subbehavior('receiver')
- First State Machine is set up, then:
# Triggered whenever the line changes
self.remove_all_subbehaviors()
for i in range(6):
pt = self._line.get_pt(0) + (self.diff * float(i))
self.add_subbehavior(
skills.move.Move(pt),
name="robot" + str(i),
required=False,
priority=6 - i)
def execute_running(self):
for i in range(6):
pt = self._line.get_pt(0) + (self.diff * float(i))
self.subbehavior_with_name("robot" + str(i)).pos = pt
- Find some code doing something like what you want
- Tweak it until it works
- It’s less effective than working everything out, but it’s great for beginners!
- Our role assignment system picks the best robot for the task
- You define your constraints, and we’ll give you a robot if we can!
- It’s also some black magic…
- Override Role Requirements to add your constraints!
- This next section is Extra Credit…
- And it’s a massive oversimplification
- See
role_assignment.py
for more information.
# From Move
def role_requirements(self):
reqs = super().role_requirements()
# Destination Shape is used for distances to points or segments
reqs.destination_shape = self.pos
return reqs
def role_requirements(self):
reqs = super().role_requirements()
reqs.require_kicking = True
# try to be near the ball
if main.ball().valid:
reqs.destination_shape = main.ball().pos
return reqs
# From Goalie
def role_requirements(self):
reqs = super().role_requirements()
# This iteration is needed if we have
# subbehaviors we want to have applied as well.
for req in role_assignment \
.iterate_role_requirements_tree_leaves(reqs):
req.required_shell_id \
= self.shell_id if self.shell_id != None else -1
return reqs
- Create a binary clock play
- Display the current minute in binary on the field
- Use a robot to represent a 1, and lack of a robot to represent a 0
- Starter code is in
soccer/gameplay/plays/skel/binary_clock.py
. - Move it to
soccer/gameplay/plays/training
to begin.
import time
mins = time.localtime().tm_min
binary = format(mins, '06b')
print(binary)
# Index with binary[0-6]
# THIS INDEX IS A CHARACTER VALUE, NOT AN INT
# USE == '1', not == 1
#+RESULTS[2cdccf696e363d1f51ce50c0b895bf17a58a9b55]:
010011