tripweather

package
v0.40.21 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Nov 1, 2026 License: MIT Imports: 2 Imported by: 0

Documentation

Overview

Package tripweather corrects a Rivian trip plan's per-waypoint SoC curve for weather conditions Rivian's planner doesn't see. The gateway models pack + base efficiency from the account-side vehicle config, but its `planTripWithMultiStopV2` operation accepts no weather inputs — so a cold day or a strong headwind silently turns a "comfortable 5% arrival margin" plan into a stranded one.

Adjust takes the plan's waypoint sequence plus a parallel slice of per-leg weather snapshots, applies an energy multiplier per leg, and re-runs the cumulative SoC subtraction. The output mirrors the input shape (corrected ArrivalSoC per waypoint) plus a top-level flag for whether the corrected final arrival is below the user's target floor.

The multiplier model lives here as pure functions so it can be unit-tested without booting Postgres or hitting Open-Meteo. See docs/ROADMAP.md "Weather-aware range adjustment" for what's in v1 and what's deferred.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func Multiplier

func Multiplier(s *weather.Snapshot) float64

Multiplier returns the per-leg energy multiplier for the given weather snapshot. A return value of 1.0 means "no adjustment"; 1.15 means "this leg needs 15% more energy than Rivian planned".

Model (see docs/ROADMAP.md for the underlying empirical sources):

cold:    1 + 0.008 * max(0, 21 - apparent_temp_C)   // 30% loss at -7C
heat:    1 + 0.004 * max(0, apparent_temp_C - 27)   // A/C draw
wind:    1 + 0.012 * clamp(headwind_kph, -30, 30)   // drag, symmetric
wet:     × 1.05 when precip_mm > 0.5                // coarse on/off

Factors are multiplicative so a cold + headwind + wet leg compounds. nil snapshot returns 1.0.

Types

type Adjustment

type Adjustment struct {
	AdjustedArrivalSoC []float64
	Multipliers        []float64
	// BelowTarget is true when the final corrected arrival SoC is
	// below TargetArrivalSoCPercent. Caller renders the warning chip
	// based on this single boolean — keeps the SPA decision local.
	BelowTarget bool
	// FinalArrivalSoC is a convenience alias for the last entry of
	// AdjustedArrivalSoC so callers don't have to index.
	FinalArrivalSoC float64
}

Adjustment is the output. AdjustedArrivalSoC[i] is the corrected SoC at waypoint i, in percent. Multipliers[i] is the leg multiplier for the leg ending at waypoint i+1 (so Multipliers has len == len-1 of the waypoint slice). For the origin waypoint, AdjustedArrivalSoC equals the input StartingSoC.

func Adjust

func Adjust(startingSoC float64, waypointArrivalSoC []float64, legs []Leg, targetArrivalSoC, baseMultiplier float64) *Adjustment

Adjust re-runs the cumulative SoC subtraction with per-leg multipliers applied. startingSoC + waypointArrivalSoC describe the uncorrected plan; len(legs) must equal len(waypointArrivalSoC) (one leg per arrival), and waypointArrivalSoC[i] is the SoC Rivian forecast at waypoint i+1 (origin is implied).

targetArrivalSoC is the user's floor; the returned BelowTarget is true when the corrected final arrival is below it.

baseMultiplier is a trip-wide multiplier applied to every leg's consumption on top of the per-leg weather multiplier. Pass 1.0 when there's no profile correction. Profile contribution (wheels, tires, accessories, payload) comes through here from internal/tripprofile so the pipeline stays single-pass.

type Leg

type Leg struct {
	Weather *weather.Snapshot
}

Leg is the input shape for one driving segment between two waypoints. Multiplier is computed from Weather; callers may pass a nil Weather to signal "no snapshot available" — that leg gets a pass-through multiplier of 1.0.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL