/*************************************************************************** file : traffic5.h created : September 2026 copyright : (C) 2026 by Bernhard Wymann email : berniw@bluewin.ch ***************************************************************************/ /* This program is free software; you can redistribute it and/or modify it * under the GNU General Public License, version 2 or (at your option) any * later version. Distributed WITHOUT ANY WARRANTY, including MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See . */ #ifndef _TUTORIAL5_TRAFFIC_H_ #define _TUTORIAL5_TRAFFIC_H_ #include #include "speed4.h" #include "steering4.h" struct TrafficCar { tCarElt* car = nullptr; double along = 0.0; // signed center distance from our car, metres double lateral = 0.0; // center offset from road centerline, positive left double speed = 0.0; // world velocity projected along the road, m/s double lateralSpeed = 0.0; // world velocity projected onto the left normal, m/s double halfLength = 0.0; // footprint projection onto the road tangent double halfWidth = 0.0; // footprint projection onto the left normal }; double wrappedDistance(double distance, double length); TrafficCar describeCar(tCarElt* car); double approach(double value, double target, double maximumChange); bool offsetTarget(tCarElt* car, double offset, int count, double length, Vector2& target); void applySpeedTarget(SpeedDriver& driver, tCarElt* car, double target, double brakeLimit); struct TrafficPlanner { enum class Mode { Cruising, Following, Passing, Returning, Holding }; Mode mode = Mode::Cruising; std::vector opponents; TrafficCar self; tCarElt* passingCar = nullptr; double offset = 0.0; double passOffset = 0.0; double holdOffset = 0.0; double holdUntil = 0.0; double previousTime = 0.0; double speedLimit = 0.0; bool nearby = false; bool emergency = false; bool corridorAvailable = true; // geometric check, not a swept-path guarantee void reset(double time); void observe(tCarElt* car, tSituation* situation, double trackLength); bool corridorFree(double target, const tCarElt* except, double seconds) const; void lateralBounds(double roadHalfWidth, double& low, double& high) const; void plan(double time, double freeSpeed, double roadHalfWidth, double currentHalfWidth = -1.0, double narrowingDistance = 0.0); void drive(SpeedDriver& driver, tCarElt* car, tSituation* situation); }; #endif