-
Notifications
You must be signed in to change notification settings - Fork 110
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
Implemented Chip Pass Modeling #3229
Implemented Chip Pass Modeling #3229
Conversation
#include "software/logger/logger.h" | ||
#include "proto/message_translation/tbots_protobuf.h" | ||
|
||
// #include "software/logger/logger.h" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
remember to re-comment this back in
LOG(PLOTJUGGLER) << *createPlotJugglerValue({ | ||
{"dist", std::sqrt(pow(p.x() - 0, 2) + pow(p.y() - 0, 2))}, | ||
{"z", p.z()} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
remember to remove this when you're done
@@ -79,10 +80,13 @@ std::unique_ptr<SSLSimulationProto::RobotCommand> getRobotCommandFromDirectContr | |||
float numerator = | |||
range * | |||
static_cast<float>(ACCELERATION_DUE_TO_GRAVITY_METERS_PER_SECOND_SQUARED); | |||
float denominator = static_cast<float>(2.0f * (chip_angle * 2.0f).sin()); | |||
float denominator = static_cast<float>(2.0f * (chip_angle * 2.0f).22()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
.22()
?
LOG(PLOTJUGGLER) << *createPlotJugglerValue({ | ||
{"speed", chip_speed} | ||
}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
remember to remove when you're done
// std::vector<ValidationFunction> terminating_validation_functions = { | ||
// [angle_to_kick_at, tactic](std::shared_ptr<World> world_ptr, | ||
// ValidationCoroutine::push_type& yield) { | ||
// while (!tactic->done()) | ||
// { | ||
// yield("Tactic did not complete!"); | ||
// } | ||
// ballKicked(angle_to_kick_at, world_ptr, yield); | ||
// }}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
remember to comment this back in
// place the ball directly to the left of the robot | ||
std::make_tuple(Vector(0, 0.5), Angle::zero()), | ||
// place the ball directly to the right of the robot | ||
std::make_tuple(Vector(0, -0.5), Angle::zero()), | ||
// place the ball directly infront of the robot | ||
std::make_tuple(Vector(0.5, 0), Angle::zero()), | ||
// place the ball directly behind the robot | ||
std::make_tuple(Vector(-0.5, 0), Angle::zero()), | ||
// place the ball in the robots dribbler | ||
std::make_tuple(Vector(ROBOT_MAX_RADIUS_METERS, 0), Angle::zero()), | ||
// Repeat the same tests but kick in the opposite direction | ||
// place the ball directly to the left of the robot | ||
std::make_tuple(Vector(0, 0.5), Angle::half()), | ||
// place the ball directly to the right of the robot | ||
std::make_tuple(Vector(0, -0.5), Angle::half()), | ||
// place the ball directly infront of the robot | ||
std::make_tuple(Vector(0.5, 0), Angle::half()), | ||
// place the ball directly behind the robot | ||
std::make_tuple(Vector(-0.5, 0), Angle::half()), | ||
// place the ball in the robots dribbler | ||
std::make_tuple(Vector(ROBOT_MAX_RADIUS_METERS, 0), Angle::zero()))); | ||
// std::make_tuple(Vector(0, 0.5), Angle::zero()), | ||
// // place the ball directly to the right of the robot | ||
// std::make_tuple(Vector(0, -0.5), Angle::zero()) | ||
// // place the ball directly infront of the robot | ||
std::make_tuple(Vector(0.5, 0), Angle::zero()) | ||
// // place the ball directly behind the robot | ||
// std::make_tuple(Vector(-0.5, 0), Angle::zero()), | ||
// // place the ball in the robots dribbler | ||
// std::make_tuple(Vector(ROBOT_MAX_RADIUS_METERS, 0), Angle::zero()), | ||
// // Repeat the same tests but kick in the opposite direction | ||
// // place the ball directly to the left of the robot | ||
// std::make_tuple(Vector(0, 0.5), Angle::half()), | ||
// // place the ball directly to the right of the robot | ||
// std::make_tuple(Vector(0, -0.5), Angle::half()), | ||
// // place the ball directly infront of the robot | ||
// std::make_tuple(Vector(0.5, 0), Angle::half()), | ||
// // place the ball directly behind the robot | ||
// std::make_tuple(Vector(-0.5, 0), Angle::half()), | ||
// // place the ball in the robots dribbler | ||
// std::make_tuple(Vector(ROBOT_MAX_RADIUS_METERS, 0), Angle::zero()) | ||
)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
remember to revert these when you're done
|
||
double BasePass::length() const | ||
{ | ||
return std::sqrt(std::pow(receiverPoint().x() - passerPoint().x(), 2) + std::pow(receiverPoint().y() - passerPoint().y(), 2)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
return std::sqrt(std::pow(receiverPoint().x() - passerPoint().x(), 2) + std::pow(receiverPoint().y() - passerPoint().y(), 2)); | |
return (receiverPoint() - passerPoint()).length() |
// std::ostream& printHelper(std::ostream& output_stream, const BasePass& pass) | ||
// { | ||
// output_stream << "Pass from " << pass.passer_point | ||
// << " to: " << pass.receiver_point; | ||
|
||
// return output_stream; | ||
// } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
remember to remove this when you're done
// (receive_location_x, receive_location_y) | ||
static const int NUM_PARAMS_TO_OPTIMIZE = 2; | ||
|
||
class BasePass |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
missing class docs
virtual Duration estimatePassDuration() const | ||
{ | ||
return Duration::fromSeconds(0); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this seems a bit of a useless implementation, why not do virtual Duration estimatePassDuration() const = 0
?
src/software/ai/passing/base_pass.h
Outdated
/** | ||
// * Implement the "<<" operator for printing | ||
// * | ||
// * @param output_stream The stream to print to | ||
// * @param pass The pass to print | ||
// * @return The output stream with the string representation of the class appended | ||
// */ | ||
// friend std::ostream& printHelper(std::ostream& output_stream, const BasePass& pass); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why is this declared as a friend
function?
double last_bounce_range; | ||
double length_to_go = length(); | ||
|
||
std::cout << "LENGTH: " << length_to_go << std::endl; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
delete when done
std::cout << "LENGTH: " << length_to_go << std::endl; | ||
|
||
// if we cover more than 90% of the pass, stop calculating | ||
while(length_to_go >= pass_length * 0.1) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
0.1
should be a constant of some kind
double bounce_height = getBounceHeightFromDistanceTraveled(length_to_go); | ||
last_bounce_range = getBounceRangeFromBounceHeight(bounce_height); | ||
length_to_go -= last_bounce_range; | ||
std::cout << "LENGTH: " << length_to_go << std::endl; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
remove std::cout when you're done
|
||
double ChipPass::getBounceHeightFromDistanceTraveled(double distance_traveled) | ||
{ | ||
return 0.0306 * std::exp(-2.04 * (distance_traveled - pass_length)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
you should link a picture of the plot for future software members
|
||
double ChipPass::getBounceRangeFromBounceHeight(double bounce_height) | ||
{ | ||
return 4 * bounce_height * (std::cos(ROBOT_CHIP_ANGLE_RADIANS) / std::sin(ROBOT_CHIP_ANGLE_RADIANS)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
you should add some comments about where this derivation comes form
|
||
Duration ChipPass::estimatePassDuration() const | ||
{ | ||
return Duration::fromSeconds(0); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
do you have plans of estimating the time? or is it intentionally 0?
|
||
double firstBounceRange(); | ||
|
||
virtual Duration estimatePassDuration() const; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
you should use override
so that it checks at compile time that you're overriding the base class implementation corrctly
#include "software/ai/passing/base_pass.h" | ||
#include "shared/constants.h" | ||
|
||
class ChipPass: public BasePass |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
missing docs
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
functions in this class are missing docs
|
||
EXPECT_EQ(Point(1, 2), p.passerPoint()); | ||
EXPECT_EQ(Point(3, 4), p.receiverPoint()); | ||
std::cout << p.firstBounceRange() << std::endl; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
remove std::cout when you're done
* @return An estimate of how long the pass will take, from kicking to receiving | ||
*/ | ||
Duration estimatePassDuration() const; | ||
virtual Duration estimatePassDuration() const; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
virtual Duration estimatePassDuration() const; | |
Duration estimatePassDuration() const = override; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I know you're still working on the details of this project but I left some interim feedback
is this PR scoped to modelling chips? what's the plan for generating more chip passes? |
return std::max((btScalar)0, relBallSpeed.y()) - | ||
qBound((btScalar)0, (btScalar)0.5 * relBallSpeed.y(), | ||
(btScalar)0.5 * dirFloor); | ||
} | ||
}; | ||
const float speedCompensation = getSpeedCompensation(); | ||
ball->kick(t * btVector3(0, dirFloor * power + speedCompensation, dirUp * power) * | ||
ball->kick(t * btVector3(0, dirFloor * power - speedCompensation, dirUp * power) * |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why do you need this change?
src/software/ai/passing/base_pass.h
Outdated
return Duration::fromSeconds(0); | ||
} | ||
|
||
virtual Duration estimateTimeToPoint(Point& point) const; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
needs docs
// if we cover more than 90% of the pass, stop calculating | ||
while(length_to_go >= pass_length * 0.2) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
90% should be pass_length * 0.1
|
||
Duration ChipPass::estimateTimeToPoint(Point& point) const | ||
{ | ||
return Duration::fromSeconds(0); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
needs impl
* | ||
* @param passer_point the starting point of the pass | ||
* @param pass_destination the end point of the pass | ||
* @return the ChipPass constructed from the start and end points |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we don't usually add @return
to constructors
*/ | ||
ChipPass(Point passer_point, Point receiver_point); | ||
|
||
double firstBounceRange(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
needs docs
src/software/ai/passing/chip_pass.h
Outdated
double calcFirstBounceRange(); | ||
|
||
double getBounceHeightFromDistanceTraveled(double distance_traveled); | ||
|
||
double getBounceRangeFromBounceHeight(double bounce_height); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
needs docs
double rateGroundPass(const World& world, const Pass& pass, const Rectangle& zone, | ||
TbotsProto::PassingConfig passing_config) | ||
{ | ||
return ratePass(world, pass, zone, world.enemyTeam(), passing_config); | ||
} | ||
|
||
double rateChipPass(const World& world, const ChipPass& pass, const Rectangle& zone, | ||
TbotsProto::PassingConfig passing_config) | ||
{ | ||
return ratePass(world, pass, zone, world.enemyTeam(), passing_config); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if you're using the same implementation, does it make sense to have separate rateGroundPass
and rateChipPass
methods?
ball_time_to_closest_pass_point = | ||
Duration::fromSeconds(std::numeric_limits<int>::max()); | ||
} | ||
Duration ball_time_to_closest_pass_point = pass.estimateTimeToPoint(closest_point_on_pass_to_robot); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
you still need to do a check for division by 0 here
@@ -246,12 +250,6 @@ double ratePassFriendlyCapability(const Team& friendly_team, const Pass& pass, | |||
return 0; | |||
} | |||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
you still need a check for division by 0
double rateGroundPass(const World& world, const Pass& pass, const Rectangle& zone, | ||
TbotsProto::PassingConfig passing_config); | ||
|
||
double rateChipPass(const World& world, const ChipPass& pass, const Rectangle& zone, | ||
TbotsProto::PassingConfig passing_config) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
needs docs
@@ -2,8 +2,7 @@ | |||
|
|||
|
|||
Pass::Pass(Point passer_point, Point receiver_point, double pass_speed_m_per_s) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
maybe rename this to GroundPass
* @return true if the Passes are equal and false otherwise | ||
*/ | ||
bool operator==(const Pass& other) const; | ||
friend std::ostream& operator<<(std::ostream& output_stream, const Pass& pass); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why do we need a friend
here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
left a few more comments
pass_length = length(); | ||
first_bounce_range_m = calcFirstBounceRange(); | ||
skip_area = calcSkipArea(); | ||
std::cout << "SKIP: " << skip_area << std::endl; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
delete comment
Point point_on_pass(passer_point.x() + vec_on_pass.x(), passer_point.y() + vec_on_pass.y()); | ||
|
||
Vector perpendicular = pass_direction.perpendicular().normalize(1.5); | ||
Vector perpendicular_opp = perpendicular.rotate(Angle::fromDegrees(180)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this is just the parallel and the same as pass_direction
return Polygon({ | ||
Point(passer_point.x() + perpendicular.x(), passer_point.y() + perpendicular.y()), | ||
Point(passer_point.x() + perpendicular_opp.x(), passer_point.y() + perpendicular_opp.y()), | ||
Point(point_on_pass.x() + perpendicular.x(), point_on_pass.y() + perpendicular.y()), | ||
Point(point_on_pass.x() + perpendicular_opp.x(), point_on_pass.y() + perpendicular_opp.y()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
maybe draw an ASCII art diagram for readability
|
||
virtual Duration estimateTimeToPoint(Point& point) const; | ||
|
||
friend std::ostream& operator<<(std::ostream& output_stream, const ChipPass& pass); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why do we need a friend
here?
// TEST(PassTest2, simple_getters) | ||
// { | ||
// ChipPass p(Point(0, 0), Point(2, 0)); | ||
|
||
// EXPECT_EQ(Point(0, 0), p.passerPoint()); | ||
// EXPECT_EQ(Point(2, 0), p.receiverPoint()); | ||
// std::cout << p.firstBounceRange() << std::endl; | ||
// } | ||
|
||
// TEST(PassTest3, simple_getters) | ||
// { | ||
// ChipPass p(Point(0, 0), Point(3, 0)); | ||
|
||
// EXPECT_EQ(Point(0, 0), p.passerPoint()); | ||
// EXPECT_EQ(Point(3, 0), p.receiverPoint()); | ||
// std::cout << p.firstBounceRange() << std::endl; | ||
// } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
update tests
if (pass.type() == PassType::CHIP_PASS) | ||
{ | ||
std::vector<Robot> enemy_team_not_skipped; | ||
|
||
for (auto &enemy_robot : world.enemyTeam().getAllRobots()) | ||
{ | ||
if (!reinterpret_cast<const ChipPass*>(&pass)->isSkipped(enemy_robot.position())) | ||
{ | ||
enemy_team_not_skipped.push_back(enemy_robot); | ||
} | ||
} | ||
return ratePass(world, pass, zone, Team(enemy_team_not_skipped), passing_config); | ||
} | ||
else if (pass.type() == PassType::GROUND_PASS) | ||
{ | ||
return ratePass(world, pass, zone, world.enemyTeam(), passing_config); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
maybe better for BasePass
to have a function called getIgnoredEnemyRobots(const World& world)
. I'd be happy to listen to any counter-arguments you have
|
||
/** | ||
* This class represents a Pass, a receive point with a speed | ||
*/ | ||
class Pass | ||
class Pass: public BasePass |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
maybe Pass
should be called GroundPass
@@ -22,7 +26,7 @@ | |||
* @return A value in [0,1] representing the quality of the pass, with 1 being an | |||
* ideal pass, and 0 being the worst pass possible | |||
*/ | |||
double ratePass(const World& world, const Pass& pass, const Rectangle& zone, | |||
double ratePass(const World& world, const BasePass& pass, const Rectangle& zone, const Team& enemy_team, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
docs
* @return The output stream with the string representation of the class appended | ||
*/ | ||
friend std::ostream& operator<<(std::ostream& output_stream, const Pass& pass); | ||
virtual Duration estimateTimeToPoint(Point& point) const; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
virtual Duration estimateTimeToPoint(Point& point) const; | |
Duration estimateTimeToPoint(Point& point) const = override; |
* @return true if the Passes are equal and false otherwise | ||
*/ | ||
bool operator==(const Pass& other) const; | ||
virtual PassType type() const; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
virtual PassType type() const; | |
PassType type() const = override; |
@@ -3,6 +3,5 @@ | |||
bool operator==(const PassWithRating &lhs, const PassWithRating &rhs) | |||
{ | |||
return lhs.rating == rhs.rating && | |||
lhs.pass.receiverPoint() == rhs.pass.receiverPoint() && | |||
lhs.pass.speed() == rhs.pass.speed(); | |||
lhs.pass.receiverPoint() == rhs.pass.receiverPoint(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why not compare the passes lhs.pass == rhs.pass
since we've defined ==
operators for them already
This PR is stale because it has been open for 30 days with no activity. Remove stale label or comment or this will be closed in 5 days. |
This PR is stale because it has been open for 30 days with no activity. Remove stale label or comment or this will be closed in 5 days. |
This PR was closed because it has been stalled for 5 days with no activity. |
Please fill out the following before requesting review on this PR
Description
This PR implements a new class for Chip Passes. It allows us to calculate the route of the chip pass from a start and end point.
Testing Done
Resolved Issues
Length Justification and Key Files to Review
Review Checklist
It is the reviewers responsibility to also make sure every item here has been covered
.h
file) should have a javadoc style comment at the start of them. For examples, see the functions defined inthunderbots/software/geom
. Similarly, all classes should have an associated Javadoc comment explaining the purpose of the class.TODO
(or similar) statements should either be completed or associated with a github issue