Skip to content

Commit

Permalink
Rotate Kick Development (#2295)
Browse files Browse the repository at this point in the history
* Created a new motion planner called rotation planner. It is a work in progress. This planner should theoretically only be rotation around a point (in our case, we are developing it to rotate about itself).

* tested some theory about the problem. With changing the values in points, we have pinpointed the likely problem. If the two rotation points are the current pivot point and the point (0, 0), it will rotate but also translate. If the only points in the rotation are the pivot point, it will try to plan but get stuck. This is because we try to move to the same point that we are already at, so we think it is done because planners check they are done by translation. However, we need to make this one check it is done by its orientation.

* trapezoid angle planning

* end 09/08

* updated files

* Dribble in Sim (#2287)

* dribbler is stupid

* use realism

* add realism to simoulator cli run

---------

Co-authored-by: petergarud <[email protected]>

* add ros env vars to source script (#2288)

* Update tutorial.rst (#2286)

* fixed rebase issues

* Fix Code Style On rotate-kick (#2300)

automated style fixes

Co-authored-by: Squid5678 <[email protected]>

* changes

* Fix Code Style On rotate-kick (#2303)

automated style fixes

Co-authored-by: Squid5678 <[email protected]>

* change to is angle done threshold

* removing SPDLOG stuff

* removed unnecessary line pivot changes

* gitignore

* remove log stuff

* comments

---------

Co-authored-by: Shourik Banerjee <[email protected]>
Co-authored-by: rishiso <[email protected]>
Co-authored-by: Sanat Dhanyamraju <[email protected]>
Co-authored-by: petergarud <[email protected]>
Co-authored-by: Sid Parikh <[email protected]>
Co-authored-by: Jack <[email protected]>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Squid5678 <[email protected]>
  • Loading branch information
9 people authored Nov 6, 2024
1 parent ba4465c commit 68cbf04
Show file tree
Hide file tree
Showing 14 changed files with 253 additions and 51 deletions.
1 change: 1 addition & 0 deletions soccer/src/soccer/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ set(ROBOCUP_LIB_SRC
planning/planner/path_target_path_planner.cpp
planning/planner/pivot_path_planner.cpp
planning/planner/line_pivot_path_planner.cpp
planning/planner/rotate_path_planner.cpp
planning/planner/plan_request.cpp
planning/planner/settle_path_planner.cpp
planning/planner/goalie_idle_path_planner.cpp
Expand Down
6 changes: 3 additions & 3 deletions soccer/src/soccer/control/trapezoidal_motion.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -112,9 +112,9 @@ double Trapezoidal::get_time(double distance, double path_length, double max_spe
}
}

bool trapezoidal_motion(double path_length, double max_speed, double max_acc, double time_into_lap,
double start_speed, double final_speed, double& pos_out,
double& speed_out) {
bool Trapezoidal::trapezoidal_motion(double path_length, double max_speed, double max_acc,
double time_into_lap, double start_speed, double final_speed,
double& pos_out, double& speed_out) {
// begin by assuming that there's enough time to get up to full speed
// we do this by calculating the full ramp-up and ramp-down, then seeing
// if the distance travelled is too great. If it's gone too far, this is
Expand Down
35 changes: 17 additions & 18 deletions soccer/src/soccer/control/trapezoidal_motion.hpp
Original file line number Diff line number Diff line change
@@ -1,23 +1,5 @@
#pragma once

/**
* This function evaluates a control situation using "bang-bang". The robot
* accelerates at maxAcceleration until it hits max speed, then decelerates at
* max acc to the end point.
*
* @param[in] pathLength The total distance we are trying to travel
* @param[in] timeIntoLap How long since we started moving along the trapezoid
* @param[in] finalSpeed The speed we'd like to be going at the end of the
* trapezoid
* @param[out] distOut The distance to be at at the given time
* @param[out] speedOut The speed to be at at the given time
* @return true if the trapezoid is valid at the given time, false
* otherwise
*/
bool trapezoidal_motion(double path_length, double max_speed, double max_acc,
double time_into_lap, double start_speed, double final_speed,
double& pos_out, double& speed_out);

namespace Trapezoidal {
/**
* Estimates how long it would take to move to a certain distance down a path
Expand All @@ -37,4 +19,21 @@ namespace Trapezoidal {
double get_time(double distance, double path_length, double max_speed,
double max_acc, double start_speed, double final_speed);

/**
* This function evaluates a control situation using "bang-bang". The robot
* accelerates at maxAcceleration until it hits max speed, then decelerates at
* max acc to the end point.
*
* @param[in] pathLength The total distance we are trying to travel
* @param[in] timeIntoLap How long since we started moving along the trapezoid
* @param[in] finalSpeed The speed we'd like to be going at the end of the
* trapezoid
* @param[out] distOut The distance to be at at the given time
* @param[out] speedOut The speed to be at at the given time
* @return true if the trapezoid is valid at the given time, false
* otherwise
*/
bool trapezoidal_motion(double path_length, double max_speed, double max_acc, double time_into_lap,
double start_speed, double final_speed, double& pos_out, double& speed_out);

} // namespace Trapezoidal
24 changes: 12 additions & 12 deletions soccer/src/soccer/control/trapezoidal_motion_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ bool trapezoid1(double t, double& pos_out, double& speed_out) {
double start_speed = 0;
double final_speed = 0;

bool valid = trapezoidal_motion(path_length, max_speed, max_acc, t, start_speed, final_speed,
pos_out, speed_out);
bool valid = Trapezoidal::trapezoidal_motion(path_length, max_speed, max_acc, t, start_speed,
final_speed, pos_out, speed_out);

if (valid) {
auto time = Trapezoidal::get_time(pos_out, path_length, max_speed, max_acc, start_speed,
Expand All @@ -34,8 +34,8 @@ bool trapezoid2(double t, double& pos_out, double& speed_out) {
double start_speed = 1;
double final_speed = 0;

bool valid = trapezoidal_motion(path_length, max_speed, max_acc, t, start_speed, final_speed,
pos_out, speed_out);
bool valid = Trapezoidal::trapezoidal_motion(path_length, max_speed, max_acc, t, start_speed,
final_speed, pos_out, speed_out);

if (valid) {
double time = Trapezoidal::get_time(pos_out, path_length, max_speed, max_acc, start_speed,
Expand All @@ -55,8 +55,8 @@ bool triangle1(double t, double& pos_out, double& speed_out) {
double start_speed = 0;
double final_speed = 0;

bool valid = trapezoidal_motion(path_length, max_speed, max_acc, t, start_speed, final_speed,
pos_out, speed_out);
bool valid = Trapezoidal::trapezoidal_motion(path_length, max_speed, max_acc, t, start_speed,
final_speed, pos_out, speed_out);

if (valid) {
double time = Trapezoidal::get_time(pos_out, path_length, max_speed, max_acc, start_speed,
Expand All @@ -76,8 +76,8 @@ bool triangle2(double t, double& pos_out, double& speed_out) {
double start_speed = 0;
double final_speed = 0;

bool valid = trapezoidal_motion(path_length, max_speed, max_acc, t, start_speed, final_speed,
pos_out, speed_out);
bool valid = Trapezoidal::trapezoidal_motion(path_length, max_speed, max_acc, t, start_speed,
final_speed, pos_out, speed_out);

if (valid) {
double time = Trapezoidal::get_time(pos_out, path_length, max_speed, max_acc, start_speed,
Expand All @@ -97,8 +97,8 @@ bool triangle3(double t, double& pos_out, double& speed_out) {
double start_speed = 1;
double final_speed = 1;

bool valid = trapezoidal_motion(path_length, max_speed, max_acc, t, start_speed, final_speed,
pos_out, speed_out);
bool valid = Trapezoidal::trapezoidal_motion(path_length, max_speed, max_acc, t, start_speed,
final_speed, pos_out, speed_out);

if (valid) {
double time = Trapezoidal::get_time(pos_out, path_length, max_speed, max_acc, start_speed,
Expand All @@ -118,8 +118,8 @@ bool triangle4(double t, double& pos_out, double& speed_out) {
double start_speed = 1;
double final_speed = 0;

bool valid = trapezoidal_motion(path_length, max_speed, max_acc, t, start_speed, final_speed,
pos_out, speed_out);
bool valid = Trapezoidal::trapezoidal_motion(path_length, max_speed, max_acc, t, start_speed,
final_speed, pos_out, speed_out);

if (valid) {
double time = Trapezoidal::get_time(pos_out, path_length, max_speed, max_acc, start_speed,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ LinePivotPathPlanner::State LinePivotPathPlanner::next_state(const PlanRequest&
double vel = plan_request.world_state->get_robot(true, static_cast<int>(plan_request.shell_id))
.velocity.linear()
.mag();

if (current_state_ == LINE && (target_point.dist_to(current_point) < 0.3) && (vel < 0.3) &&
(!plan_request.play_state.is_stop())) {
return PIVOT;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,10 @@ AngleFunction PathTargetPathPlanner::get_angle_function(const PlanRequest& reque
return AngleFns::face_angle(std::get<FaceAngle>(face_option).target);
}

if (std::holds_alternative<FaceTarget>(face_option)) {
return AngleFns::face_point(request.motion_command.target.position);
}

// default to facing tangent to path
// (rj_convert in motion_command.hpp also follows this default)
return AngleFns::tangent;
Expand Down
80 changes: 80 additions & 0 deletions soccer/src/soccer/planning/planner/rotate_path_planner.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
#include "rotate_path_planner.hpp"

#include <memory>
#include <vector>

#include <rj_constants/constants.hpp>
#include <rj_geometry/pose.hpp>
#include <rj_geometry/util.hpp>

#include "planning/instant.hpp"
#include "planning/planning_params.hpp"
#include "planning/primitives/angle_planning.hpp"
#include "planning/primitives/path_smoothing.hpp"
#include "planning/primitives/trapezoidal_motion.hpp"
#include "planning/primitives/velocity_profiling.hpp"
#include "planning/trajectory.hpp"

namespace planning {
using namespace rj_geometry;

Trajectory RotatePathPlanner::plan(const PlanRequest& request) {
return pivot(request); // type is Trajectory
}

bool RotatePathPlanner::is_done() const {
if (!cached_angle_change_) {
return false;
}
return abs(cached_angle_change_.value()) <
degrees_to_radians(static_cast<float>(kIsDoneAngleChangeThresh));
}

Trajectory RotatePathPlanner::pivot(const PlanRequest& request) {
const RobotInstant& start_instant = request.start;
const auto& linear_constraints = request.constraints.mot;
const auto& rotation_constraints = request.constraints.rot;

rj_geometry::ShapeSet static_obstacles;
std::vector<DynamicObstacle> dynamic_obstacles;
fill_obstacles(request, &static_obstacles, &dynamic_obstacles, false);

const MotionCommand& command = request.motion_command;

auto pivot_point =
request.world_state->get_robot(true, static_cast<int>(request.shell_id)).pose.position();
auto pivot_target = command.target.position;

double start_angle =
request.world_state->get_robot(true, static_cast<int>(request.shell_id)).pose.heading();

double target_angle = pivot_point.angle_to(pivot_target);
double angle_change = fix_angle_radians(target_angle - start_angle);

cached_angle_change_ = angle_change;

Trajectory path{};

if (abs(*cached_target_angle_ - target_angle) < degrees_to_radians(kIsDoneAngleChangeThresh)) {
if (cached_path_) {
path = cached_path_.value();
} else {
plan_angles(&path, start_instant, AngleFns::face_point(pivot_target),
request.constraints.rot);
path.stamp(RJ::now());
cached_path_ = path;
}
} else {
cached_path_.reset();
plan_angles(&path, start_instant, AngleFns::face_point(pivot_target),
request.constraints.rot);
path.stamp(RJ::now());
cached_path_ = path;
}

cached_target_angle_ = target_angle;

return path;
}

} // namespace planning
46 changes: 46 additions & 0 deletions soccer/src/soccer/planning/planner/rotate_path_planner.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
#pragma once

#include "path_planner.hpp"
#include "path_target_path_planner.hpp"

namespace planning {
/**
* Path planner that only rotates the robot about a point given.
*
* Params taken from MotionCommand:
* target.position - robot will face this point when done
* target.pivot_point - robot will pivot around this point
*/
class RotatePathPlanner : public PathPlanner {
public:
RotatePathPlanner() : PathPlanner("rotate") {}
~RotatePathPlanner() override = default;

RotatePathPlanner(RotatePathPlanner&&) noexcept = default;
RotatePathPlanner& operator=(RotatePathPlanner&&) noexcept = default;
RotatePathPlanner(const RotatePathPlanner&) = default;
RotatePathPlanner& operator=(const RotatePathPlanner&) = default;

Trajectory plan(const PlanRequest& request) override;

void reset() override {
cached_target_angle_ = std::nullopt;
cached_angle_change_ = std::nullopt;
}
[[nodiscard]] bool is_done() const override;

private:
Trajectory previous_;

std::optional<double> cached_target_angle_; // equivalent to previously recorded accorded
std::optional<double> cached_angle_change_;

std::optional<Trajectory> cached_path_;

PathTargetPathPlanner path_target_{};

Trajectory pivot(const PlanRequest& request);

static constexpr double kIsDoneAngleChangeThresh{1.0};
};
} // namespace planning
2 changes: 2 additions & 0 deletions soccer/src/soccer/planning/planner_for_robot.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#include "planning/planner/line_pivot_path_planner.hpp"
#include "planning/planner/path_target_path_planner.hpp"
#include "planning/planner/pivot_path_planner.hpp"
#include "planning/planner/rotate_path_planner.hpp"
#include "planning/planner/settle_path_planner.hpp"

namespace planning {
Expand All @@ -32,6 +33,7 @@ PlannerForRobot::PlannerForRobot(int robot_id, rclcpp::Node* node,
path_planners_[LineKickPathPlanner().name()] = std::make_unique<LineKickPathPlanner>();
path_planners_[PivotPathPlanner().name()] = std::make_unique<PivotPathPlanner>();
path_planners_[LinePivotPathPlanner().name()] = std::make_unique<LinePivotPathPlanner>();
path_planners_[RotatePathPlanner().name()] = std::make_unique<RotatePathPlanner>();
path_planners_[EscapeObstaclesPathPlanner().name()] =
std::make_unique<EscapeObstaclesPathPlanner>();

Expand Down
34 changes: 31 additions & 3 deletions soccer/src/soccer/planning/primitives/angle_planning.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,40 @@
namespace planning {

void plan_angles(Trajectory* trajectory, const RobotInstant& start_instant,
const AngleFunction& angle_function,
const RotationConstraints& /* constraints */) {
const AngleFunction& angle_function, const RotationConstraints& constraints) {
const RJ::Time start_time = start_instant.stamp;

if (trajectory->empty()) {
throw std::invalid_argument("Cannot profile angles for empty trajectory.");
trajectory->append_instant(start_instant);
double delta_angle =
angle_function(start_instant.linear_motion(), start_instant.heading(), nullptr) -
start_instant.heading();

if (delta_angle > M_PI) {
delta_angle -= 2 * M_PI;
}

if (delta_angle < -M_PI) {
delta_angle += 2 * M_PI;
}

double time = Trapezoidal::get_time(abs(delta_angle), abs(delta_angle),
constraints.max_speed, constraints.max_accel, 0, 0);

for (int i = 1; i < time / TIME_STEP; i++) {
double pos_out = 0;
double speed_out = 0;
Trapezoidal::trapezoidal_motion(abs(delta_angle), constraints.max_speed,
constraints.max_accel, i * TIME_STEP, 0, 0, pos_out,
speed_out);
pos_out *= std::signbit(delta_angle) ? -1 : 1;
trajectory->append_instant(RobotInstant{
rj_geometry::Pose{start_instant.position(), pos_out + start_instant.heading()},
rj_geometry::Twist{start_instant.linear_velocity(), speed_out},
start_instant.stamp + RJ::Seconds(i * TIME_STEP)});
}
trajectory->mark_angles_valid();
return;
}

if (!trajectory->check_time(start_time)) {
Expand Down
2 changes: 2 additions & 0 deletions soccer/src/soccer/planning/primitives/angle_planning.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include <rj_common/utils.hpp>
#include <rj_constants/constants.hpp>

#include "control/trapezoidal_motion.hpp"
#include "planning/instant.hpp"
#include "planning/robot_constraints.hpp"
#include "planning/trajectory.hpp"
Expand Down Expand Up @@ -114,4 +115,5 @@ void plan_angles(Trajectory* trajectory, const RobotInstant& start_instant,
const AngleFunction& angle,
const RotationConstraints& constraints);

constexpr double TIME_STEP = 0.001;
} // namespace planning
1 change: 0 additions & 1 deletion soccer/src/soccer/radio/sim_radio.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,6 @@ SimRadio::SimRadio(bool blue_team)
// file probably an issue with the hacky way I got param files to dynamically load
std::string localhost = "127.0.0.1";
this->get_parameter_or("interface", param_radio_interface_, localhost);
SPDLOG_INFO("SimRadio param_radio_interface_ {}", param_radio_interface_);
address_ = boost::asio::ip::make_address(param_radio_interface_).to_v4();
robot_control_endpoint_ =
ip::udp::endpoint(address_, blue_team_ ? kSimBlueCommandPort : kSimYellowCommandPort);
Expand Down
Loading

0 comments on commit 68cbf04

Please sign in to comment.