# Simulator (`assignments::three::Simulator`) The `Simulator` class provides a flexible time-based value generation engine that supports multiple interpolation types. It is used by both the IMU and Wheel data simulator nodes to generate configurable sensor data patterns. ## Implementation Details **Namespace**: `assignments::three` **Header**: `simulator/Simulator.hpp` ### Data Structures **SimType Enum** ```cpp enum class SimType { CONSTANT, // y = c (constant value) LINEAR, // y = y0 + (y1-y0) * (t-t0)/(t1-t0) QUADRATIC // Lagrange interpolation through 3 points }; ``` **IntervalConfig Struct** ```cpp struct IntervalConfig { SimType type; // Interpolation type double t_start; // Interval start time double t_end; // Interval end time double y_start; // Start value double y_end; // End value double t_mid; // Mid-point time (quadratic only) double y_mid; // Mid-point value (quadratic only) }; ``` ### Constructor ```cpp Simulator(rclcpp::Node* node, const std::vector& objects) ``` - Takes a ROS2 node pointer for parameter access - Takes a list of object/channel names to configure - Loads interval configurations from ROS2 parameters - Validates intervals for overlaps (throws `std::runtime_error` if detected) ## Core Functionality **`double get_object_value(const std::string& object, double t)`** - Returns the simulated value for a given object at time `t` - If `t` is within an interval, computes the interpolated value - If `t` is after all intervals, holds the last interval's end value - If `t` is before all intervals, returns 0.0 - If object doesn't exist, returns 0.0 **`double compute_value(double t, const IntervalConfig& interval)`** (private) - Computes the interpolated value based on interval type: - **CONSTANT**: Returns `y_start` - **LINEAR**: Lagrange interpolation between 2 points - **QUADRATIC**: Lagrange interpolation through 3 points **`void load_intervals(rclcpp::Node* node, const std::vector& objects)`** (private) - Declares and loads parameters for each object - Validates that intervals don't overlap - Respects `max_intervals` limit ## Parameter Configuration For each object, the following parameters are used: | Parameter | Type | Description | |-----------|------|-------------| | `max_intervals` | int | Global maximum intervals per object | | `.num_intervals` | int | Number of intervals for this object | | `.interval_.type` | string | "constant", "linear", or "quadratic" | | `.interval_.t_start` | double | Interval start time | | `.interval_.t_end` | double | Interval end time | | `.interval_.y_start` | double | Value at start | | `.interval_.y_end` | double | Value at end | | `.interval_.t_mid` | double | Mid-point time (quadratic) | | `.interval_.y_mid` | double | Mid-point value (quadratic) | ## Example Configuration ```yaml # Constant acceleration of 5.0 m/s² from t=0 to t=10 linear_x: num_intervals: 1 interval_0: type: "constant" t_start: 0.0 t_end: 10.0 y_start: 5.0 # Linear ramp from 0 to 10 over 5 seconds wheel_fl: num_intervals: 1 interval_0: type: "linear" t_start: 0.0 t_end: 5.0 y_start: 0.0 y_end: 10.0 # Quadratic curve peaking at t=5 angular_z: num_intervals: 1 interval_0: type: "quadratic" t_start: 0.0 t_end: 10.0 y_start: 0.0 y_end: 0.0 t_mid: 5.0 y_mid: 3.14 ``` ## Error Handling - Throws `std::runtime_error` if overlapping intervals are detected for the same object - Logs warning for unknown interval types, defaults to CONSTANT - Returns 0.0 for non-existent objects (graceful degradation)