Skip to content

chat not taking input from letter "n" #313041

@cbicari

Description

@cbicari

Type: Bug

this bug was still happening after update
#312926 (comment)

As mentioned in previous bug bfore update, letter "n" was never taken into account. I have a terminal and a file open as well as the Github Copilot Chat.
When I wrote in terminal, the "n" would appear.
When I wrote in my file with vim extension, I had to press "esc" several times to force it out of any special input mode, the press "i" for input, and the "n" letter was accepted. After doing that, the Github Chat started accepting the "n" input again.

Do you folks think it's related to any vim add on for file editing ?

Extension version: 0.45.1
VS Code version: Code 1.117.0 (10c8e55, 2026-04-21T16:12:14-07:00)
OS version: Linux x64 6.9.1-060901-generic
Modes:

Logs
Trace: [NES][DocumentEditCache][tryRebaseCacheEntry] Rebase duration: 0ms
Trace: [NES][NextEditProvider][f36b][_getNextEdit] fetching next edit with shouldExpandEditWindow=false
Trace: [NES][NextEditProvider][f36b][_getNextEdit] awaiting firstEdit promise
Trace: [NES][NextEditProvider][f36b][_getNextEdit][fetchNextEdit][_executeNewNextEditRequest][XtabProvider][doGetNextEditWithSelection] Debouncing for cursor at end of line
Trace: [NES][NextEditProvider][f36b][_getNextEdit][fetchNextEdit][_executeNewNextEditRequest][XtabProvider][doGetNextEditWithSelection] Using default nLinesBelow: 5
Info: ccreq:8f897cf8.copilotmd | markdown
Trace: [NES][NextEditProvider][f36b][_getNextEdit][fetchNextEdit][_executeNewNextEditRequest][XtabProvider][doGetNextEditWithSelection] Debouncing for 2083 ms
Debug: [relatedFiles] Fetched following traits  for 'file:///home/chu/Desktop/soft/sat_soft/puara-gestures/include/puara/utils/kalmanQuaternion.h'
Debug: [relatedFiles] neighborFiles.getNeighborFilesAndTraits 0 related files found for file:///home/chu/Desktop/soft/sat_soft/puara-gestures/include/puara/utils/kalmanQuaternion.h
Debug: [default] Context providers telemetry: '[{"providerId":"ms-vscode.cpptools","resolution":"full","resolutionTimeMs":25.792094999924302,"usage":"full","usageDetails":[{"id":"d09387e0-ccc6-4c8e-b900-2265bea4ed1e","type":"Trait","usage":"full","expectedTokens":17,"actualTokens":17},{"id":"055c38e4-e3ca-426c-abed-11be4bdf2710","type":"CodeSnippet","usage":"full","expectedTokens":15,"actualTokens":15},{"id":"776c69c2-3ab6-47fc-8f6f-2f29028c5645","type":"CodeSnippet","usage":"full","expectedTokens":57,"actualTokens":57},{"id":"bcaec17f-1ae2-4d32-9cf3-44bedf3902a9","type":"CodeSnippet","usage":"full","expectedTokens":18,"actualTokens":18},{"id":"b3051594-ff30-426e-860c-2189276aef3b","type":"CodeSnippet","usage":"full","expectedTokens":15,"actualTokens":15}],"matched":true,"numResolvedItems":5,"numUsedItems":5,"numPartiallyUsedItems":0},{"providerId":"scm-context-provider","resolution":"none","resolutionTimeMs":0,"usage":"none","matched":false,"numResolvedItems":0},{"providerId":"promptfile-ai-context-provider","resolution":"none","resolutionTimeMs":0,"usage":"none","matched":false,"numResolvedItems":0},{"providerId":"pylanceTraitProvider","resolution":"none","resolutionTimeMs":0,"usage":"none","matched":false,"numResolvedItems":0},{"providerId":"pylanceCodeSnippetProvider","resolution":"none","resolutionTimeMs":0,"usage":"none","matched":false,"numResolvedItems":0}]'
Trace: [Ghost][CopilotInlineCompletionItemProvider][provideInlineCompletionItems][GhostTextProvider][provideInlineCompletionItems][GhostTextComputer#getGhostText][GhostTextComputer#getGhostTextWithoutAbortHandling] Starting ghost text computation, prefix length: 2823
Trace: [Ghost][CopilotInlineCompletionItemProvider][provideInlineCompletionItems][GhostTextProvider][provideInlineCompletionItems][GhostTextComputer#getGhostText][GhostTextComputer#getGhostTextWithoutAbortHandling] hasAcceptedCurrentCompletion: false
Trace: [Ghost][CopilotInlineCompletionItemProvider][provideInlineCompletionItems][GhostTextProvider][provideInlineCompletionItems][GhostTextComputer#getGhostText][GhostTextComputer#getGhostTextWithoutAbortHandling] Ghost text strategy: blockMode=server, requestMultiline=true, stop=undefined, maxTokens=undefined
Debug: [getCompletionsFromCache] Found no completions in cache
Trace: [Ghost][CopilotInlineCompletionItemProvider][provideInlineCompletionItems][GhostTextProvider][provideInlineCompletionItems][GhostTextComputer#getGhostText][GhostTextComputer#getGhostTextWithoutAbortHandling] Local cache lookup: no cached choices
Trace: [Ghost][CopilotInlineCompletionItemProvider][provideInlineCompletionItems][GhostTextProvider][provideInlineCompletionItems][GhostTextComputer#getGhostText][GhostTextComputer#getGhostTextWithoutAbortHandling] Skipping wait for async completions
Trace: [Ghost][CopilotInlineCompletionItemProvider][provideInlineCompletionItems][GhostTextProvider][provideInlineCompletionItems][GhostTextComputer#getGhostText][GhostTextComputer#getGhostTextWithoutAbortHandling] Going to network, isCycling=false
Trace: [Ghost][CopilotInlineCompletionItemProvider][provideInlineCompletionItems][GhostTextProvider][provideInlineCompletionItems][GhostTextComputer#getGhostText][GhostTextComputer#getGhostTextWithoutAbortHandling] Initiating network request for completions
Debug: [ghostText] Getting completions from network
Debug: [AsyncCompletionManager] [e50df62c-abb1-425a-984d-4ddbf580ccbb] Queueing async completion request: 
Debug: [AsyncCompletionManager] [e50df62c-abb1-425a-984d-4ddbf580ccbb] Cancelling request: 4f5082af-287b-4944-8199-be84790bfade
Info: ccreq:280bc375.copilotmd | markdown
Error: [AsyncCompletionManager] [4f5082af-287b-4944-8199-be84790bfade] Request errored with [AbortError: The operation was aborted
	at handleKnownInternalErrors (node:internal/webstreams/adapters:111:14)
	at IncomingMessage. (node:internal/webstreams/adapters:476:13)
	at AsyncResource.runInAsyncScope (node:async_hooks:214:14)
	at IncomingMessage. (node:internal/streams/end-of-stream:61:21)
	at IncomingMessage. (node:internal/util:575:20)
	at IncomingMessage.onclose (node:internal/streams/end-of-stream:165:25)
	at IncomingMessage.emit (node:events:519:28)
	at IncomingMessage.emit (node:domain:489:12)
	at emitCloseNT (node:internal/streams/destroy:148:10)
	at processTicksAndRejections (node:internal/process/task_queues:88:21)
	at runNextTicks (node:internal/process/task_queues:68:3)
	at process.processTimers (node:internal/timers:518:9)] {
  code: 'ABORT_ERR',
  [cause]: [Error: Premature close
  	at IncomingMessage.onclose (node:internal/streams/end-of-stream:166:30)
  	at IncomingMessage.emit (node:events:519:28)
  	at IncomingMessage.emit (node:domain:489:12)
  	at emitCloseNT (node:internal/streams/destroy:148:10)
  	at processTicksAndRejections (node:internal/process/task_queues:88:21)
  	at runNextTicks (node:internal/process/task_queues:68:3)
  	at process.processTimers (node:internal/timers:518:9)] {
    code: 'ERR_STREAM_PREMATURE_CLOSE'
  }
}
Debug: [AsyncCompletionManager] [4f5082af-287b-4944-8199-be84790bfade] No matching completions found
Trace: [Ghost][CopilotInlineCompletionItemProvider][provideInlineCompletionItems][GhostTextProvider][provideInlineCompletionItems][GhostTextComputer#getGhostText][GhostTextComputer#getGhostTextWithoutAbortHandling] Network request returned no results
Debug: [getCompletions] No ghostText produced -- empty: received no results from async completions
Trace: [NES][DiagnosticsNextEditProvider] no diagnostic edit result
Info: [fetchCompletions] Request e50df62c-abb1-425a-984d-4ddbf580ccbb at  finished with 200 status after 394.74865799956024ms
Debug: [fetchCompletions] request.response properties {
  headerRequestId: 'e50df62c-abb1-425a-984d-4ddbf580ccbb',
  opportunityId: 'icr-f36b690a-3a5d-4500-b83c-abf1cad78ed1',
  copilot_build: '1',
  copilot_buildType: 'prod',
  languageId: 'cpp',
  afterAccept: 'false',
  isSpeculative: 'false',
  gitRepoInformation: 'available',
  gitRepoUrl: 'https://github.com/Puara/puara-gestures',
  gitRepoHost: 'github.com',
  gitRepoOwner: 'Puara',
  gitRepoName: 'puara-gestures',
  gitRepoPath: '/Puara/puara-gestures',
  engineName: 'gpt-41-copilot',
  engineChoiceSource: 'default',
  isMultiline: 'true',
  isCycling: 'false',
  endpoint: 'completions',
  uiKind: 'ghostText',
  temperature: '0',
  n: '1',
  stop: 'unset',
  logit_bias: 'null',
  'request.option.max_tokens': '500',
  'request.option.temperature': '0',
  'request.option.top_p': '1',
  'request.option.n': '1',
  'request.option.stop': '["\\n\\n\\n","\\n```"]',
  'request.option.stream': 'true',
  'request.option.extra': '{"language":"cpp","next_indent":0,"trim_by_indentation":true,"prompt_tokens":6447,"suffix_tokens":1154}',
  'request.option.nwo': '"puara/puara-gestures"',
  'request.option.code_annotations': 'false',
  serverExperiments: '',
  deploymentId: '',
  status: '200'
}
Debug: [fetchCompletions] request.response measurements {
  documentLength: 9021,
  documentLineCount: 268,
  promptCharLen: 22502,
  promptSuffixCharLen: 4510,
  totalTimeMs: 394.74865799956024
}
Debug: [fetchCompletions] prompt: {
  prefix: '/*\n' +
    ' * KalmanQuaternionFilter\n' +
    ' * -----------------------\n' +
    ' *\n' +
    ' * A simplified Kalman-style quaternion filter for 9-DoF IMU orientation.\n' +
    ' * This implementation performs gyro-based quaternion prediction and then\n' +
    ' * blends toward an accel/magnetometer-based orientation measurement.\n' +
    ' *\n' +
    ' * It is intentionally compact and similar in usage style to the Madgwick\n' +
    ' * and Mahony filters in this project.\n' +
    ' *\n' +
    ' * Usage:\n' +
    ' *   - The class stores orientation as `puara_gestures::Quaternion`.\n' +
    ' *   - Input data is accepted through `puara_gestures::Imu9Axis`.\n' +
    ' *   - Gyroscope values are assumed to be in radians/sec by default.\n' +
    ' *   - Use `gyroDegrees = true` when gyro values are in degrees/sec.\n' +
    ' *\n' +
    ' * Example:\n' +
    ' *   puara_gestures::KalmanQuaternionFilter filter(0.001, 0.01);\n' +
    ' *   puara_gestures::Imu9Axis imu{ {0.0, 0.0, 9.81}, {1.0, 2.0, 3.0}, {0.3, 0.0, 0.5} };\n' +
    ' *   bool ok = filter.update(imu, true);\n' +
    ' */\n' +
    '\n' +
    '#pragma once\n' +
    '\n' +
    '#ifndef KALMANQUATERNION_H\n' +
    '#define KALMANQUATERNION_H\n' +
    '\n' +
    '#include \n' +
    '#include \n' +
    '#include \n' +
    '#include \n' +
    '\n' +
    'namespace puara_gestures {\n' +
    '\n' +
    'struct KalmanQuaternionFilter {\n' +
    '    // Simplified Kalman-style quaternion fusion.\n' +
    '    // This implementation uses gyro prediction and an adaptive blend\n' +
    '    // toward an accel/magnetometer-based orientation estimate.\n' +
    '    // A true quaternion EKF is much larger; this keeps the interface\n' +
    '    // compact and similar to the other AHRS filters.\n' +
    '    double processNoise{};\n' +
    '    double measurementNoise{};\n' +
    '    Quaternion quaternion{};\n' +
    '    uint64_t lastUpdateMicros{};\n' +
    '\n' +
    '    explicit KalmanQuaternionFilter(double processNoise_ = 0.001, double measurementNoise_ = 0.01)\n' +
    '        : processNoise(processNoise_)\n' +
    '        , measurementNoise(measurementNoise_)\n' +
    '        , quaternion{1.0, 0.0, 0.0, 0.0}\n' +
    '        , lastUpdateMicros(0)\n' +
    '    {\n' +
    '    }\n' +
    '\n' +
    '    void reset() {\n' +
    '        quaternion = {1.0, 0.0, 0.0, 0.0};\n' +
    '        lastUpdateMicros = 0;\n' +
    '    }\n' +
    '\n' +
    '    bool update(const Imu9Axis& imu, bool gyroDegrees = false) {\n' +
    '        return updateWithTimestamp(imu, utils::getCurrentTimeMicroseconds(), gyroDegrees);\n' +
    '    }\n' +
    '\n' +
    '    const Quaternion& getQuaternion() const {\n' +
    '        return quaternion;\n' +
    '    }\n' +
    '\n' +
    '    void getEulerRadians(double& roll, double& pitch, double& yaw) const {\n' +
    '        const double w = quaternion.w;\n' +
    '        const double x = quaternion.x;\n' +
    '        const double y = quaternion.y;\n' +
    '        const double z = quaternion.z;\n' +
    '\n' +
    '        roll = std::atan2(2.0 * (w * x + y * z), 1.0 - 2.0 * (x * x + y * y));\n' +
    '        pitch = std::asin(clamp(2.0 * (w * y - z * x), -1.0, 1.0));\n' +
    '        yaw = std::atan2(2.0 * (w * z + x * y), 1.0 - 2.0 * (y * y + z * z));\n' +
    '    }\n' +
    '\n' +
    '    void getEulerDegrees(double& roll, double& pitch, double& yaw) const {\n' +
    '        getEulerRadians(roll, pitch, yaw);\n' +
    '        roll *= RadToDeg;\n' +
    '        pitch *= RadToDeg;\n' +
    '        yaw *= RadToDeg;\n' +
    '    }\n',
  prefixTokens: 6447,
  suffix: 'private:\n' +
    '    bool updateWithTimestamp(const Imu9Axis& imu, uint64_t currentMicros, bool gyroDegrees) {\n' +
    '        if (currentMicros == 0) {\n' +
    '            return false;\n' +
    '        }\n' +
    '        if (lastUpdateMicros == 0) {\n' +
    '            lastUpdateMicros = currentMicros;\n' +
    '            return false;\n' +
    '        }\n' +
    '\n' +
    '        double deltatSeconds = double(currentMicros - lastUpdateMicros) * 1.0e-6;\n' +
    '        lastUpdateMicros = currentMicros;\n' +
    '        return updateInternal(imu, deltatSeconds, gyroDegrees);\n' +
    '    }\n' +
    '\n' +
    '    bool updateInternal(const Imu9Axis& imu, double deltatSeconds, bool gyroDegrees) {\n' +
    '        if (deltatSeconds <= 0.0) {\n' +
    '            return false;\n' +
    '        }\n' +
    '\n' +
    '        double gx = imu.gyro.x;\n' +
    '        double gy = imu.gyro.y;\n' +
    '        double gz = imu.gyro.z;\n' +
    '        if (gyroDegrees) {\n' +
    '            gx *= DegToRad;\n' +
    '            gy *= DegToRad;\n' +
    '            gz *= DegToRad;\n' +
    '        }\n' +
    '\n' +
    '        predictQuaternion(gx, gy, gz, deltatSeconds);\n' +
    '\n' +
    '        Quaternion measured;\n' +
    '        if (!estimateQuaternionFromAccelMag(imu.accl.x, imu.accl.y, imu.accl.z,\n' +
    '                                           imu.magn.x, imu.magn.y, imu.magn.z,\n' +
    '                                           measured)) {\n' +
    '            return true;\n' +
    '        }\n' +
    '\n' +
    '        double gain = processNoise / (processNoise + measurementNoise);\n' +
    '        gain = clamp(gain, 0.0, 1.0);\n' +
    '        quaternion = slerp(quaternion, measured, gain);\n' +
    '        normalizeQuaternion(quaternion);\n' +
    '\n' +
    '        return true;\n' +
    '    }\n' +
    '\n' +
    '    void predictQuaternion(double gx, double gy, double gz, double deltat) {\n' +
    '        // Gyro integration step: propagate the quaternion forward using angular velocity.\n' +
    '        // This is the prediction phase of the simplified Kalman-style filter.\n' +
    '        double q0 = quaternion.w;\n' +
    '        double q1 = quaternion.x;\n' +
    '        double q2 = quaternion.y;\n' +
    '        double q3 = quaternion.z;\n' +
    '\n' +
    '        double qDot1 = 0.5 * (-q1 * gx - q2 * gy - q3 * gz);\n' +
    '        double qDot2 = 0.5 * (q0 * gx + q2 * gz - q3 * gy);\n' +
    '        double qDot3 = 0.5 * (q0 * gy - q1 * gz + q3 * gx);\n' +
    '        double qDot4 = 0.5 * (q0 * gz + q1 * gy - q2 * gx);\n' +
    '\n' +
    '        q0 += qDot1 * deltat;\n' +
    '        q1 += qDot2 * deltat;\n' +
    '        q2 += qDot3 * deltat;\n' +
    '        q3 += qDot4 * deltat;\n' +
    '\n' +
    '        quaternion.w = q0;\n' +
    '        quaternion.x = q1;\n' +
    '        quaternion.y = q2;\n' +
    '        quaternion.z = q3;\n' +
    '        normalizeQuaternion(quaternion);\n' +
    '    }\n' +
    '\n' +
    '    static bool estimateQuaternionFromAccelMag(double ax, double ay, double az,\n' +
    '                                               double mx, double my, double mz,\n' +
    '                                               Quaternion& quaternionOut) {\n' +
    '        // Normalize accelerometer data to extract the gravity direction.\n' +
    '        double norm = std::hypot(ax, ay, az);\n' +
    '        if (norm == 0.0) {\n' +
    '            return false;\n' +
    '        }\n' +
    '        norm = std::sqrt(norm);\n' +
    '        ax /= norm;\n' +
    '        ay /= norm;\n' +
    '        az /= norm;\n' +
    '\n' +
    '        // Compute roll and pitch from the gravity vector.\n' +
    '        double roll = std::atan2(ay, az);\n' +
    '        double pitch = std::atan2(-ax, std::hypot(ay, az));\n' +
    '\n' +
    '        double sinRoll = std::sin(roll);\n' +
    '        double cosRoll = std::cos(roll);\n' +
    '        double sinPitch = std::sin(pitch);\n' +
    '        double cosPitch = std::cos(pitch);\n' +
    '\n' +
    '        // Rotate the magnetometer measurements into the horizontal plane.\n' +
    '        // This removes the effect of tilt and allows yaw to be computed.\n' +
    '        double mx2 = mx * cosPitch + my * sinPitch * sinRoll + mz * sinPitch * cosRoll;\n' +
    '        double my2 = my * cosRoll - mz * sinRoll;\n' +
    '        if (mx2 == 0.0 && my2 == 0.0) {\n' +
    '            return false;\n' +
    '        }\n' +
    '\n' +
    '        double yaw = std::atan2(-my2, mx2);\n' +
    '        quaternionOut = quaternionFromEuler(roll, pitch, yaw);\n' +
    '        return true;\n' +
    '    }\n' +
    '\n' +
    '    static Quaternion quaternionFromEuler(double roll, double pitch, double yaw) {\n' +
    '        double cr = std::cos(roll * 0.5);\n' +
    '        double sr = std::sin(roll * 0.5);\n' +
    '        double cp = std::cos(pitch * 0.5);\n' +
    '        double sp = std::sin(pitch * 0.5);\n' +
    '        double cy = std::cos(yaw * 0.5);\n' +
    '        double sy = std::sin(yaw * 0.5);\n' +
    '\n' +
    '        return Quaternion{\n' +
    '            cr * cp * cy + sr * sp * sy,\n' +
    '            sr * cp * cy - cr * sp * sy,\n' +
    '            cr * sp * cy + sr * cp * sy,\n' +
    '            cr * cp * sy - sr * sp * cy\n' +
    '        };\n' +
    '    }\n' +
    '\n' +
    '    static Quaternion slerp(const Quaternion& a, const Quaternion& b, double t) {\n' +
    '        // Spherical linear interpolation between two quaternion orientations.\n' +
    '        // This blends the predicted orientation and the measured orientation smoothly.\n' +
    '        double cosTheta = a.w * b.w',
  suffixTokens: 1154,
  context: [
    'Path: include/puara/utils/kalmanQuaternion.h\n' +
      'Consider this related information:\n' +
      'C++ language standard version: This project uses the C++17 language standard version.\n' +
      'Compare this snippet from include/puara/utils/chrono.h:\n' +
      'inline unsigned long long getCurrentTimeMicroseconds()\n' +
      '{\n' +
      '  auto currentTimePoint = std::chrono::steady_clock::now();\n' +
      '  auto duration = std::chrono::duration_cast(\n' +
      '      currentTimePoint.time_since_epoch());\n' +
      '  return duration.count();\n' +
      '}\n' +
      'Compare these snippets from include/puara/structs.h:\n' +
      'struct Quaternion\n' +
      '{\n' +
      '  double w, x, y, z;\n' +
      '};\n' +
      '---\n' +
      'struct Imu9Axis\n' +
      '{\n' +
      '  Coord3D accl, gyro, magn;\n' +
      '};\n' +
      '---\n' +
      'struct Coord3D\n' +
      '{\n' +
      '  double x, y, z;\n' +
      '};\n' +
      'Compare this snippet from tests/platformio/src/main.cpp:\n' +
      'x = x * 1.25 + 0.22;\n' +
      '    y = y * 0.68 - 0.16;\n' +
      '    z = z * 1.14 + 0.06;\n' +
      '    samples[i] = {x, y, z};\n' +
      '  }\n' +
      '\n' +
      '  puara_gestures::utils::Embedded_Calibration calib(sampleCount);\n' +
      '  bool ok = (calib.generateMagnetometerMatrices(samples, sampleCount) == 1);\n' +
      '\n' +
      '  for (size_t i = 0; ok && i < sampleCount; ++i) {\n' +
      '    puara_gestures::Imu9Axis raw{};\n' +
      '    raw.magn = samples[i];\n' +
      '    calib.applyMagnetometerCalibration(raw);\n' +
      '    const double r = std::sqrt(calib.myCalIMU.magn.x * calib.myCalIMU.magn.x + \n' +
      '                              calib.myCalIMU.magn.y * calib.myCalIMU.magn.y + \n' +
      '                              calib.myCalIMU.magn.z * calib.myCalIMU.magn.z);\n' +
      '    ok &= almostEqual(r, 1.0, 0.25);\n' +
      '  }\n' +
      '\n' +
      '  logResult(ok, name);\n' +
      '}\n' +
      '\n' +
      'static void testRollingMinMax() {\n' +
      '  const char* name = "RollingMinMax sliding range";\n' +
      '  puara_gestures::utils::RollingMinMax window(3);\n' +
      '\n' +
      '  bool ok = true;\n' +
      '  auto result1 = window.update(5);\n' +
      '  ok &= (result1.min == 5 && result1.max == 5);\n' +
      '\n' +
      '  auto result2 = window.update(3);\n' +
      '  ok &= (result2.min == 3 && result2.max == 5);\n' +
      '\n' +
      '  auto result3 = window.update(8);\n' +
      '  ok &= (result3.min == 3 && result3.max == 8);\n' +
      '\n' +
      '  auto result4 = window.update(1);\n' +
      '  ok &= (result4.min == 1 && result4.max == 8);\n' +
      '\n' +
      '  auto result5 = window.update(9);\n' +
      '  ok &= (result5.min == 1 && result5.max == 9);\n' +
      '\n' +
      '  logResult(ok, name);\n' +
      '}\n' +
      '\n' +
      'static void testDiscretizer() {\n' +
      '  const char* name = "Discretizer change detection";\n' +
      '  puara_gestures::utils::Discretizer detector;\n' +
      '\n' +
      '  bool ok = detector.isNew(10) && (detector.getLatestValue() == 10);\n' +
      '  ok &= !detector.isNew(10);\n' +
      '  ok &= detector.isNew(20) && (detector.getLatestValue() == 20);\n' +
      '  ok &= !detector.isNew(20);\n' +
      '  ok &= detector.isNew(15) && (detector.getLatestValue() == 15);\n' +
      '\n' +
      '  logResult(ok, name);\n' +
      '}\n' +
      '\n' +
      'static void runEmbeddedTests() {\n' +
      'Compare this snippet from tests/test_descriptors.cpp:\n' +
      'Tilt test;\n' +
      '\n' +
      '  double maxDiff = 0.0;\n' +
      '\n' +
      '  for(size_t r = 0; r < rowCount; ++r)\n' +
      '  {\n' +
      '    const double timestamp = readCsvDouble(doc, "timestamp", r);\n' +
      '\n' +
      '    Coord3D accl{\n' +
      '        readCsvDouble(doc, "accl_x", r),\n' +
      '        readCsvDouble(doc, "accl_y", r),\n' +
      '        readCsvDouble(doc, "accl_z", r),\n' +
      '    };\n' +
      '\n' +
      '    Coord3D gyro{\n' +
      '        readCsvDouble(doc, "gyro_x", r),\n' +
      '        readCsvDouble(doc, "gyro_y", r),\n' +
      '        readCsvDouble(doc, "gyro_z", r),\n' +
      '    };\n' +
      '\n' +
      '    Coord3D mag{\n' +
      '        readCsvDouble(doc, "mag_x", r),\n' +
      '        readCsvDouble(doc, "mag_y", r),\n' +
      '        readCsvDouble(doc, "mag_z", r),\n' +
      '    };\n' +
      '\n' +
      '    const double expectedTilt = readCsvDouble(doc, "tilt", r);\n' +
      '    const double measuredTilt = test.tilt(accl, gyro, mag, timestamp);\n' +
      '    const double diff = std::fabs(measuredTilt - expectedTilt);\n' +
      '\n' +
      '    INFO(\n' +
      '        "row=" << r << " timestamp=" << timestamp << " expected=" << expectedTilt\n' +
      '               << " measured=" << measuredTilt << " diff=" << diff);\n' +
      '    CHECK(diff < 0.35);\n' +
      '    maxDiff = std::max(maxDiff, diff);\n' +
      '  }\n' +
      '\n' +
      '  CHECK(maxDiff < 0.35);\n' +
      '}\n' +
      '\n' +
      'TEST_CASE(\n' +
      '    "Simple Tilt/Roll descriptor computes roll and tilt from accelerometer data",\n' +
      '    "[descriptors][simple_tilt_roll]")\n' +
      '{\n' +
      '  puara_gestures::Tilt_Roll simple;\n' +
      '  simple.update(0.0, 0.0, 1.0);\n' +
      '\n' +
      '  CHECK(simple.current_roll_value() == Catch::Approx(M_PI_2).margin(1e-6));\n' +
      '  CHECK(simple.current_tilt_value() == Catch::Approx(0.0).margin(1e-6));\n' +
      '\n' +
      '  simple.update(1.0, 0.0, 0.0);\n' +
      '  CHECK(simple.current_roll_value() == Catch::Approx(0.0).margin(1e-6));\n' +
      '  CHECK(simple.current_tilt_value() == Catch::Approx(M_PI_2).margin(1e-3));\n' +
      '\n' +
      '  Coord3D imu_data{0.0, 0.0, 1.0};\n' +
      '  Tilt_Roll tied(&imu_data);\n' +
      '  tied.update();\n' +
      '  CHECK(tied.current_roll_value() == Catch::Approx(M_PI_2).margin(1e-6));\n' +
      '  CHECK(tied.current_tilt_value() == Catch::Approx(0.0).margin(1e-6));\n' +
      'Compare this snippet from include/puara/descriptors/shake.h:\n' +
      '#include \n' +
      '#include \n' +
      '\n' +
      'namespace puara_gestures\n' +
      '{\n' +
      '\n' +
      '/**\n' +
      ' * @brief Simple 1D shake detector.\n' +
      ' *\n' +
      ' * Shake turns raw acceleration energy into a slowly changing value.\n' +
      ' * It is useful when you want a smooth gesture-like signal for shaking,\n' +
      ' * vibration, or repeated movement on one axis.\n' +
      ' *\n' +
      ' * Example:\n' +
      ' *   double accel = 0.0;\n' +
      ' *   puara_gestures::Shake shake(&accel);\n' +
      ' *   shake.threshold = 0.2;\n' +
      ' *   shake.fast_leak = 0.6;\n' +
      ' *   shake.slow_leak = 0.3;\n' +
      ' *\n' +
      ' *   // in your sensor loop:\n' +
      ' *   accel = sensor.read();\n' +
      ' *   shake.update();\n' +
      ' *   double energy = shake.current_value();\n' +
      ' *\n' +
      ' * The output grows when motion is above threshold, and it decays when the\n' +
      ' * motion calms down.\n' +
      ' *\n' +
      ' * `Shake2D` and `Shake3D` work the same way for two or three axes.\n' +
      ' */\n' +
      'class Shake\n' +
      '{\n' +
      'public:\n' +
      '  utils::LeakyIntegrator integrator{0, 0, 0.6, 10, 0};\n' +
      '  double fast_leak = 0.6;\n' +
      '  double slow_leak = 0.3;\n' +
      '  double threshold = 0.1;\n' +
      '\n' +
      '  Shake()\n' +
      '      : tied_value(nullptr)\n' +
      '  {\n' +
      '  }\n' +
      '  explicit Shake(double* tied)\n' +
      '      : tied_value(tied)\n' +
      '  {\n' +
      '  }\n' +
      '  explicit Shake(Coord1D* tied)\n' +
      '      : tied_value(&(tied->x))\n' +
      '  {\n' +
      '  }\n' +
      '\n' +
      '  double update(double reading)\n' +
      '  {\n' +
      '    if(tied_value != nullptr)\n' +
      '    {\n' +
      '      *tied_value = reading;\n' +
      '    }\n' +
      '\n' +
      '    double abs_reading = std::abs(reading);\n' +
      'Compare this snippet from include/puara/descriptors/button.h:\n' +
      '}\n' +
      '\n' +
      '  unsigned int count = 0;\n' +
      '  bool press = false;\n' +
      '  unsigned int tap = 0;\n' +
      '  unsigned int doubleTap = 0;\n' +
      '  unsigned int tripleTap = 0;\n' +
      '  bool hold = false;\n' +
      '  unsigned int pressTime = 0;\n' +
      '  unsigned int threshold = 1;\n' +
      '  unsigned int countInterval = 200;\n' +
      '  unsigned int holdInterval = 5000;\n' +
      '\n' +
      '  void update(int value)\n' +
      '  {\n' +
      '    long currentTime = puara_gestures::utils::getCurrentTimeMicroseconds() / 1000LL;\n' +
      '    value = value;\n' +
      '    if(value >= threshold)\n' +
      '    {\n' +
      '      if(!press)\n' +
      '      {\n' +
      '        press = true;\n' +
      '        timer = currentTime;\n' +
      '      }\n' +
      '      if(currentTime - timer > holdInterval)\n' +
      '      {\n' +
      '        hold = true;\n' +
      '      }\n' +
      '    }\n' +
      '    else if(hold)\n' +
      '    {\n' +
      '      hold = false;\n' +
      '      press = false;\n' +
      '      count = -1;\n' +
      '    }\n' +
      '    else\n' +
      '    {\n' +
      '      if(press)\n' +
      '      {\n' +
      '        press = false;\n' +
      '        pressTime = currentTime - timer;\n' +
      '        timer = currentTime;\n' +
      '        count++;\n' +
      '      }\n' +
      '    }\n' +
      '    if(!press && (currentTime - timer > countInterval))\n' +
      '    {\n' +
      '      switch(count)\n' +
      '      {\n' +
      '        case 0:\n' +
      '          tap = 0;\n' +
      '          doubleTap = 0;\n' +
      '          tripleTap = 0;\n' +
      '          break;\n' +
      '        case 1:\n' +
      '          tap = 1;\n' +
      '          doubleTap = 0;\n' +
      '          tripleTap = 0;\n' +
      '          break;\n' +
      '        case 2:\n' +
      'Compare this snippet from tests/testing_magnetometerCalibration.cpp:\n' +
      '#include \n' +
      '#include \n' +
      '#include \n' +
      '#include \n' +
      '\n' +
      '#include \n' +
      '\n' +
      'using namespace Catch;\n' +
      'using namespace puara_gestures;\n' +
      'using namespace puara_gestures::utils;\n' +
      '\n' +
      '#ifndef M_PI\n' +
      '#define M_PI 3.14159265358979323846\n' +
      '#endif\n' +
      '\n' +
      '// This suite validates the trusted float-recorded magnetometer file only.\n' +
      '// The integer dataset is excluded from the core Catch2 validation so the\n' +
      '// calibration expectations remain aligned with the desired process.\n' +
      '\n' +
      'static std::vector loadMagnetometerCsv(const std::filesystem::path& csvPath)\n' +
      '{\n' +
      "    rapidcsv::Document doc(csvPath.string(), rapidcsv::LabelParams(0, -1), rapidcsv::SeparatorParams(','));\n" +
      '    std::vector colX = doc.GetColumn("magn_x");\n' +
      '    std::vector colY = doc.GetColumn("magn_y");\n' +
      '    std::vector colZ = doc.GetColumn("magn_z");\n' +
      '\n' +
      '    std::vector points;\n' +
      '    points.reserve(colX.size());\n' +
      '    for (size_t i = 0; i < colX.size(); ++i)\n' +
      '    {\n' +
      '        points.push_back({colX[i], colY[i], colZ[i]});\n' +
      '    }\n' +
      '    return points;\n' +
      '}\n' +
      '\n' +
      'static std::vector makeBiasedScaledSphere(size_t count)\n' +
      '{\n' +
      '    std::vector samples;\n' +
      '    samples.reserve(count);\n' +
      '\n' +
      '    for (size_t i = 0; i < count; ++i)\n' +
      '    {\n' +
      '        double longitude = 2.0 * M_PI * static_cast(i) / static_cast(count);\n' +
      '        double latitude = M_PI * static_cast(i) / static_cast(count) - M_PI / 2.0;\n' +
      '        double x = std::cos(latitude) * std::cos(longitude);\n' +
      '        double y = std::cos(latitude) * std::sin(longitude);\n' +
      '        double z = std::sin(latitude);\n' +
      '\n' +
      '        x = x * 1.4 + 0.25;\n' +
      '        y = y * 0.7 - 0.12;\n' +
      '        z = z * 1.2 + 0.08;\n' +
      '\n' +
      '        samples.push_back({x, y, z});\n' +
      '    }\n' +
      '    return samples;\n' +
      '}\n' +
      '\n' +
      'TEST_CASE("Calibration: generateMagnetometerMatrices returns 0 on empty input", "[calibration]")\n' +
      '{\n' +
      'Compare this snippet from include/puara/descriptors/simple_tilt_roll.h:\n' +
      '* #include \n' +
      ' *\n' +
      ' * puara_gestures::Coord3D imu_data{0.0, 0.0, 0.0};\n' +
      ' * puara_gestures::three_dof_tilt_roll tiltRoll(&imu_data);\n' +
      ' *\n' +
      ' * void setup() {\n' +
      ' *   // Initialize sensors and serial output here.\n' +
      ' * }\n' +
      ' *\n' +
      ' * void loop() {\n' +
      ' *   // Fill imu_data from your accelerometer and gyroscope.\n' +
      ' *   imu_data.x = readAccelX();\n' +
      ' *   imu_data.y = readAccelY();\n' +
      ' *   imu_data.z = readAccelZ();\n' +
      ' *\n' +
      ' *   tiltRoll.update();\n' +
      ' *\n' +
      ' *   double roll = tiltRoll.current_roll_value();\n' +
      ' *   double tilt = tiltRoll.current_tilt_value();\n' +
      ' *\n' +
      ' *   Serial.print("roll=");\n' +
      ' *   Serial.print(roll);\n' +
      ' *   Serial.print(" tilt=");\n' +
      ' *   Serial.println(tilt);\n' +
      ' * }\n' +
      ' * @endcode\n' +
      ' */\n' +
      'class Tilt_Roll\n' +
      '{\n' +
      'public:\n' +
      '  Tilt_Roll() noexcept\n' +
      '      : tied_x(nullptr)\n' +
      '      , tied_y(nullptr)\n' +
      '      , tied_z(nullptr)\n' +
      '  {\n' +
      '  }\n' +
      '\n' +
      '  Tilt_Roll(const Tilt_Roll&) noexcept = default;\n' +
      '  Tilt_Roll(Tilt_Roll&&) noexcept = default;\n' +
      '  Tilt_Roll& operator=(const Tilt_Roll&) noexcept = default;\n' +
      '  Tilt_Roll& operator=(Tilt_Roll&&) noexcept = default;\n' +
      '\n' +
      '  explicit Tilt_Roll(Coord3D* tied)\n' +
      '    : tied_x(&(tied->x))\n' +
      '    , tied_y(&(tied->y))\n' +
      '    , tied_z(&(tied->z))\n' +
      '  {\n' +
      '  }\n' +
      '\n' +
      '  int update(double accelx, double accely, double accelz)\n' +
      '  {\n' +
      '    // calculate polar representation of accelerometer data\n' +
      '    roll = atan2(accelz, accely);\n' +
      '    magnitude = sqrt(pow(accelz, 2) + pow(accely, 2));\n' +
      '    tilt = atan2(accelx, magnitude);\n' +
      '    magnitude = sqrt(pow(accelx, 2) + pow(magnitude, 2));\n' +
      '    magnitude *= 0.00390625;\n' +
      '\n' +
      '    return 1;\n' +
      '  }\n' +
      'Compare this snippet from tests/test_descriptors.cpp:\n' +
      '#include \n' +
      '\n' +
      '#include \n' +
      '#include \n' +
      '\n' +
      '#include \n' +
      '#include \n' +
      '#include \n' +
      '\n' +
      'using namespace puara_gestures;\n' +
      '\n' +
      'static double\n' +
      'readCsvDouble(const rapidcsv::Document& doc, const std::string& column, size_t row)\n' +
      '{\n' +
      '  return doc.GetCell(column, row);\n' +
      '}\n' +
      '\n' +
      'static std::filesystem::path getTestDataPath(std::string_view filename)\n' +
      '{\n' +
      '  const auto sourceDir = std::filesystem::path(__FILE__).parent_path();\n' +
      '  return sourceDir / "data" / filename;\n' +
      '}\n' +
      '\n' +
      'TEST_CASE("Roll descriptor follows reference CSV values", "[descriptors][roll]")\n' +
      '{\n' +
      '  const auto path = getTestDataPath("imu_data_roll.csv");\n' +
      '  REQUIRE(std::filesystem::exists(path));\n' +
      '  rapidcsv::Document doc(path.string(), rapidcsv::LabelParams(0, -1));\n' +
      '  const size_t rowCount = doc.GetRowCount();\n' +
      '\n' +
      '  Roll test;\n' +
      '  Imu9Axis imu_data;\n' +
      '  double maxDiff = 0.0;\n' +
      '\n' +
      '  for(size_t r = 0; r < rowCount; ++r)\n' +
      '  {\n' +
      '    const double timestamp = readCsvDouble(doc, "timestamp", r);\n' +
      '    imu_data.accl.x = readCsvDouble(doc, "accl_x", r);\n' +
      '    imu_data.accl.y = readCsvDouble(doc, "accl_y", r);\n' +
      '    imu_data.accl.z = readCsvDouble(doc, "accl_z", r);\n' +
      '    imu_data.gyro.x = readCsvDouble(doc, "gyro_x", r);\n' +
      '    imu_data.gyro.y = readCsvDouble(doc, "gyro_y", r);\n' +
      '    imu_data.gyro.z = readCsvDouble(doc, "gyro_z", r);\n' +
      '    imu_data.magn.x = readCsvDouble(doc, "mag_x", r);\n' +
      '    imu_data.magn.y = readCsvDouble(doc, "mag_y", r);\n' +
      '    imu_data.magn.z = readCsvDouble(doc, "mag_z", r);\n' +
      '\n' +
      '    const double expectedRoll = readCsvDouble(doc, "roll", r);\n' +
      '    const double measuredRoll\n' +
      '        = test.roll(imu_data.accl, imu_data.gyro, imu_data.magn, timestamp);\n' +
      '    const double diff = std::fabs(measuredRoll - expectedRoll);\n' +
      '\n' +
      '    if(r < 3)\n' +
      '    {\n' +
      '      std::cerr << "DEBUG roll row=" << r << " ts=" << timestamp\n' +
      '                << " accl=" << imu_data.accl.x << "," << imu_data.accl.y << ","\n' +
      '                << imu_data.accl.z << " gyro=" << imu_data.gyro.x << ","\n' +
      '                << imu_data.gyro.y << "," << imu_data.gyro.z\n' +
      '                << " mag=" << imu_data.magn.x << "," << imu_data.magn.y << ","\n' +
      '                << imu_data.magn.z << " expected=" << expectedRoll\n' +
      'Compare this snippet from 3rdparty/IMU_Sensor_Fusion/imu_orientation.h:\n' +
      '*                                                                         *\n' +
      ' ***************************************************************************/\n' +
      '\n' +
      '#ifndef IMU_ORIENTATION_H\n' +
      '#define IMU_ORIENTATION_H\n' +
      '\n' +
      '// Add our own type\n' +
      '#ifdef SENSOR_FUSION_FLOATS\n' +
      '    typedef float sfFloat;\n' +
      '#else\n' +
      '    typedef double sfFloat;\n' +
      '#endif\n' +
      '\n' +
      '// Add definitions of M_PI just in case\n' +
      '// Define sfFloat versions of M_PI and M_PI_2\n' +
      '\n' +
      '#ifdef M_PI\n' +
      '    #define M_PIF        sfFloat(M_PI)\n' +
      '#else\n' +
      '    #define M_PIF        sfFloat(3.14159265358979323846)\n' +
      '#endif\n' +
      '#ifdef M_PI_2\n' +
      '    #define M_PI_2F      sfFloat(M_PI_2)\n' +
      '#else\n' +
      '    #define M_PI_2F      sfFloat(1.57079632679489661923f)\n' +
      '#endif\n' +
      '\n' +
      'class IMU_Orientation {\n' +
      '  public:\n' +
      '    IMU_Orientation(): quaternion(1,0,0,0)\n' +
      '    {\n' +
      '        accel.x = accel.y = accel.z = accel.magnitude = sfFloat(0);\n' +
      '        gyro.x = gyro.y = gyro.z = gyro.magnitude = sfFloat(0);\n' +
      '        gyro_bias.x = gyro_bias.y = gyro_bias.z = gyro_bias.magnitude = sfFloat(0);\n' +
      '        mag.x = mag.y = mag.z = mag.magnitude = sfFloat(0);\n' +
      '        euler.tilt = sfFloat(0);\n' +
      '        euler.roll = sfFloat(0);\n' +
      '        euler.azimuth = sfFloat(0);\n' +
      '    }\n' +
      '    ~IMU_Orientation() {}\n' +
      '  \n' +
      '    // Data structures\n' +
      '    class Quaternion\n' +
      '    {\n' +
      '    public:\n' +
      '        Quaternion(): w(1), x(0), y(0), z(0) {}\n' +
      '        Quaternion(sfFloat w, sfFloat x, sfFloat y, sfFloat z): w(w), x(x), y(y), z(z) {}\n' +
      '        Quaternion(const Quaternion&) = default;\n' +
      '        Quaternion& operator= (const Quaternion&) = default;\n' +
      '\n' +
      '        ~Quaternion() {}\n' +
      '\n' +
      '        Quaternion operator*(Quaternion& rhs);\n' +
      '\n' +
      '        Quaternion inverse();\n' +
      '        Quaternion conjugate();\n' +
      '        sfFloat dotProduct(Quaternion &q);\n' +
      '        Quaternion slerp(Quaternion &q, sfFloat weight);\n' +
      '        void normalize();\n' +
      '        void minimizeDistance(Quaternion &q);\n' +
      'Compare this snippet from include/puara/descriptors/tilt.h:\n' +
      '#pragma once\n' +
      '\n' +
      '#include "IMU_Sensor_Fusion/imu_orientation.h"\n' +
      '#include \n' +
      '#include \n' +
      '\n' +
      '#include \n' +
      '\n' +
      'namespace puara_gestures\n' +
      '{\n' +
      '\n' +
      '/**\n' +
      ' * @file tilt.h\n' +
      ' * @brief Tilt estimator using accelerometer, gyroscope, and magnetometer data.\n' +
      ' *\n' +
      ' * This class wraps the IMU_Sensor_Fusion orientation filter and returns a\n' +
      ' * filtered tilt value in radians.\n' +
      ' *\n' +
      ' * Example:\n' +
      ' * @code\n' +
      ' * #include \n' +
      ' *\n' +
      ' * puara_gestures::Coord3D accel{0.0, 0.0, 1.0};\n' +
      ' * puara_gestures::Coord3D gyro{0.0, 0.0, 0.0};\n' +
      ' * puara_gestures::Coord3D mag{0.3, 0.0, 0.5};\n' +
      ' * puara_gestures::Tilt tilt;\n' +
      ' *\n' +
      ' * void setup() {\n' +
      ' *   // sensor and serial initialization\n' +
      ' * }\n' +
      ' *\n' +
      ' * void loop() {\n' +
      ' *   // Read your IMU sensors into accel, gyro, mag\n' +
      ' *   double period = 0.01; // seconds since last sample\n' +
      ' *   double tiltValue = tilt.tilt(accel, gyro, mag, period);\n' +
      ' *   Serial.print("tilt=");\n' +
      ' *   Serial.println(tiltValue);\n' +
      ' * }\n' +
      ' * @endcode\n' +
      ' */\n' +
      'class Tilt : public utils::Smooth\n' +
      '{\n' +
      'public:\n' +
      '  IMU_Orientation orientation;\n' +
      '\n' +
      '  using utils::Smooth::Smooth;\n' +
      '\n' +
      '  /**\n' +
      '   * @brief Calculates tilt (aka "pitch") measurement\n' +
      '   *\n' +
      "   * @param accel Measured in G's\n" +
      '   * @param gyro Measured in degrees/sec\n' +
      '   * @param mag Measured in Gauss\n' +
      '   * @param period_sec Measured in seconds\n' +
      '   *\n' +
      '   * @return Output range of [- PI /2, PI /2]\n' +
      '   */\n' +
      '  double tilt(Coord3D accel, Coord3D gyro, Coord3D mag, double period_sec)\n' +
      '  {\n' +
      '    orientation.setAccelerometerValues(accel.x, accel.y, accel.z);\n' +
      'Compare this snippet from tests/platformio/src/main.cpp:\n' +
      'ok &= almostEqual(val3d.x, 1.0);\n' +
      '  ok &= almostEqual(val3d.y, 0.5);\n' +
      '  ok &= almostEqual(val3d.z, 0.2);\n' +
      '\n' +
      '  logResult(ok, name);\n' +
      '}\n' +
      '\n' +
      'static void testIMUFilters() {\n' +
      '  const char* name = "IMU filter quaternion normalization";\n' +
      '\n' +
      '  puara_gestures::Imu9Axis imu{\n' +
      '      {0.0, 0.0, 9.81},\n' +
      '      {1.0, 2.0, 3.0},\n' +
      '      {0.3, 0.0, 0.5}\n' +
      '  };\n' +
      '\n' +
      '  bool ok = true;\n' +
      '\n' +
      '  puara_gestures::MadgwickQuaternionFilter madgwick(0.1);\n' +
      '  ok &= (madgwick.update(imu, true) == false);\n' +
      '  delay(5);\n' +
      '  ok &= (madgwick.update(imu, true) == true);\n' +
      '  ok &= almostEqual(madgwick.getQuaternion().w * madgwick.getQuaternion().w +\n' +
      '                    madgwick.getQuaternion().x * madgwick.getQuaternion().x +\n' +
      '                    madgwick.getQuaternion().y * madgwick.getQuaternion().y +\n' +
      '                    madgwick.getQuaternion().z * madgwick.getQuaternion().z,\n' +
      '                    1.0);\n' +
      '\n' +
      '  puara_gestures::MahonyQuaternionFilter mahony(1.0, 0.0);\n' +
      '  ok &= (mahony.update(imu, true) == false);\n' +
      '  delay(5);\n' +
      '  ok &= (mahony.update(imu, true) == true);\n' +
      '  ok &= almostEqual(mahony.getQuaternion().w * mahony.getQuaternion().w +\n' +
      '                    mahony.getQuaternion().x * mahony.getQuaternion().x +\n' +
      '                    mahony.getQuaternion().y * mahony.getQuaternion().y +\n' +
      '                    mahony.getQuaternion().z * mahony.getQuaternion().z,\n' +
      '                    1.0);\n' +
      '\n' +
      '  puara_gestures::KalmanQuaternionFilter kalman(0.001, 0.01);\n' +
      '  ok &= (kalman.update(imu, true) == false);\n' +
      '  delay(5);\n' +
      '  ok &= (kalman.update(imu, true) == true);\n' +
      '  ok &= almostEqual(kalman.getQuaternion().w * kalman.getQuaternion().w +\n' +
      '                    kalman.getQuaternion().x * kalman.getQuaternion().x +\n' +
      '                    kalman.getQuaternion().y * kalman.getQuaternion().y +\n' +
      '                    kalman.getQuaternion().z * kalman.getQuaternion().z,\n' +
      '                    1.0);\n' +
      '\n' +
      '  logResult(ok, name);\n' +
      '}\n' +
      '\n' +
      'static void testEmbeddedMagnetometerCalibration() {\n' +
      '  const char* name = "Embedded magnetometer calibration";\n' +
      '  constexpr size_t sampleCount = 24;\n' +
      '  puara_gestures::Coord3D samples[sampleCount];\n' +
      '\n' +
      '  for (size_t i = 0; i < sampleCount; ++i) {\n' +
      '    const double longitude = 2.0 * M_PI * static_cast(i) / static_cast(sampleCount);\n' +
      '    const double latitude = M_PI * static_cast(i) / static_cast(sampleCount) - M_PI / 2.0;\n' +
      '    double x = std::cos(latitude) * std::cos(longitude);',
    'These are recently edited files. Do not suggest code that has been deleted.\n' +
      'File: include/puara/utils/circularbuffer.h\n' +
      '--- a/file:///home/chu/Desktop/soft/sat_soft/puara-gestures/include/puara/utils/circularbuffer.h\n' +
      '+++ b/file:///home/chu/Desktop/soft/sat_soft/puara-gestures/include/puara/utils/circularbuffer.h\n' +
      '@@ -49,7 +49,7 @@\n' +
      '   /** \n' +
      '    * @brief Underlying storage for circular buffer elements. \n' +
      '    * */\n' +
      '+  boost::circular_buffer buffer = boost::circular_buffer(size);\n' +
      '-  boost::circular_buffer buffer ; --- IGNORE ---\n' +
      ' \n' +
      '   CircularBuffer(const CircularBuffer&) = default;\n' +
      '   CircularBuffer(CircularBuffer&&) noexcept = default;\n' +
      'File: include/puara/utils/kalmanQuaternion.h\n' +
      '--- a/file:///home/chu/Desktop/soft/sat_soft/puara-gestures/include/puara/utils/kalmanQuaternion.h\n' +
      '+++ b/file:///home/chu/Desktop/soft/sat_soft/puara-gestures/include/puara/utils/kalmanQuaternion.h\n' +
      '@@ -243,7 +243,7 @@\n' +
      '     }\n' +
      ' \n' +
      '     static void normalizeQuaternion(Quaternion& q) {\n' +
      '+        double norm = std::hypot(std::hypot(q.w, q.x), std::hypot(q.y, q.z));\n' +
      '-        double norm = std::sqrt(q.w * q.w + q.x * q.x + q.y * q.y + q.z * q.z); --- IGNORE ---\n' +
      '         if (norm == 0.0) {\n' +
      '             q = {1.0, 0.0, 0.0, 0.0};\n' +
      '             return;\n' +
      'End of recent edits'
  ],
  isFimEnabled: true
}
Trace: [NES][DiagnosticsNextEditProvider] DiagnosticsInlineCompletionProvider runUntilNextEdit complete (cancelled)
Trace: [NES][NextEditProvider][f36b][_getNextEdit][fetchNextEdit][_executeNewNextEditRequest][streamEnd] no edit, reason: gotCancelled
Trace: [NES][NextEditProvider][f36b][_getNextEdit] resolved firstEdit promise
Trace: [NES][NextEditProvider][f36b][_getNextEdit] First edit latency: 553 ms
Trace: [NES][NextEditProvider][f36b][_getNextEdit] failed to fetch next edit gotCancelled:afterDebounce
Trace: [NES][NextEditProvider][f36b][_getNextEdit] had no edit
Trace: [NES][Provider][provideInlineCompletionItems][f36b] Return: lost race to cancellation
Trace: [NES][Provider][handleListEndOfLifetime][f36b] List icr-f36b690a-3a5d-4500-b83c-abf1cad78ed1 disposed, reason: TokenCancellation
Info: ccreq:83a5c836.copilotmd | markdown
Debug: [ghostText] All choices redacted
Debug: [AsyncCompletionManager] [e50df62c-abb1-425a-984d-4ddbf580ccbb] Request failed with all choices redacted
Debug: [AsyncCompletionManager] [e50df62c-abb1-425a-984d-4ddbf580ccbb] No matching completions found
Trace: [Ghost][CopilotInlineCompletionItemProvider][provideInlineCompletionItems][GhostTextProvider][provideInlineCompletionItems][GhostTextComputer#getGhostText][GhostTextComputer#getGhostTextWithoutAbortHandling] Network request returned no results
Debug: [getCompletions] No ghostText produced -- empty: received no results from async completions
Trace: [NES][DiagnosticsInlineCompletionProvider] Diagnostics changed received in processor: 
Trace: [NES][DiagnosticsInlineCompletionProvider] Diagnostics changed received in processor: 
Trace: [NES][Triggerer][onDidChangeTextEditorSelection][editorSwitch] Return: document switch didn't happen
Trace: [NES][Triggerer][onDidChangeTextEditorSelection] Return: no recent edit
Trace: [NES][DiagnosticsInlineCompletionProvider] Diagnostics changed received in processor: 
Request IDs
f8d22e0b-f377-424d-86db-39419b263f9e
c6d27be1-62d2-48f0-b560-bc3f2a0b6764
8691891f-7269-4123-a210-bf825dcfc75b
18ce37ff-98a5-4575-879b-dbe9127f6d70
bc558384-7b62-4677-984e-6624dd5848e8
00d1af54-c07d-4627-893e-b5968f0b67ea
40be4929-89d5-4e86-8867-674f73730047
0d241de1-80ce-4cd4-994b-c8c4f751689e
669938c2-8b4d-4837-b15e-74d22c07d320
e9a14ff7-9c9f-4986-ae91-22cd39dd1a7f
26fe38e8-d708-4347-adca-f224739f19c3
992dc69c-a63f-4825-a274-dbaa3f57c474
6f77afcc-07fa-4566-a837-db5c1c4e9971
106ddc99-98a7-4f45-9f42-4945a952346b
85b8cef5-bf7d-484c-bc7d-6ecf02775d34
33e547c6-34fd-42e2-aa44-66233e4a7925
bddc2f5a-ee77-4baa-bc6d-51b782f775e2
5b621a32-b6fa-4818-af9f-5040c0f2a8f0
0515d10d-9038-464f-b2ee-5d7312bb7fa6
a37e7063-6946-4601-84ef-f1d19eecbd5f
4b573f23-cb76-4092-97ca-401bf9dca4e1
7e96b442-40fb-49a2-baec-be2d3d233f01
78bb2f78-ab04-4760-a235-5a4a6d044031
88282110-a3c8-48fa-b29f-561858d1dd80
4dcb240d-13c2-4e2b-8c6b-78095eb5d39b
c0f9d5a0-a7a1-4333-8c3b-c273f421fb98
5a299d84-0621-4ead-8d79-89678dba72d9
2df273d6-d22b-42c4-aa36-134a6103d668
4ef2dea5-ccf0-4151-bb9b-1ded2248f64e
b963930a-5a92-4361-a02f-a4cfa4ba1880
cd67292a-09a5-4dc5-8179-f11c5f988bd0
e8ff3236-9b83-44e9-b1cc-a46844ad2ddd
56875044-2a9d-46af-b356-25056268376c
906cac51-066a-449b-8496-4ef0b3bd0993
db562314-9f05-4413-ace2-3cbed46e1ee2
3b0f37a2-2cad-41d8-9098-260e8e721850
16d72779-249a-46cd-a72b-8b72ad98576b
12223503-3776-46ba-8c23-400ad4ce6e4c
f3b97613-e92a-4a25-bf64-038cfd2e62d4
4d8f4015-50c5-4534-84c4-fc6a49d315f1
8b91f3f8-1504-46dd-83e4-918e290be94e
3d004811-8ce1-42d5-a5e9-061addd97753
f80a82b4-1141-4c4f-939c-428f9a2c6d5e
ed0018ed-12ee-49e4-8e45-7fe86e2fa83c
d5beb883-69b1-46ad-8fa6-71c9b7c18e6b
ed8719b5-3642-429d-b20f-206a7161ce2f
a9c3fd44-c3f0-4dcb-97a2-65fd2c61b475
4d235b34-6730-44a3-b792-f9d2db20a800
aa2f0f44-10b0-4db0-b7f7-3e135b0c8014
System Info
Item Value
CPUs Intel(R) Core(TM) i7-10750H CPU @ 2.60GHz (12 x 3500)
GPU Status 2d_canvas: enabled
GPU0: VENDOR= 0x10de, DEVICE=0x1f15, DRIVER_VENDOR=Mesa, DRIVER_VERSION=24.0.9
GPU1: VENDOR= 0x8086, DEVICE=0x9bc4, DRIVER_VENDOR=Mesa, DRIVER_VERSION=24.0.9 ACTIVE
Machine model name:
Machine model version:
direct_rendering_display_compositor: disabled_off_ok
gpu_compositing: enabled
multiple_raster_threads: enabled_on
opengl: enabled_on
rasterization: enabled
raw_draw: disabled_off_ok
skia_graphite: disabled_off
trees_in_viz: disabled_off
video_decode: enabled
video_encode: disabled_software
vulkan: disabled_off
webgl: enabled
webgl2: enabled
webgpu: disabled_off
webnn: disabled_off
Load (avg) 2, 2, 2
Memory (System) 15.27GB (6.44GB free)
Process Argv --crash-reporter-id 434156e3-a401-48f6-a7cd-123c69f0ffa9
Screen Reader no
VM 0%
DESKTOP_SESSION xubuntu
XDG_CURRENT_DESKTOP XFCE
XDG_SESSION_DESKTOP xubuntu
XDG_SESSION_TYPE x11
A/B Experiments
vsliv368:30146709
binariesv615:30325510
nativeloc1:31344060
dwcopilot:31170013
dwoutputs:31242946
copilot_t_ci:31333650
e5gg6876:31282496
pythonrdcb7:31342333
6518g693:31463988
aj953862:31281341
4f60g487:31327383
6abeh943:31336334
envsdeactivate2:31464701
cloudbuttont:31379625
3efgi100_wstrepl:31403338
ec5jj548:31422691
cp_cls_t_966_ss:31454198
a9239246:31499107
4je02754:31466945
8hhj4413:31478653
ge8j1254_inline_auto_hint_haiku:31490510
38bie571_auto:31478678
cp_cls_t_1081:31454832
conptydll_true:31498968
ia-use-proxy-models-svc:31452481
e9c30283:31461165
test_treatment2:31471001
c9b86496:31447327
control_6dc23131:31497324
idci7584:31464702
e3e4d672:31494082
ei9d7968:31496641
534a6447:31496642
nes-extended-on:31455476
chat:31457767
8hig5102:31480529
89g7j272:31500881
7e187181:31503455
cpptoolsoff-v2:31475362
i2gc6536:31499202
1g3cj959:31501677
ghj88844:31499326
23c7c724:31491644
client_tst_t:31495907
ddid_c:31478207
getcmakediagnosticsoff:31489825
pro_large_t:31499376
cp_cls_c_1082:31491634
719di409_sum_t:31499347
logging_enabled_new:31498466
j0d79568:31499440
nes-dist-check-ctrl:31503268
748c7209:31497895

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type
No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions