Generated banner for Matlab Fit Tire Model
Generated logo for Matlab Fit Tire Model

Matlab Fit Tire Model

MathWorksOfficialCreated by MathWorks

  • Skill
  • Workflow
  • Software development
  • BSD-2-Clause
  • No issues found

From the author

Fit a tire model (Magic Formula 6.2/5.2/5.1, Dugoff, or Fiala) to measured tire force and moment data using the Vehicle Dynamics Blockset Extended Tire Features API (tireData.import, tireModel.new, tireModel.fit, tireModel.export). Use when fitting, parameterizing, or calibrating a tire model from tire measurement data (TYDEX, Calspan, MTS, or text/CSV from any test source), creating a .tir file, or building a Magic Formula tire model from test data. Also use for the individual steps: importing TYDEX, Calspan, MTS, or CSV tire data (file extensions `.tdx` for TYDEX; `.data`, `.tim`, `.rsp` for MTS; any other extension read as text) into a tireData object, exporting a tire model to .tir, inspecting, smoothing, cropping, or plotting tire measurement data or a model's response, or converting a fitted model to another type.
— the description by MathWorks

AutoGineer summary

Written by AutoGineer from the skill’s own files, not by the author

This skill provides a structured workflow for fitting tire models—including Magic Formula, Dugoff, and Fiala—to measured tire force and moment data. It leverages the Vehicle Dynamics Blockset Extended Tire Features API to handle data import, model creation, parameter fitting, and export. The workflow emphasizes data-driven routing, dependency-aware fitting, and comprehensive reporting to ensure accurate model parameterization from various test sources like TYDEX, Calspan, and MTS.

What it does

  • Imports tire measurement data from formats like TYDEX, Calspan, MTS, and CSV.
  • Classifies channel content to route data correctly to specific fit types.
  • Fits tire models in a dependency-ordered sequence to ensure parameter consistency.
  • Exports fitted models to standard .tir files for use in simulation.
  • Provides diagnostic reporting on fit status, including inert or collinear parameters.
  • Supports advanced fit tuning via weights, parameter constraints, and solver options.

When to use it

  • When you need to create a parameterized tire model from raw test data.
  • When you need to convert or re-fit an existing tire model to a different type.
  • When you need to perform individual tasks like smoothing, cropping, or plotting tire data.
  • When you need to export a model to a .tir file for use in vehicle dynamics simulations.

Advantages

  • Ensures consistent model fitting by following dependency-ordered schedules.
  • Automates the handling of units and coordinate systems for recognized file formats.
  • Provides clear visibility into which parameters were fitted versus left at baseline.
  • Reduces manual error by querying valid model and fit types rather than hardcoding them.

Usage examples

“Fit a Magic Formula 6.2 tire model using my TYDEX data file.”
The agent will verify the required toolboxes, import the data, classify the channels, perform the fit in the correct dependency order, and provide a report on the fitted parameters.
“How do I export my fitted tire model to a .tir file?”
The agent will guide you through using the export method, ensuring the correct file extension is used and checking for existing files to prevent accidental overwrites.

Install

  1. Download the skill as a ZIP:

    https://autogineer.com/agent-skills/matlab/matlab-fit-tire-model/download
  2. Unzip it into the cross-client skills folder of your project:

    mkdir -p .agents/skills && unzip matlab-fit-tire-model.zip -d .agents/skills

Documentation by MathWorks

Fit a Tire Model from Tire Measurement Data

Fit a tire model from tire measurement data using the Vehicle Dynamics Blockset Extended Tire Features API. The API supplies the fitter, so the work is three judgments it does not enforce: query the valid fit types and their order rather than hardcoding them, route data to each fit type by channel content, and report which fit types were left at defaults.

When to Use

  • You have tire measurement data (in TYDEX, Calspan, MTS, or text/CSV form, from any test source) and want a fitted tire model or a .tir file. This full fitting workflow is the primary use.

  • You want a single step of that workflow against tire measurement data or a tire model: import to a tireData object; export a model to .tir; inspect, summarize, crop, or smooth measurement data; plot measurement data or a model's response; convert a fitted model to another type. See Partial invocation below.

  • Target model type is Magic Formula 6.2 (the worked example), MF5.2, MF5.1, Dugoff, or Fiala.

When NOT to Use

  • Designing an FIR or IIR signal filter: use matlab-design-digital-filter. This skill's filter() is channel smoothing during fitting, not filter design.

  • Cleaning generic (non-tire) signals, or building signal datastores and labels for ML: use matlab-prepare-signal-data. Smoothing, cropping, or downsampling a tireData object stays here.

  • Specifying or planning a plant or tire-subsystem architecture for closed-loop simulation: use specifying-plant-models (Simulink Agentic Toolkit).

  • Adding, wiring, or restructuring blocks in a model: use building-simulink-models (Simulink Agentic Toolkit). This skill only writes fitted parameters into an existing tire block via set.

  • Simulating a model containing the tire block: use simulating-simulink-models (Simulink Agentic Toolkit). Inspecting a fit you just ran is in scope.

  • Grabbing a reference or production tire to simulate against (tireModel.builtin); it is ruled out as a fitting seed.

  • Deriving or hand-coding Magic Formula coefficients yourself; the API supplies the fitter.

  • The Step 0 prerequisite gate fails (Extended Tire Features support package or Optimization Toolbox missing): the user runs matlab-install-products or matlab-list-products, not you.

Workflow

The full fit is a step-ordered sequence. Steps 0 through 9 run in order. Load references/fit-type-data-requirements.md when you reach Step 2 (routing) or Step 5 (fitting): it holds the per-fit-type data-requirements table, the channel-content routing table, and the Dimensions geometry-property details.

0. Recognize the path and check prerequisites

Gate on class availability, not detect_matlab_toolboxes (misses support packages) or matlabshared.supportpkg.getInstalled. Confirm the methods are present so a same-named custom class cannot pass:

if exist('tireModel','class') ~= 8 || ...
        ~all(ismember(["new" "fit" "export"], ...
            string({meta.class.fromName('tireModel').MethodList.Name})))
    error("Extended Tire Features support package not found. Install it from Add-Ons.");
end

If either gate fails, report it, stop, and tell the user to install the missing product; never install it yourself. Do not hand-roll Magic Formula. fit requires Optimization Toolbox (new does not). Check install and license separately. Nothing overrides an empty ver("optim"): which('fmincon') resolves either way, and a license check passes for a licensed-but-absent product.

if isempty(ver("optim"))
    error("Optimization Toolbox not installed.");
elseif ~license('test','optimization_toolbox')
    error("Optimization Toolbox unlicensed.");
end
1. Import to a tireData array

obj = tireData.import(filepath, ...) takes a string scalar or array and returns a tireData array, one element per file. Recognized formats (TYDEX, MTS, Calspan) auto-convert every channel to canonical SI units and import as ISO coordinates, which is what Magic Formula expects. So after a recognized-format import, angles are in radians, not degrees, and no coordinate fiddling or manual slip-angle negation is needed. Import options are extension-gated (TYDEX honors only DatetimeFormat/Locale; MTS adds VariableAlias; text/CSV passes all options through).

On the text/CSV path, or when hand-authoring a tireData property from another source, you supply the units and coordinates: provide radians, N, Nm, and Pa, or designate the file's units with VariableUnits, VariableUnitsLine, or HeaderUnits, and pass CoordinateSystem= (or convert after import with coordinateTransform(obj, "ISO")).

2. Inspect content and classify each channel (routing foundation, C2)

The routing decision is made here and carried to Step 5. For each imported object, classify alpha, kappa, Fz (and gamma/V where relevant) as constant, swept, or stepped, using public methods only. summaryTable gives one per-object statistic per channel: DataStat="range" for the swept-versus-held call (large span = swept, small = held), DataStat="mean" for each channel's level. Read the two together: the mean is a meaningful level only for a channel the range shows is held; for a swept channel the mean is just the sweep's center. Narrow VariableNames= to Filename, the channels you route on, and any response channel whose presence you test; it defaults to every tireData property, so an unnarrowed table is over eighty columns wide with filepaths and comments in it.

routeVars = ["Filename" "alpha" "kappa" "Fz" "gamma" "V"];
spans = summaryTable(td, VariableNames=routeVars, DataStat="range");
means = summaryTable(td, VariableNames=routeVars, DataStat="mean");

split(obj, channel) returns one element per discrete level: more than one means bundled fixed-level cases; exactly one emits the expected warning Unable to identify splits in data ("one level," not an error). Splitting is optional: fit accepts a multi-condition object directly, so split only when you need per-sweep processing (filter smoothing, mean hold), never merely to fit. Never assume a channel's role: Fz swept is a load sweep (RL/Re), Fz stepped is bundled load cases, Fz constant is a single-load test. Determine it per object. The pure-versus-combined split is on mean alpha, not alpha range (a naive alpha-range threshold misclassifies). Angles are radians (Step 1).

3. Choose or honor the model type (query the list, C1 philosophy)

Valid types come from vdyntire.tiremodels.modelTypes(). The set is version-dependent, so query it and never embed a hardcoded list; new also accepts "MF" as an alias for MF62. Honor the user's stated type: validate it against modelTypes() and use it, do not silently substitute. The type drives the whole schedule (Fiala and Dugoff have no Nominal, no combined, and no Re/relaxation/contact-patch fits), so never replay the MF62 schedule on another type. If the user names no type, stop before Step 4: list the types from modelTypes() and end your turn asking which to use. If the user named the intended simulation, you may say which types suit it, but still ask. A file format or an intended use does not name a type; every supported type exports to .tir. If the user names an unsupported model (for example FTire, MF-Swift, CDTire, or another third-party designation), use your own tire-model knowledge to propose the nearest supported alternative under three guardrails: the final choice must be a member of modelTypes() (validate the proposal live), name the gap honestly and never silently swap, and stop to confirm, as above. For a fundamentally different model class (transient, thermal, high-frequency), it is fine to answer that this workflow cannot produce that model.

4. Query the valid fit types and order (C1), never hardcode

Normal path: vdyntire.tiremodels.fitTypes(ModelType=<type>) returns the fittable types in a valid schedule order, as a column string array, so loop by index. Iterate them in returned order and fit each type the data supports; Nominal-upstream falls out naturally because fitTypes lists it first for Magic Formula and omits it for Fiala/Dugoff. fitTypeDependency is the secondary, diagnostic tool: [deps, params] = tm.fitTypeDependency(<type>) returns the transitive closure of upstream prerequisites, ordered dependencies-first, excluding the type itself. Use it only to validate or repair a user-forced custom order, and to reason about what becomes unfittable when a prerequisite is skipped for lack of data. Take dependencies from it rather than from a documentation table. Do not try/catch-probe a type list; fitTypeDependency errors on a type the model lacks, so enumerate with fitTypes instead.

5. Route by content (C2); route it yourself, fit will not

The Tire Manager app auto-assigns data to fit types with an internal inspector; the command-line fit API does not. fit checks only channel presence and warns on wrong-condition data, then concatenates everything and fits. So handing every file to every fit type biases the fits with wrong-condition data and emits only warnings. Route by selecting the objects whose Step-2 classification matches each fit type's row in references/fit-type-data-requirements.md, then pass that object or array to fit. Never route by filename or subfolder. Nominal, Limits, and Dimensions consume ALL data, not a swept subset. crop trims unusable rows within an object; filter, mean, and downsample are per-object processing (smoothing, holding, decimation), never row selection.

6. Seed the model (new or import; builtin ruled out)

Fit from scratch with tireModel.new(<type>): physically reasonable nonzero defaults, ready to fit. Fit a variant or re-fit an existing tire with tireModel.import(<parent>) (a .tir or .mat path, an extensionless TIR file, or a parameter struct): it starts the optimizer near the answer, so fit only the types the variant changed. When seeding via import, the model type comes from the file, so query fitTypes against the imported model's actual type and surface any disagreement with the requested type. The C3 baseline also changes: untouched parameters retain the imported parent's coefficients rather than new defaults, and Step 9 must name which. tireModel.builtin is not a seed (fit errors on a builtin model); it is only for grabbing a named reference tire to simulate against.

Prefer fitting Nominal, Limits, and Dimensions over hand-setting model coefficients: never hand-set FNOMIN, dimensions, or limits as model properties. Legitimate manual setting is on the tireData object (for example a dimension property the headers omit), never on the model coefficients a fit should set. Dimensions fits from the tireData geometry properties, which TYDEX import populates from the file header. If they are empty, you may ask the user for the tire size and assign the five properties directly, minding the mixed canonical units in the reference file; if the user cannot supply it, leave the parameters at the seed value and report it (C3) rather than fabricating dimensions. TireSize is bookkeeping only and does not gate Dimensions.

7. Fit in dependency order, inspect each result (C1 runtime + C2 safety net)

The signature is [fitObj, diffTable, errorStat, optimOutput, H] = fit(obj, Data, FitType, options), where obj is the seed model, Data is the routed subset from Step 5, and FitType is a single type string. The normal path passes no options. fit returns a NEW model and does not mutate in place, so reassign and thread the model through the schedule (mdl = fit(mdl, subset, type), once per supported fit type in fitTypes order, as in the worked example). Discarding the return, or re-seeding from new each step, makes the dependency order meaningless because nothing accumulates. Nominal, Limits, and Dimensions short-circuit the optimizer and return early with empty errorStat/optimOutput/H, so inspect their diffTable only. Surface every dataChecks and checkLimits warning rather than swallowing it: they signal sloppy Step-5 routing. fit errors only when a required channel is entirely absent, so check the routed subset for that type's required channels first (references/fit-type-data-requirements.md) and record a skipped type in the Step 9 report rather than calling fit to surface the error.

After each fit, read diffTable.Status when present (Optimized, Inert, or Collinear; report Inert and Collinear parameters in Step 9, naming them from diffTable.Parameter, never from diffTable.Properties.RowNames, which is empty) and errorStat.Final, the whole-fit in-sample RMSE (not validation). Judge a fit by the size of the .Initial-to-.Final drop and the overlay plot, not by whether the solver hit its own convergence flag: tire fits routinely stop on MaxFunEvals at a residual floor, which is normal, so do not chase the flag by raising the limit, switching solvers, or re-seeding. Verify from the numbers, not a figure; the MATLAB desktop is visible, so do not pop a plot unless asked (offer it, and pass PlotFit=true to overlay each fit). Load references/fit-diagnostics.md for the output-struct fields and these diagnostics in detail.

8. Deliver the model, by intent

Save to a portable standard file (recommended): export(mdl, "path/fitted.tir"). It has no return value. A .tir is consumable by Vehicle Dynamics Blockset tire blocks and by third-party Magic Formula compatible software. The format is chosen by extension. export errors on an existing file, so pass overwrite=true deliberately or pick a fresh name. To use the model immediately in a model, set(mdl, blockPath, ...) pushes the fitted parameters into a supported Vehicle Dynamics Blockset tire block. Two consistency gates apply: the target must be a supported tire block, and the block's configured model type must match mdl.ModelType. set operates by side effect on an open model and returns nothing. Do not hardcode the supported-block list.

9. Report scope completely, up front (C3)

Report at the fit-type level using public accessors only. Build the report from the supported set fitTypes(ModelType) minus the types you fit, which gives the not-run set. State each not-run type and that its parameters remain at the baseline. For the types you did run, use diffTable.Status (when the column is present, per the Step 7 existence check) to disclose Inert and Collinear parameters, frozen before the fit and left at the baseline; where absent, build the report from the fit-type set alone. Name which baseline the untouched parameters carry: new defaults, or the imported parent's coefficients (Step 6). Report the ENTIRE not-run set, not just the one glaring omission. Do not over-claim: in-sample residuals are not validation plots, errorStat.Final is in-sample RMSE, and the model is not "ready for use" or "validated." Neither export nor set checks completeness, so this report is the only thing between a silently partial .tir and the user.

Inspect by plotting (supplementary)

Plotting is never required by the fit, but a human review often wants it. Offer it rather than producing a figure unrequested, and use the shipped methods (tireData.plot, tireModel.plot) rather than pulling channels off the object and calling generic plot, which discards the metadata-derived labels and units and invites fabricated axis or coordinate-frame claims. Load references/inspect-by-plotting.md for the options, arguments, and examples.

Advanced: fine-tune the fit on user request

Never change the default fit on your own initiative to chase a lower in-sample residual. A user may ask to steer the fit (Weight, Parameters, FixedParameters, LowerBounds/UpperBounds, Solver, optimoptions); each is a supported way to do so, applied only when asked, and a weighted or steered fit must be disclosed in the Step 9 report. Load references/advanced-fit-tuning.md for each option and its guardrails before using any of them.

Partial invocation

When the user asks for a single step (just import, just export, just plot, or convert), do that step correctly, mention that the fuller fitting workflow and the Tire Manager app (a GUI alternative that auto-routes data) exist, then stop. Do not force the end-to-end workflow onto a narrow request. The Step 9 scope report applies only when the user actually fits.

Adjacent operation: convert a fitted model to another type

Not a step in the linear schedule. Offer it when the user already has a fitted model and wants it re-expressed as another type. convert(mdl, TargetType) requires Optimization Toolbox and is approximate and lossy on downgrades (MF6.2 to Fiala drops combined, relaxation, and pressure behavior), so disclose the lossiness as Step 9 discloses unfit types and never present a downgraded conversion as equivalent to the source. Load references/convert-operation.md for the signature, the MF51-to-MF52 fast path, the guardrails, and delivery via Steps 8 and 9.

Key Functions

All ship with the Vehicle Dynamics Blockset Extended Tire Features support package. The model-type and fit-type SETS are release-dependent, which is why the workflow queries them (modelTypes, fitTypes) rather than asserting a fixed list. Available From flags the one function newer than the R2025a support-package floor.

FunctionPurposeAvailable From
tireData.importImport measurement files to a tireData array, one element per file
summaryTablePer-channel range/mean statistics, the classification foundation
split / cropSeparate into discrete levels / trim unusable rows within an object
coordinateTransformConvert a tireData object to a coordinate system (for example "ISO")
tireData.plotPlot measured channels; DataVariableNames picks the axes, ColorBy groups by condition
vdyntire.tiremodels.modelTypesQuery the valid model types
vdyntire.tiremodels.fitTypesQuery the fittable types and their schedule order for a model type
tireModel.new / tireModel.importSeed a model from defaults / from a parent file or struct
tireModel.fitTypeDependencyUpstream prerequisites for a fit type (diagnostic, not enumeration)R2026a
tireModel.fitFit one fit type; returns a NEW model plus diagnostics
tireModel.export / tireModel.setWrite a .tir / push parameters onto a VDB tire block
tireModel.convertRe-express a fitted model as another type (adjacent operation)
tireModel.plotPlot a model's response, driven by a tireData or by specified conditions

Patterns

Load references/worked-example.md for concrete code putting the three judgments together end to end: querying fitTypes and iterating in returned order, classifying channel content with summaryTable to select each fit type's subset, threading mdl = fit(mdl, ...) through the schedule, and building the not-run set with setdiff for the scope report.

Conventions

Always: query modelTypes/fitTypes and iterate fitTypes in returned order (never embed a list); route each fit type by channel content (Step 2 plus the reference table); reassign mdl = fit(mdl, ...) every step so fits accumulate in dependency order; report the complete not-run set up front, naming the baseline (Step 9); gate on class availability and Optimization Toolbox install plus license before fitting (Step 0).

Ask first: when the user names no model type, stop and ask (Step 3); before substituting a nearest supported type for an unsupported one (validate it against modelTypes); before assigning tireData geometry properties from a user-supplied tire size the data lacks; before overwriting an existing .tir (pass overwrite=true deliberately).

Never:

  • Hand-roll Magic Formula or hand-write a .tir when the API is available.

  • Call vdyntire.internal.* helpers directly; reach behavior through public methods.

  • Seed a fit from tireModel.builtin.

  • Use filter, mean, or downsample to select rows; they are per-object processing.

  • Label in-sample residuals as validation, or call a partial model "ready" or "validated."

Common Mistakes

Load references/common-mistakes.md for the failure-mode lookup table, each row giving a mistake, why it is wrong, and the correct approach.


Copyright 2026 The MathWorks, Inc.


Files

references/fit-diagnostics.md

Fit Diagnostics: Reading fit Outputs Correctly

Load this at Step 7 when inspecting the results of a fit call.

The output structs and where each field lives

The full signature is:

[fitObj, diffTable, errorStat, optimOutput, H] = fit(obj, Data, FitType, options);
  • errorStat carries the whole-fit RMSE in scalar .Initial and .Final fields (before and after the fit). .Final < .Initial shows improvement, but this is in-sample RMSE, not validation. The scalar RMSE lives on errorStat alone. Do not look for it on diffTable: diffTable does have Initial Value and Final Value columns, but those are the per-parameter seed and fitted values, which is a different quantity from the whole-fit RMSE. Use errorStat to judge the fit and diffTable to see what happened to individual parameters.

  • optimOutput is the chosen solver's native output struct (iterations, funcCount, message). It carries no exit flag, so do not index .exitflag on it.

  • Nominal, Limits, and Dimensions short-circuit the optimizer and return early with empty errorStat/optimOutput/H, so inspect their diffTable only.

The diffTable columns: most names contain a space

diffTable carries these variables, in this order:

ColumnDot access
ParameterdiffTable.Parameter
Initial ValuediffTable.("Initial Value")
Final ValuediffTable.("Final Value")
DifferencediffTable.Difference
% DifferencediffTable.("% Difference")
Lower BoundsdiffTable.("Lower Bounds")
Upper BoundsdiffTable.("Upper Bounds")
Parameter DescriptiondiffTable.("Parameter Description")
StatusdiffTable.Status (may be absent, see below)

The table above is the current shape. Status and the two bounds columns are recent additions and are missing on older releases, so guard each one with ismember before reading it rather than assuming the shape. Parameter, Initial Value, Final Value, Difference, % Difference, and Parameter Description are the long-standing core. See the Status section below for the guard pattern, which applies to the bounds columns equally.

Only Parameter, Difference, and Status are valid MATLAB identifiers. Every other column needs the diffTable.("Column Name") form. Plain dot access on the rest raises Unrecognized table variable name. Do not guess a space-free spelling such as LowerBounds, and do not invent names such as OldValue/NewValue; the before-and-after pair is Initial Value and Final Value.

Parameter names live in the Parameter variable, not in row names. diffTable has none, so diffTable.Properties.RowNames is empty rather than an error, and any report keyed on it comes back silently empty. That reads as "nothing to disclose" when the truth may be the opposite, so it is worse than a crash: a scope report built this way looks complete and is vacuous.

Watch the asymmetry between input and output names. The fit options are Parameters, FixedParameters, LowerBounds, UpperBounds, Weight, Solver, optimoptions, and PlotFit, all without spaces. The columns that come back carry spaces. LowerBounds= is correct going in and wrong coming out.

To count how many parameters the fit actually moved:

initVals = diffTable.("Initial Value");
finalVals = diffTable.("Final Value");
nChanged = sum(initVals ~= finalVals);

When unsure on a given release, read diffTable.Properties.VariableNames rather than assuming.

The Status column (recent addition, guard for it)

After each optimizer-driven fit, read diffTable.Status, which classifies each parameter as Optimized, Inert, or Collinear. These are three distinct outcomes, not two grades of failure, and the difference is worth reporting accurately:

  • Optimized means the parameter was in the active set the optimizer worked on.

  • Inert means the parameter has zero sensitivity to your data, because a condition variable is not just constant but sitting at its reference value: camber zero throughout, inflation pressure never leaving nominal, or vertical load never leaving nominal. A camber coefficient cannot influence the residual when every sample is at zero camber. The parameter is mathematically unreachable with this data.

  • Collinear means the parameter does affect the residual, but its effect cannot be separated from other parameters', because a condition variable is constant while held away from its reference value: camber pinned at a non-zero angle, pressure held off nominal, load held off nominal, or speed effectively constant. The sensitivity is non-zero but degenerate, so the fit cannot attribute a change in residual to this parameter rather than another.

Both Inert and Collinear are frozen before the optimizer runs and are returned at their seed values, so both belong in the C3 scope report. Neither is a solver failure or something to work around: each is a statement about what your data can support. Do not widen bounds, switch solvers, or re-seed to chase them. The remedy is data that varies the condition in question (a camber sweep, a pressure sweep, a load sweep, or speed variation), and if that data does not exist, say so plainly. When a parameter would qualify as both, Inert takes precedence.

Report which of the two applies rather than collapsing them into "the data could not identify this parameter." Inert says the parameter is invisible to this data; Collinear says it is visible but not separable. A tire modeler reads those differently.

If every parameter for a fit type ends up frozen, fit performs no optimization and warns All optimization parameters are structurally inert for the provided data. No optimization performed. The model is returned unchanged., returning the seed model with empty errorStat, optimOutput, and H. Surface that outcome; do not report it as a successful fit.

Status is a recent addition. Before reading it, confirm the column exists:

if ismember("Status", diffTable.Properties.VariableNames)
    % read diffTable.Status
end

On releases that predate it, skip the Status-based disclosure rather than indexing a missing variable, and never invent a Status column when it is absent. Fall back to building the C3 report from the fit-type set alone.

The bounds columns (a distinct signal from Status)

diffTable also carries Lower Bounds/Upper Bounds columns, read as diffTable.("Lower Bounds") and diffTable.("Upper Bounds"). Like Status these are a recent addition, so confirm they exist with ismember("Lower Bounds", diffTable.Properties.VariableNames) before reading, and skip the pinned-parameter disclosure on releases that lack them. A fitted parameter whose final value sits on a bound was constrained from going further, a distinct signal from Status. Surface any such pinned parameter and the bound it hit, and do not widen a bound on your own initiative.

Judge by residual drop, not the convergence flag

Judge a fit by the size of the .Initial-to-.Final drop and by the overlay plot, not by whether the solver reached its own convergence flag. A tire fit routinely exhausts MaxFunEvals (the solver reports it stopped on the evaluation limit, not on a converged gradient) after a large residual reduction. Because the Magic Formula's functional form and the scatter in the measured data set a floor the residual cannot drop below, that plateau is the normal, healthy terminal state for these fits. It is not a defect, and not evidence the fit can be meaningfully improved.

Do not reflexively raise the evaluation limit, switch solvers, or re-seed to chase the convergence flag; those cost time, yield diminishing-to-zero returns, and risk diverging the fit. Report the plateau and the RMSE reached, and let the user decide whether to push further.

Verify from numbers, not figures

Verify each fit from these numeric diagnostics, the .Initial-to-.Final drop and the Status breakdown, rather than by generating a figure. A plot is a user-facing artifact (the MATLAB desktop is visible), so do not pop one unless the user asked to see or inspect the fit; offer it instead. When a plot is wanted, pass PlotFit=true to fit for a per-fit-type overlay as each fit lands (returned as the H output), or overlay the model on the routed data afterward with mdl.plot(Data=subset, ...) or td.plot(..., Model=mdl) (see references/inspect-by-plotting.md).


Copyright 2026 The MathWorks, Inc.


Requirements and compatibility

Works with: Claude Code, Claude apps, OpenAI Codex, GitHub Copilot, Cursor, Gemini CLI, Kiro, OpenCode, Goose, Amp, Roo Code, JetBrains Junie, Factory Droid, Devin (ex-Windsurf), Mistral Vibe, OpenHands, Letta

“Works with” means the tool reads the open Agent Skills format; a skill written for one tool may use features others lack.

Security

No issues found by our static scan· No issues found

A static scan is not a guarantee. Skills are third-party content: review a skill before you let an agent use it.

Attribution and licence

Created by
MathWorks
Publisher
MathWorks (Official)
Source
matlab/matlab-agentic-toolkit · skills-catalog/automotive/matlab-fit-tire-model · commit 2a7f215
Licence
BSD 2-Clause License (redistribution allowed)
  • LICENSE (added by AutoGineer from LICENSE.md)
  • ATTRIBUTION.md (written by AutoGineer)
Synced

AutoGineer is not affiliated with or endorsed by MathWorks or MathWorks.

Download ZIP

The ZIP holds the skill’s files, its licence files and an ATTRIBUTION.md. Download matlab-fit-tire-model.zip