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
Show file tree
Hide file tree
Changes from 6 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
1 change: 0 additions & 1 deletion rj_gameplay/rj_gameplay/action/capture.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ def tick(self, intent) -> None:
intent.motion_command.collect_command = [collect_command]
intent.dribbler_speed = 1.0
intent.is_active = True

return intent

def is_done(self, world_state) -> bool:
Expand Down
14 changes: 11 additions & 3 deletions rj_gameplay/rj_gameplay/action/kick.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,7 @@ class Kick(IKick):
"""
Kick action
"""
def __init__(self, robot_id:Optional[int]=None, chip:Optional[bool]=False, kick_speed:Optional[float]=255.0) -> None:
#TODO: Cahnge kick speed to use max_kick_speed param for default value
def __init__(self, robot_id:int, chip:bool, kick_speed:float) -> None:
self.robot_id = robot_id
self.chip = chip
self.kick_speed = kick_speed
Expand All @@ -37,4 +36,13 @@ def tick(self, intent:RobotIntent) -> RobotIntent:
return new_intent

def is_done(self, world_state:rc.WorldState) -> bool:
return np.linalg.norm(world_state.ball.vel) > 1
if self.robot_id is None:
return False
ball_vel_unit = world_state.ball.vel / np.linalg.norm(world_state.ball.vel)
heading_angle = world_state.our_robots[self.robot_id].pose[2]
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.

return True
return False
3 changes: 2 additions & 1 deletion rj_gameplay/rj_gameplay/action/pivot.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@

class Pivot(action.IFiniteAction):

def __init__(self, robot_id:int, pivot_point:np.ndarray, target_point:np.ndarray, dribble_speed:float=1.0, priority:int=1):
def __init__(self, robot_id:int, pivot_point:np.ndarray, target_point:np.ndarray, dribble_speed:float, priority:int=1):
self.robot_id = robot_id
self.pivot_point = pivot_point
self.target_point = target_point
Expand All @@ -32,6 +32,7 @@ def tick(self, intent: RobotIntent) -> None:
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)

#TODO: Make these local params
stopped_threshold = 1*10**(-5)
kfu02 marked this conversation as resolved.
Show resolved Hide resolved
if self.robot_id is None:
return False
Expand Down
8 changes: 3 additions & 5 deletions rj_gameplay/rj_gameplay/action/receive.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,22 +13,20 @@ class Receive(action.IAction):
Receive action
"""

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


def tick(self, intent) -> None:
settle_command = SettleMotionCommand()
if self.one_touch_target is not None:
settle_command.maybe_target = self.one_touch_target
intent.motion_command.settle_command = [settle_command]
intent.dribbler_speed = 1.0
intent.is_active = True

return intent

def is_done(self, world_state) -> bool:
if np.linalg.norm(world_state.ball.vel) < 0.1:
#TODO: Use local params for this threshold
if np.linalg.norm(world_state.ball.vel) < 0.005:
return True
return False
14 changes: 10 additions & 4 deletions rj_gameplay/rj_gameplay/skill/pivot_kick.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@
import stp.rc as rc
import numpy as np

MAX_DRIBBLER_SPEED = 1.0

class IPivotKick(skill.ISkill, ABC):
...

Expand All @@ -22,17 +24,21 @@ class PivotKick(IPivotKick):
A pivot kick skill
"""

def __init__(self, target_point:np.array, 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.

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

#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

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

self.kick_speed = kick_speed
self.root = Sequence("Sequence")
self.target_point = target_point
if robot is not None:
self.pivot = action.pivot.Pivot(robot.id ,robot.pose[0:2], target_point)
self.pivot = action.pivot.Pivot(robot.id ,robot.pose[0:2], target_point, MAX_DRIBBLER_SPEED)
self.kick = action.kick.Kick(self.robot.id, self.chip, self.kick_speed)
else:
self.pivot = action.pivot.Pivot(None, np.array([0.0,0.0]), target_point)
self.pivot = action.pivot.Pivot(None, np.array([0.0,0.0]), target_point, MAX_DRIBBLER_SPEED)
self.kick = action.kick.Kick(self.robot, self.chip, self.kick_speed)
self.capture = action.capture.Capture()
self.kick = action.kick.Kick()
self.capture_behavior = ActionBehavior('Capture', self.capture)
self.pivot_behavior = ActionBehavior('Pivot', self.pivot)
self.kick_behavior = ActionBehavior('Kick', self.kick)
Expand Down
8 changes: 3 additions & 5 deletions rj_gameplay/rj_gameplay/skill/receive.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,16 +27,14 @@ class IReceive(skill.ISkill, ABC):
class Receive(IReceive):

def __init__(self,
robot:rc.Robot = None,
one_touch_target:np.ndarray = None):
robot:rc.Robot = None):

self.robot = robot
self.one_touch_target = one_touch_target
if self.robot is not None:
self.receive = receive.Receive(self.robot.id, self.one_touch_target)
self.receive = receive.Receive(self.robot.id)
self.capture = capture.Capture(self.robot.id)
else:
self.receive = receive.Receive(self.robot, self.one_touch_target)
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

self.receive_behavior = ActionBehavior('Receive', self.receive)
kylestach marked this conversation as resolved.
Show resolved Hide resolved
self.capture_behavior = ActionBehavior('Capture', self.capture)
Expand Down
12 changes: 6 additions & 6 deletions rj_gameplay/rj_gameplay/tactic/pass_tactic.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
import numpy as np


class receiver_cost(role.CostFn):
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.

"""
A cost function for how to choose a robot to pass to
TODO: Implement a better cost function
Expand All @@ -33,7 +33,7 @@ def __call__(
return 0.0
kylestach marked this conversation as resolved.
Show resolved Hide resolved
return 1.0

class passer_cost(role.CostFn):
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

"""
A cost function for how to choose a robot that will pass
TODO: Implement a better cost function
Expand All @@ -59,10 +59,10 @@ class Pass(tactic.ITactic):

def __init__(self, target_point:np.ndarray):
self.target_point = target_point
self.pivot_kick = tactic.SkillEntry(pivot_kick.PivotKick(target_point = target_point))
self.pivot_kick = tactic.SkillEntry(pivot_kick.PivotKick(target_point = target_point, chip=False, kick_speed=4.0))
self.receive = tactic.SkillEntry(receive.Receive())
self.receiver_cost = receiver_cost(target_point)
self.passer_cost = passer_cost()
self.receiver_cost = Receiver_cost(target_point)
self.Passer_cost = Passer_cost()

def compute_props(self):
pass
Expand All @@ -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!

role_requests[self.receive] = [receive_request]
Expand Down
1 change: 0 additions & 1 deletion rj_gameplay/stp/coordinator.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
import stp.role.assignment as assignment
import stp.situation
from rj_msgs import msg
from rj_geometry_msgs.msg import Point

NUM_ROBOTS = 16

Expand Down