function [probeDefString] = GenerateProbeDefinitionFiles(varargin)

writeFiles = false;
projectRoot = fullfile(fileparts(mfilename('fullpath')), '..', '..');
probeDefFile = '/robot/probeDefinition.cpp';

numFractionalBits = 15;

parseVarargin(varargin{:});

gridSize = VisionMarkerTrained.ProbeParameters.GridSize;
numDimensions = gridSize^2;

probeDefString = sprintf( [...
    '// Autogenerated by VisionMarkerTrained.%s() on %s\n\n' ...
    '// NOTE: (X,Y) probe locations are stored as SQ%d.%d\n\n' ...
    '#ifndef ANKI_COZMO_ROBOT_MARKER_PROBE_DEFINITIONS_H\n' ...
    '#define ANKI_COZMO_ROBOT_MARKER_PROBE_DEFINITIONS_H\n\n' ...
    '#include "coretech/vision/robot/fiducialMarkers.h"\n\n' ...
    'namespace Anki {\n' ...
    'namespace Embedded {\n\n' ...
    'const u32 VisionMarker::GRIDSIZE = %d;\n' ...
    'const u32 VisionMarker::NUM_PROBES = %d;\n' ...
    'const s32 VisionMarker::NUM_FRACTIONAL_BITS = %d;\n\n'], ...
    mfilename, datestr(now), 15-numFractionalBits, numFractionalBits, ...
    gridSize, numDimensions, numFractionalBits);

%% Probe point pattern

numPoints = length(VisionMarkerTrained.ProbePattern.x);
x_str = cell(1, numPoints);
y_str = cell(1, numPoints);

for i_pt = 1:numPoints
    x = VisionMarkerTrained.ProbePattern.x(i_pt);
    x_str{i_pt} = sprintf('  %5d, // X[%d] = %.4f\n', ...
        FixedPoint(x, numFractionalBits), i_pt, x);
    
    y = VisionMarkerTrained.ProbePattern.y(i_pt);
    y_str{i_pt} = sprintf('  %5d, // Y[%d] = %.4f\n', ...
        FixedPoint(y, numFractionalBits), i_pt, y);
end
        
probeDefString = [probeDefString sprintf([ ...
    '// Note: the probe points included the center (0,0) point\n' ...
    'const u32 VisionMarker::NUM_PROBE_POINTS = %d;\n' ...
    'const s16 VisionMarker::ProbePoints_X[VisionMarker::NUM_PROBE_POINTS] = {\n' ...
    '%s' ...
    '};\n' ...
    'const s16 VisionMarker::ProbePoints_Y[VisionMarker::NUM_PROBE_POINTS] = {\n' ...
    '%s' ...
    '};\n\n'], ...
    numPoints, [x_str{:}], [y_str{:}])];


%% Threshold Probe Locations

numProbes = length(VisionMarkerTrained.BrightProbes.x);
assert(length(VisionMarkerTrained.DarkProbes.x)==numProbes, ...
    'Must have same number of dark and bright probes.');

dark_xStr = cell(1, numProbes);
dark_yStr = cell(1, numProbes);

bright_xStr = cell(1, numProbes);
bright_yStr = cell(1, numProbes);

for i = 1:numProbes
    dark_xStr{i} = sprintf('  %5d, // X = %.4f\n', ...
        FixedPoint(VisionMarkerTrained.DarkProbes.x(i), numFractionalBits), ...
        VisionMarkerTrained.DarkProbes.x(i));
    dark_yStr{i} = sprintf('  %5d, // Y = %.4f\n', ...
        FixedPoint(VisionMarkerTrained.DarkProbes.y(i), numFractionalBits), ...
        VisionMarkerTrained.DarkProbes.y(i));
    
    bright_xStr{i} = sprintf('  %5d, // X = %.4f\n', ...
        FixedPoint(VisionMarkerTrained.BrightProbes.x(i), numFractionalBits), ...
        VisionMarkerTrained.BrightProbes.x(i));
    bright_yStr{i} = sprintf('  %5d, // Y = %.4f\n', ...
        FixedPoint(VisionMarkerTrained.BrightProbes.y(i), numFractionalBits), ...
        VisionMarkerTrained.BrightProbes.y(i));
end

probeDefString = [probeDefString sprintf([ ...
    'const u32 VisionMarker::NUM_THRESHOLD_PROBES = %d;\n' ...
    'const s16 VisionMarker::ThresholdDarkProbe_X[NUM_THRESHOLD_PROBES] = {\n' ...
    '%s' ...
    '};\n\n' ...
    'const s16 VisionMarker::ThresholdDarkProbe_Y[NUM_THRESHOLD_PROBES] = {\n' ...
    '%s' ...
    '};\n\n' ...
    'const s16 VisionMarker::ThresholdBrightProbe_X[NUM_THRESHOLD_PROBES] = {\n' ...
    '%s' ...
    '};\n\n'...
    'const s16 VisionMarker::ThresholdBrightProbe_Y[NUM_THRESHOLD_PROBES] = {\n' ...
    '%s' ...
    '};\n\n'], ...
    numProbes, [dark_xStr{:}], [dark_yStr{:}], [bright_xStr{:}], [bright_yStr{:}])];

%% Probe Center Locations
numProbes = VisionMarkerTrained.ProbeParameters.GridSize^2;

[xgrid,ygrid] = VisionMarkerTrained.GetProbeGrid();
        
center_xStr = cell(1, numProbes);
center_yStr = cell(1, numProbes);

for i = 1:numProbes
    center_xStr{i} = sprintf('  %5d, // X = %.4f\n', ...
        FixedPoint(xgrid(i), numFractionalBits), xgrid(i));
    center_yStr{i} = sprintf('  %5d, // Y = %.4f\n', ...
        FixedPoint(ygrid(i), numFractionalBits), ygrid(i));
end

probeDefString = [probeDefString sprintf([ ...
    'const s16 VisionMarker::ProbeCenters_X[NUM_PROBES] = {\n' ...
    '%s' ...
    '};\n\n' ...
    'const s16 VisionMarker::ProbeCenters_Y[NUM_PROBES] = {\n' ...
    '%s' ...
    '};\n\n'], ...
    [center_xStr{:}], [center_yStr{:}])];



probeDefString = [probeDefString sprintf([ ...
    '} // namespace Embedded\n' ...
    '} // namespace Anki\n\n' ...
    '#endif // ANKI_COZMO_ROBOT_MARKER_PROBE_DEFINITIONS_H\n'])];



if writeFiles 
   
    probeDefFile = fullfile(projectRoot, probeDefFile); %#ok<UNRCH>
    fid = fopen(probeDefFile, 'wt');
    if fid == -1
        error('Could not open "%s" for writing probe definition file.', probeDefFile);
    else
        fprintf(fid, '%s', probeDefString);
        fclose(fid);
        fprintf('Wrote probe definition file to "%s".\n', probeDefFile);
    end
    
end % IF writeFiles
    
end % FUNCTION GenerateHeaderFile()

function fixedPt = FixedPoint(value, numFractionalBits)

if isempty(value)
    fixedPt = 0;
else
    fixedPt = int32(round(2^numFractionalBits)*value);
end

end % FUNCTION FixedPointHelper()


