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

New gameplay passing #1644

Merged
merged 18 commits into from
Jun 18, 2021
Merged

New gameplay passing #1644

merged 18 commits into from
Jun 18, 2021

Conversation

HussainGynai
Copy link
Contributor

@HussainGynai HussainGynai commented May 24, 2021

Description

Everything needed for passing will go here (pivoting, pivot kicking, receiving, passing).
Current things in:

  • Pivot action with test play
  • Pivot kick skill with test play
  • Receive Action
  • Passing tactic with test play
    With the pivot kick skill, I had to create our own separate sequence block for behavior trees, since we need to pass actions/intent back up the tree. When an action server is implemented we will no longer need this, since the action can just make a direct call to the server to start behavior, and won't need to pass any data back up.

Steps to test

Test Case 1

  1. Run sim
  2. robot 1 should capture the ball, spin to face robot 7, kick the ball at 7, 7 settles the ball.

@codecov-commenter
Copy link

codecov-commenter commented May 24, 2021

Codecov Report

Merging #1644 (cc59d58) into gameplay_node_update (78fd8b4) will decrease coverage by 2.87%.
The diff coverage is 0.00%.

❗ Current head cc59d58 differs from pull request most recent head c4105a6. Consider uploading reports for the commit c4105a6 to get more accurate results
Impacted file tree graph

@@                   Coverage Diff                    @@
##           gameplay_node_update    #1644      +/-   ##
========================================================
- Coverage                 33.36%   30.49%   -2.88%     
========================================================
  Files                        46       51       +5     
  Lines                      1912     2099     +187     
========================================================
+ Hits                        638      640       +2     
- Misses                     1274     1459     +185     
Impacted Files Coverage Δ
rj_gameplay/rj_gameplay/action/pivot.py 0.00% <0.00%> (ø)
rj_gameplay/rj_gameplay/gameplay_node.py 0.00% <0.00%> (ø)
rj_gameplay/rj_gameplay/play/pivot_play.py 0.00% <0.00%> (ø)
rj_gameplay/rj_gameplay/skill/move.py 0.00% <ø> (ø)
rj_gameplay/rj_gameplay/skill/temp_pivot_skill.py 0.00% <0.00%> (ø)
...j_gameplay/rj_gameplay/tactic/temp_pivot_tactic.py 0.00% <0.00%> (ø)
rj_gameplay/stp/coordinator.py 0.00% <0.00%> (ø)
rj_gameplay/stp/rc.py 87.86% <0.00%> (-0.24%) ⬇️
rj_gameplay/rj_gameplay/skill/mark.py 0.00% <0.00%> (ø)
... and 9 more

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 78fd8b4...c4105a6. Read the comment docs.

rj_gameplay/rj_gameplay/action/pivot.py Outdated Show resolved Hide resolved
rj_gameplay/rj_gameplay/skill/temp_pivot_skill.py Outdated Show resolved Hide resolved
rj_gameplay/rj_gameplay/skill/temp_pivot_skill.py Outdated Show resolved Hide resolved
rj_gameplay/rj_gameplay/skill/temp_pivot_skill.py Outdated Show resolved Hide resolved
rj_gameplay/rj_gameplay/skill/temp_pivot_skill.py Outdated Show resolved Hide resolved
rj_gameplay/rj_gameplay/tactic/temp_pivot_tactic.py Outdated Show resolved Hide resolved
rj_gameplay/stp/coordinator.py Outdated Show resolved Hide resolved
rj_gameplay/rj_gameplay/skill/temp_pivot_skill.py Outdated Show resolved Hide resolved
Copy link
Contributor

@kfu02 kfu02 left a comment

Choose a reason for hiding this comment

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

Left minor comments, but robot 7 does pivot towards (0,0), which is what matters most right now. Nicely done.

self.pivot_point = pivot_point
self.target_point = target_point
self.dribble_speed =dribble_speed
Copy link
Contributor

Choose a reason for hiding this comment

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

Nit: space before dribble_speed here

dot_product = np.dot(robot_pos_unit, target_point_unit)
angle = np.arccos(dot_product)
if abs(angle - angle_threshold) < angle_threshold:
Copy link
Contributor

Choose a reason for hiding this comment

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

Could more simply return the conditional directly, but it doesn't matter if we'll end up rewriting this anyways.

if robot is not None:
self.pivot.pivot_point = robot.pose[0:2]
actions = self.root.tick_once(robot)
return actions
# TODO: change so this properly returns the actions intent messages
Copy link
Contributor

Choose a reason for hiding this comment

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

This TODO is done, right?

import numpy as np

class PivotPlay(play.IPlay):
"""A play which lines up two robots, one on the right the one on the left
Copy link
Contributor

Choose a reason for hiding this comment

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

Comment is wrong, but this is a temp play anyhow so it doesn't matter.

rj_gameplay/rj_gameplay/skill/temp_pivot_skill.py Outdated Show resolved Hide resolved
rj_gameplay/rj_gameplay/tactic/temp_pivot_tactic.py Outdated Show resolved Hide resolved
if not self.pivot.is_done(world_state):
role_requests[self.pivot] = self.pivot.get_requests(world_state, None)
else:
pass
Copy link
Contributor

Choose a reason for hiding this comment

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

Delete the else: pass, unless this is a stub, in which case add a TODO above the pass here.

Copy link
Contributor

Choose a reason for hiding this comment

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

(Temp play caveat applies here too though)

Base automatically changed from gameplay_node_update to ros2 June 4, 2021 02:50
Copy link
Contributor

@kfu02 kfu02 left a comment

Choose a reason for hiding this comment

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

I have a few minor nits and a couple questions. Overall looks good though!

rj_gameplay/rj_gameplay/play/test_pass.py Outdated Show resolved Hide resolved
rj_gameplay/rj_gameplay/play/test_pass.py Outdated Show resolved Hide resolved
else:
skills = []

return (skill_dict ,skills)
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
return (skill_dict ,skills)
return (skill_dict, skills)

rj_gameplay/rj_gameplay/tactic/pass_tactic.py Outdated Show resolved Hide resolved
rj_gameplay/rj_gameplay/tactic/pass_tactic.py Show resolved Hide resolved
rj_gameplay/stp/skill/action_behavior.py Show resolved Hide resolved
rj_gameplay/rj_gameplay/skill/pivot_kick.py Outdated Show resolved Hide resolved
rj_gameplay/stp/skill/rj_sequence.py Outdated Show resolved Hide resolved
@kfu02 kfu02 self-requested a review June 13, 2021 23:36
Copy link
Contributor

@kfu02 kfu02 left a comment

Choose a reason for hiding this comment

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

Looks good! Caught one more weird space though, haha.


return (skill_dict, skills)

def is_done(self ,world_state):
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
def is_done(self ,world_state):
def is_done(self, world_state):

lol just saw this

Copy link
Contributor

Choose a reason for hiding this comment

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

you can directly click "Commit suggestion" on GH if you want, not sure if you were aware

Copy link
Contributor

Choose a reason for hiding this comment

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

bump

Copy link
Contributor

@Yudai-8-om Yudai-8-om left a comment

Choose a reason for hiding this comment

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

The code looks good to me, and robots moved as designed.
But you would want to tweak the ball speed a bit.
I did 4 trials:

  • 1 success
  • Robot 7 missed the ball 2 times
  • Robot 7 fumbled the ball.

This happened probably because the ball_speed was too fast, I think.
Overall, good work!


def fail(self):
return False
def __init__(self, robot_id:Optional[int]=None, chip:Optional[bool]=False, kick_speed:Optional[float]=255.0) -> None:
Copy link
Contributor

Choose a reason for hiding this comment

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

You would want to lower the kick_speed here?

Copy link
Contributor

Choose a reason for hiding this comment

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

kick_speed should be in m/s, so this is definitely way too fast. Do these all really need default values? I'd prefer not to allow a default value for kick at least, and I thought we designed things in a way that you didn't need to construct actions until you know which robot they're assigned to?

rj_gameplay/rj_gameplay/action/kick.py Outdated Show resolved Hide resolved
@kfu02 kfu02 mentioned this pull request Jun 15, 2021
@kfu02 kfu02 requested a review from kylestach June 15, 2021 19:06

return intent

def is_done(self, world_state) -> bool:
if world_state.our_robots[self.robot_id].has_ball_sense:
if not self.robot_id is None and world_state.our_robots[self.robot_id].has_ball_sense:
Copy link
Contributor

Choose a reason for hiding this comment

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

When will robot_id be None?

Copy link
Contributor

Choose a reason for hiding this comment

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

when capture action is initialized we have to default all to None


def fail(self):
return False
def __init__(self, robot_id:Optional[int]=None, chip:Optional[bool]=False, kick_speed:Optional[float]=255.0) -> None:
Copy link
Contributor

Choose a reason for hiding this comment

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

kick_speed should be in m/s, so this is definitely way too fast. Do these all really need default values? I'd prefer not to allow a default value for kick at least, and I thought we designed things in a way that you didn't need to construct actions until you know which robot they're assigned to?

return new_intent

def is_done(self, world_state:rc.WorldState) -> bool:
return np.linalg.norm(world_state.ball.vel) > 1
Copy link
Contributor

Choose a reason for hiding this comment

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

I really do not trust this condition at all...

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yeah, I could make it check that the ball is going away from the kicking robot.

rj_gameplay/rj_gameplay/action/pivot.py Show resolved Hide resolved
Receive action
"""

def __init__(self, robot_id: int = None, one_touch_target:np.ndarray = None):
Copy link
Contributor

Choose a reason for hiding this comment

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

For a vanilla receive we don't need one touch target.

There should be a separate action for one touches

rj_gameplay/rj_gameplay/tactic/pass_tactic.py Show resolved Hide resolved
rj_gameplay/rj_gameplay/tactic/pass_tactic.py Outdated Show resolved Hide resolved
rj_gameplay/rj_gameplay/tactic/pass_tactic.py Outdated Show resolved Hide resolved
rj_gameplay/stp/coordinator.py Outdated Show resolved Hide resolved
rj_gameplay/rj_gameplay/action/pivot.py Outdated Show resolved Hide resolved
HussainGynai and others added 3 commits June 16, 2021 00:54
@Yudai-8-om Yudai-8-om self-requested a review June 17, 2021 02:21
@kfu02 kfu02 self-requested a review June 17, 2021 03:14
Copy link
Contributor

@kfu02 kfu02 left a comment

Choose a reason for hiding this comment

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

Minor typos, behavior looks much neater. See my Slack comment about the capture skill before merging, though.


return (skill_dict, skills)

def is_done(self ,world_state):
Copy link
Contributor

Choose a reason for hiding this comment

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

bump

self.robot = role.robot
self.root = py_trees.composites.Sequence("Sequence")
def __init__(self, target_point:np.array, chip:bool, kick_speed:float, robot:rc.Robot=None) -> None:
#TODO: Have something which automatically determines kick speed based on targert point distance
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
#TODO: Have something which automatically determines kick speed based on targert point distance
#TODO: Have something which automatically determines kick speed based on target point distance

#TODO: Have something which automatically determines kick speed based on targert point distance
self.__name__ = 'pivot kick'
self.robot = robot
self.chip= chip
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
self.chip= chip
self.chip = chip

def __init__(self, role: role.Role, target_point: np.array) -> None:
self.robot = role.robot
self.root = py_trees.composites.Sequence("Sequence")
def __init__(self, target_point:np.array, chip:bool, kick_speed:float, robot:rc.Robot=None) -> None:
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
def __init__(self, target_point:np.array, chip:bool, kick_speed:float, robot:rc.Robot=None) -> None:
def __init__(self, target_point: np.array, chip: bool, kick_speed: float, robot: rc.Robot=None) -> None:

Copy link
Contributor

Choose a reason for hiding this comment

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

also maybe consider putting robot first? for consistency w/ other skills

@kfu02 kfu02 mentioned this pull request Jun 17, 2021
Copy link
Contributor

@Yudai-8-om Yudai-8-om left a comment

Choose a reason for hiding this comment

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

Receive skill is probably needed to be updated because robot 7 always fumbles the ball
Pivot kick looks perfect.

@@ -81,7 +81,7 @@ def get_requests(

role_requests: tactic.RoleRequests = {}

passer_request = role.RoleRequest(role.Priority.HIGH, True, self.passer_cost)
passer_request = role.RoleRequest(role.Priority.HIGH, True, self.Passer_cost)
role_requests[self.pivot_kick] = [passer_request]
receive_request = role.RoleRequest(role.Priority.HIGH, True, self.receiver_cost)
Copy link
Contributor

Choose a reason for hiding this comment

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

Based on understanding, it requests receive skill and capture skill simultaneously. so when robot 1 passes the ball, robot 7 moves toward the kicker, and it makes it difficult for the receiver to settle the ball, I believe. Capture skill should be applied only when the ball gets closer to the receiver??

Copy link
Contributor Author

Choose a reason for hiding this comment

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

this is what does happen, kind of, if you check the receive action its based off of the speed of the ball, so when the ball is slow the capture starts. I am also changing it so that if the robot has ball sense it starts capture.

Copy link
Contributor

Choose a reason for hiding this comment

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

Great! Now I understand what was happening!

Copy link
Contributor

@kfu02 kfu02 left a comment

Choose a reason for hiding this comment

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

Left nit, the receive looks much cleaner now. Nice work.

role_requests: play.RoleRequests = {}
if not self.pass_tactic.is_done(world_state):
role_requests[self.pass_tactic] = self.pass_tactic.get_requests(world_state, None)
else:
Copy link
Contributor

Choose a reason for hiding this comment

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

delete this else

@kfu02 kfu02 requested review from Yudai-8-om and kylestach June 18, 2021 15:37
@kfu02 kfu02 mentioned this pull request Jun 18, 2021
Copy link
Contributor

@Yudai-8-om Yudai-8-om left a comment

Choose a reason for hiding this comment

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

LGTM!
If we can make the transition from capture to passing more seamless, that would be nicer!

@HussainGynai HussainGynai merged commit 1ddf123 into ros2 Jun 18, 2021
@HussainGynai HussainGynai deleted the new_gameplay_passing branch June 18, 2021 17:29
heading_vect = np.array([np.cos(heading_angle), np.sin(heading_angle)])
dot_product = np.dot(heading_vect, ball_vel_unit)
#TODO: Make this threshold a local param
if dot_product > 0.1:
Copy link
Contributor

Choose a reason for hiding this comment

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

This threshold should be higher, vision noise can probably hit this pretty easily.

rj_gameplay/rj_gameplay/action/pivot.py Show resolved Hide resolved

def is_done(self, world_state:rc.WorldState) -> bool:
#TODO: Change this when we get action state feedback
angle_threshold = 0.1
Copy link
Contributor

Choose a reason for hiding this comment

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

This is definitely too big, it's about 6°. It should be closer to 1° (0.02 or so)

if self.robot_id is None:
return False
#TODO: Use local params for this threshold
if world_state.our_robots[self.robot_id].has_ball_sense or np.linalg.norm(world_state.ball.vel) < 10**(-6):
Copy link
Contributor

Choose a reason for hiding this comment

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

Velocity threshold is again way too small...also, nit: please make it a constant (even if it's not a local param)

import numpy as np


class Receiver_cost(role.CostFn):
Copy link
Contributor

Choose a reason for hiding this comment

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

Nit: ReceiverCost

Copy link
Contributor

Choose a reason for hiding this comment

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

@HussainGynai the cost functions in other tactics are styled as if they're methods, since we use/call these classes as methods. What are we going with?

Copy link
Contributor Author

@HussainGynai HussainGynai Jun 18, 2021

Choose a reason for hiding this comment

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

According to Kyle seems like class style is better here, when they're instantiated they should probably be in method form though I think.

return 0.0
return 1.0

class Passer_cost(role.CostFn):
Copy link
Contributor

Choose a reason for hiding this comment

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

Nit: PasserCost

self.capture = capture.Capture(self.robot.id)
else:
self.receive = receive.Receive(self.robot)
self.capture = capture.Capture()
Copy link
Contributor

Choose a reason for hiding this comment

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

I'm confused by these constructors here. Why do we pass in self.robot for Receive? Isn't the first argument supposed to be an ID?

Copy link
Contributor

Choose a reason for hiding this comment

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

self.robot is None is the else block so it works, I agree that it's confusing tho

@kfu02
Copy link
Contributor

kfu02 commented Jun 18, 2021

ignore the above msg, I was wondering what the "revert" button did on GH

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants