Advertisement
Trainlover08

mcl

Jan 21st, 2025 (edited)
55
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 6.61 KB | None | 0 0
  1. #include <algorithm>
  2. #include <cmath>
  3. #include <vector>
  4. #include <bitset>
  5. #include <random>
  6. //#include "../lemlib/util.hpp"
  7.  
  8. //things to try on this project in the future
  9.     //gradient decent for particle location
  10.  
  11. namespace mcl {
  12.     struct sensor {
  13.         double x, y, theta;
  14.         double distance;
  15.  
  16.         sensor(double x, double y, double theta) : x(x), y(y), theta(theta) {}
  17.     };
  18.  
  19.     class Robot {
  20.     public:
  21.         std::vector<sensor*> sensors;
  22.         std::vector<std::tuple<double>> particles;
  23.         double x, y, theta;
  24.  
  25.         Robot(std::vector<sensor*>) : sensors(std::vector<sensor*>()) {}
  26.     };
  27.  
  28.     class Particle {
  29.     public:
  30.         Particle(double x, double y, double theta, Robot* robot) : x(x), y(y), theta(theta), robot(robot) {}
  31.  
  32.         double x, y, theta, fitness;
  33.         double last_x, last_y = 0.0;
  34.         double last_theta = 0.0;
  35.         double delta_distance () {return std::hypot(x, y) - std::hypot(last_x, last_y);}
  36.         double delta_angle () {return theta - last_theta;}
  37.         Robot* robot;
  38.  
  39.         void update (double x_in, double y_in, double theta_in) {
  40.             last_x = x;
  41.             last_y = y;
  42.             last_theta = theta;
  43.  
  44.             x = x_in;
  45.             y = y_in;
  46.             theta = theta_in;
  47.         }
  48.     };
  49.  
  50.     class ParticleFilter {
  51.         ParticleFilter(Robot* robot, unsigned int points) : robot(robot), points(points) {
  52.             Particle default_particle(7200, 7200, 0.0f, robot);
  53.             std::vector<Particle> ps(points, default_particle);
  54.  
  55.             for (int i = 0; i < ps.size(); ++i) {
  56.                 mutate_particle(ps[i], 144.0f, 144.0f);
  57.             }
  58.         }
  59.  
  60.         Robot* robot;
  61.        
  62.         void predict(double velocity, double angular_velocity, double delta_t) {
  63.         for (auto& particle : particles) {
  64.             // Update theta
  65.             particle.theta += angular_velocity * delta_t;
  66.             normalize_angle(particle.theta);
  67.  
  68.             // Update position
  69.             particle.x += velocity * std::cos(particle.theta) * delta_t;
  70.             particle.y += velocity * std::sin(particle.theta) * delta_t;
  71.         }
  72.     }
  73.  
  74.         void update () {
  75.             for (int j = 0; j < ps.size(); ++j) {
  76.                 std::vector<double> sensor_predictions = calculated_intercept(ps[j]);
  77.                
  78.                 double loss = 0.0f;
  79.                 for (int i = 0; i < sensor_predictions.size(); ++i) {
  80.                     loss += calculate_loss(ps[j].robot->sensors[i]->distance, sensor_predictions[i]);
  81.                 }
  82.  
  83.                 ps[j].fitness = loss;
  84.             }
  85.  
  86.             std::vector<Particle> mc_selection = monte_carlo(ps, points / 5);
  87.  
  88.             for (int k = 0; k < mc_selection.size(); ++k) {
  89.                 for (int m = 0; m < 5; ++m) {
  90.                     ps[k * (points / 5) + m] = mc_selection[k];
  91.                 }
  92.             }
  93.  
  94.             for (int n = 0; n < mc_selection.size(); ++n) {
  95.                 mutate_particle(ps[n], 144.0f, 144.0f);
  96.             }
  97.         }
  98.  
  99.     private:
  100.         unsigned int points;
  101.         std::vector<Particle> ps;
  102.  
  103.         double compute_distance(double sensor_x, double sensor_y, double sin_theta, double cos_theta) {
  104.         std::vector<double> distances;
  105.  
  106.         // Check intersection with left wall (x = field_min)
  107.         if (cos_theta != 0) {
  108.             double distance_to_left = (field_min - sensor_x) / cos_theta;
  109.             double y_intersection = sensor_y + distance_to_left * sin_theta;
  110.             if (y_intersection >= field_min && y_intersection <= field_max && distance_to_left > 0) {
  111.                 distances.push_back(std::abs(distance_to_left));
  112.             }
  113.         }
  114.  
  115.         // Check intersection with right wall (x = field_max)
  116.         if (cos_theta != 0) {
  117.             double distance_to_right = (field_max - sensor_x) / cos_theta;
  118.             double y_intersection = sensor_y + distance_to_right * sin_theta;
  119.             if (y_intersection >= field_min && y_intersection <= field_max && distance_to_right > 0) {
  120.                 distances.push_back(std::abs(distance_to_right));
  121.             }
  122.         }
  123.  
  124.         // Check intersection with bottom wall (y = field_min)
  125.         if (sin_theta != 0) {
  126.             double distance_to_bottom = (field_min - sensor_y) / sin_theta;
  127.             double x_intersection = sensor_x + distance_to_bottom * cos_theta;
  128.             if (x_intersection >= field_min && x_intersection <= field_max && distance_to_bottom > 0) {
  129.                 distances.push_back(std::abs(distance_to_bottom));
  130.             }
  131.         }
  132.  
  133.         // Check intersection with top wall (y = field_max)
  134.         if (sin_theta != 0) {
  135.             double distance_to_top = (field_max - sensor_y) / sin_theta;
  136.             double x_intersection = sensor_x + distance_to_top * cos_theta;
  137.             if (x_intersection >= field_min && x_intersection <= field_max && distance_to_top > 0) {
  138.                 distances.push_back(std::abs(distance_to_top));
  139.             }
  140.         }
  141.  
  142.         if (!distances.empty()) {
  143.             return *std::min_element(distances.begin(), distances.end());
  144.         } else {
  145.             return std::numeric_limits<double>::infinity();
  146.         }
  147.     }
  148.  
  149.         double calculate_loss (double e_distance, double o_distance) {
  150.             return pow(fabs(o_distance - e_distance), 2);
  151.         }
  152.  
  153.         void resample() {
  154.         // Resample particles based on weights
  155.         std::vector<Particle> new_particles;
  156.         std::vector<double> weights;
  157.         for (const auto& particle : particles) {
  158.             weights.push_back(particle.weight);
  159.         }
  160.  
  161.         std::discrete_distribution<size_t> distribution(weights.begin(), weights.end());
  162.         std::mt19937 gen(std::random_device{}());
  163.  
  164.         for (size_t i = 0; i < num_particles; ++i) {
  165.             new_particles.push_back(particles[distribution(gen)]);
  166.         }
  167.  
  168.         particles = std::move(new_particles);
  169.     }
  170.        
  171.         void update_weights(double sensor_x, double sensor_y, double sensor_theta) {
  172.         // Precompute sin and cos for the sensor's angle
  173.         double sin_theta = std::sin(sensor_theta);
  174.         double cos_theta = std::cos(sensor_theta);
  175.  
  176.         for (auto& particle : particles) {
  177.             double distance = compute_distance(sensor_x, sensor_y, sin_theta, cos_theta);
  178.             particle.weight = calculate_loss();
  179.         }
  180.     }
  181.        
  182.         void my_clean_rads (double angle) {
  183.            while (angle < 0) angle += 2 * M_PI;
  184.             while (angle >= 2 * M_PI) angle -= 2 * M_PI;
  185.         }
  186.     };
  187.     // need completely new filter class
  188. };
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement