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

Implemented Chip Pass Modeling #3229

Draft
wants to merge 3 commits into
base: master
Choose a base branch
from

Conversation

sauravbanna
Copy link
Contributor

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

  • Function & Class comments: All function definitions (usually in the .h file) should have a javadoc style comment at the start of them. For examples, see the functions defined in thunderbots/software/geom. Similarly, all classes should have an associated Javadoc comment explaining the purpose of the class.
  • Remove all commented out code
  • Remove extra print statements: for example, those just used for testing
  • Resolve all TODO's: All TODO (or similar) statements should either be completed or associated with a github issue

#include "software/logger/logger.h"
#include "proto/message_translation/tbots_protobuf.h"

// #include "software/logger/logger.h"
Copy link
Contributor

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

Comment on lines 89 to 91
LOG(PLOTJUGGLER) << *createPlotJugglerValue({
{"dist", std::sqrt(pow(p.x() - 0, 2) + pow(p.y() - 0, 2))},
{"z", p.z()}
Copy link
Contributor

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());
Copy link
Contributor

Choose a reason for hiding this comment

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

.22()?

Comment on lines 87 to 89
LOG(PLOTJUGGLER) << *createPlotJugglerValue({
{"speed", chip_speed}
});
Copy link
Contributor

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

Comment on lines +41 to +49
// 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);
// }};
Copy link
Contributor

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

Comment on lines 62 to +83
// 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())
));
Copy link
Contributor

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));
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 std::sqrt(std::pow(receiverPoint().x() - passerPoint().x(), 2) + std::pow(receiverPoint().y() - passerPoint().y(), 2));
return (receiverPoint() - passerPoint()).length()

Comment on lines 37 to 43
// std::ostream& printHelper(std::ostream& output_stream, const BasePass& pass)
// {
// output_stream << "Pass from " << pass.passer_point
// << " to: " << pass.receiver_point;

// return output_stream;
// }
Copy link
Contributor

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
Copy link
Contributor

Choose a reason for hiding this comment

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

missing class docs

Comment on lines +64 to +67
virtual Duration estimatePassDuration() const
{
return Duration::fromSeconds(0);
}
Copy link
Contributor

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?

Comment on lines 85 to 92
/**
// * 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);
Copy link
Contributor

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;
Copy link
Contributor

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)
Copy link
Contributor

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;
Copy link
Contributor

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));
Copy link
Contributor

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));
Copy link
Contributor

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);
Copy link
Contributor

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;
Copy link
Contributor

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
Copy link
Contributor

Choose a reason for hiding this comment

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

missing docs

Copy link
Contributor

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;
Copy link
Contributor

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;
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
virtual Duration estimatePassDuration() const;
Duration estimatePassDuration() const = override;

Copy link
Contributor

@itsarune itsarune left a 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

@itsarune
Copy link
Contributor

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) *
Copy link
Contributor

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?

return Duration::fromSeconds(0);
}

virtual Duration estimateTimeToPoint(Point& point) const;
Copy link
Contributor

Choose a reason for hiding this comment

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

needs docs

Comment on lines +17 to +18
// if we cover more than 90% of the pass, stop calculating
while(length_to_go >= pass_length * 0.2)
Copy link
Contributor

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);
Copy link
Contributor

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
Copy link
Contributor

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();
Copy link
Contributor

Choose a reason for hiding this comment

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

needs docs

Comment on lines 32 to 36
double calcFirstBounceRange();

double getBounceHeightFromDistanceTraveled(double distance_traveled);

double getBounceRangeFromBounceHeight(double bounce_height);
Copy link
Contributor

Choose a reason for hiding this comment

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

needs docs

Comment on lines 16 to 26
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);
}
Copy link
Contributor

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);
Copy link
Contributor

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;
}

Copy link
Contributor

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

Comment on lines 14 to 18
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)
Copy link
Contributor

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)
Copy link
Contributor

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);
Copy link
Contributor

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?

Copy link
Contributor

@itsarune itsarune left a 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

@nimazareian nimazareian added the Robocup-2024 High priority for Rbocup 2024 label Jul 9, 2024
pass_length = length();
first_bounce_range_m = calcFirstBounceRange();
skip_area = calcSkipArea();
std::cout << "SKIP: " << skip_area << std::endl;
Copy link
Contributor

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));
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 just the parallel and the same as pass_direction

Comment on lines +41 to +45
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())
Copy link
Contributor

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);
Copy link
Contributor

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?

Comment on lines +14 to +30
// 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;
// }
Copy link
Contributor

Choose a reason for hiding this comment

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

update tests

Comment on lines +19 to +35
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);
}
Copy link
Contributor

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
Copy link
Contributor

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,
Copy link
Contributor

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;
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
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;
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
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();
Copy link
Contributor

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

Copy link
Contributor

github-actions bot commented Sep 3, 2024

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.

@github-actions github-actions bot added the Stale Inactive pull requests label Sep 3, 2024
@itsarune itsarune removed the Stale Inactive pull requests label Sep 28, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Robocup-2024 High priority for Rbocup 2024
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants