2.3: Implementation with AI
AI-Assisted C Coding (SWE.3)
Setup: GitHub Copilot for Embedded C
Development Environment:
- IDE: VS Code v1.85
- Extension: GitHub Copilot v1.145
- Language: C99 (ISO/IEC 9899:1999)
- Coding Standard: MISRA C:2012 (mandatory rules enforced)
- Compiler: Tasking TriCore C Compiler v6.3r1
Copilot Configuration (.vscode/settings.json):
{
"github.copilot.enable": {
"*": true,
"c": true
},
"github.copilot.inlineSuggest.enable": true,
"C_Cpp.cppStandard": "c99",
"C_Cpp.cStandard": "c99",
"editor.suggest.snippetsPreventQuickSuggestions": false,
"editor.inlineSuggest.enabled": true,
"files.associations": {
"*.h": "c",
"*.c": "c"
}
}
Example 1: AI-Generated PID Controller
Prompt Engineering for Safety-Critical Code
Developer Prompt (to GitHub Copilot):
/**
* @brief PID controller for ACC distance regulation
* @implements [SWE-022] Speed Controller
* @safety ASIL-B (ISO 26262)
* @standard MISRA C:2012
*
* Requirements:
* - Input: target_distance (meters), actual_distance (meters), dt (seconds)
* - Output: acceleration command (m/s²), range: [-3.0, +3.0]
* - Algorithm: PID with anti-windup
* - Calibration: Kp, Ki, Kd from NvM
* - Safety: Saturation limits, no division by zero
*/
float ACC_PID_Controller(
float target_distance_m,
float actual_distance_m,
float dt_s
)
{
// Copilot: Generate MISRA-compliant PID implementation
Copilot Generated Code (80% complete, developer reviews):
float ACC_PID_Controller(
float target_distance_m,
float actual_distance_m,
float dt_s
)
{
/* Static variables for integral and previous error (MISRA 8.9: declare at function scope) */
static float integral_term = 0.0f;
static float previous_error = 0.0f;
/* Calibration parameters from NvM (ASIL-B: values validated at startup) */
const float Kp = CAL_PID_Kp; /* Default: 0.5 */
const float Ki = CAL_PID_Ki; /* Default: 0.1 */
const float Kd = CAL_PID_Kd; /* Default: 0.2 */
/* Calculate error (MISRA 10.4: no mixed type operations) */
float error = target_distance_m - actual_distance_m;
/* Proportional term (MISRA 12.1: precedence explicit) */
float proportional = Kp * error;
/* Integral term with anti-windup (MISRA 14.3: avoid infinite loop) */
integral_term += (error * dt_s);
/* Anti-windup: Clamp integral (MISRA 12.5: no side effects in conditional) */
if (integral_term > 10.0f)
{
integral_term = 10.0f;
}
else if (integral_term < -10.0f)
{
integral_term = -10.0f;
}
else
{
/* No action needed (MISRA 15.7: all if-else branches must have compound statement) */
}
float integral = Ki * integral_term;
/* Derivative term (MISRA 21.1: avoid division by zero) */
float derivative = 0.0f;
if (dt_s > 0.001f) /* Minimum time step: 1ms */
{
derivative = (error - previous_error) / dt_s;
}
else
{
/* dt too small, skip derivative (MISRA 15.7) */
}
float derivative_term = Kd * derivative;
/* Update previous error for next cycle */
previous_error = error;
/* PID output (MISRA 12.1: explicit parentheses) */
float output = proportional + integral + derivative_term;
/* Safety saturation (ASIL-B: limit acceleration to ±3 m/s²) */
if (output > 3.0f)
{
output = 3.0f;
}
else if (output < -3.0f)
{
output = -3.0f;
}
else
{
/* Output within limits (MISRA 15.7) */
}
return output;
}
Developer Review (20% effort):
// [PASS] APPROVED: MISRA compliant, logic correct
// [PASS] Anti-windup implemented
// [PASS] Division by zero check
// [PASS] Safety saturation
// [WARN] MINOR FIX: Add range check on inputs
// Add input validation (ASIL-B defense):
if ((target_distance_m < 0.0f) || (target_distance_m > 200.0f))
{
return 0.0f; /* Invalid input, safe default: no acceleration */
}
if ((actual_distance_m < 0.0f) || (actual_distance_m > 200.0f))
{
return 0.0f;
}
Time Saved: 45 minutes → 10 minutes (78% reduction)
Example 2: Sensor Fusion Kalman Filter
AI-Generated Complex Algorithm
Developer Prompt:
/**
* @brief Extended Kalman Filter for radar + camera fusion
* @implements [SWE-023] Sensor Fusion Algorithm
* @safety ASIL-B
*
* State vector: [distance, velocity]
* Measurements: radar_distance, radar_velocity, camera_distance
*
* Requirements:
* - Prediction step: state = F * prev_state
* - Update step: Kalman gain, innovation
* - Covariance propagation
* - MISRA C:2012 compliant
*/
void EKF_SensorFusion(
float radar_distance_m,
float radar_velocity_mps,
float camera_distance_m,
bool camera_valid,
float* fused_distance_m,
float* fused_velocity_mps,
float* confidence
)
{
// Copilot: Generate EKF implementation
Copilot Output (requires significant review for safety):
void EKF_SensorFusion(
float radar_distance_m,
float radar_velocity_mps,
float camera_distance_m,
bool camera_valid,
float* fused_distance_m,
float* fused_velocity_mps,
float* confidence
)
{
/* State vector: [distance, velocity] (MISRA 9.1: initialize all variables) */
static float state[2] = {50.0f, 0.0f}; /* Initial: 50m, 0 m/s */
static float covariance[2][2] = {{1.0f, 0.0f}, {0.0f, 1.0f}};
/* System model: state transition matrix (MISRA 8.11: static storage) */
const float dt = 0.05f; /* 50ms cycle time */
const float F[2][2] = {{1.0f, dt}, {0.0f, 1.0f}};
/* Process noise covariance (tunable) */
const float Q[2][2] = {{CAL_EKF_Q_Distance, 0.0f},
{0.0f, CAL_EKF_Q_Velocity}};
/* Measurement noise covariance (radar: 1m, camera: 2m) */
const float R_radar = 1.0f;
const float R_camera = 2.0f;
/* --- PREDICTION STEP --- */
/* Predict state: state_pred = F * state */
float state_pred[2];
state_pred[0] = (F[0][0] * state[0]) + (F[0][1] * state[1]);
state_pred[1] = (F[1][0] * state[0]) + (F[1][1] * state[1]);
/* Predict covariance: P_pred = F * P * F' + Q */
float P_pred[2][2];
/* Simplified calculation (full matrix multiplication omitted for brevity) */
P_pred[0][0] = covariance[0][0] + Q[0][0];
P_pred[1][1] = covariance[1][1] + Q[1][1];
P_pred[0][1] = covariance[0][1];
P_pred[1][0] = covariance[1][0];
/* --- UPDATE STEP (RADAR) --- */
/* Measurement: z_radar = [distance, velocity] */
float z_radar[2] = {radar_distance_m, radar_velocity_mps};
/* Measurement matrix H (identity for direct measurement) */
const float H[2][2] = {{1.0f, 0.0f}, {0.0f, 1.0f}};
/* Innovation: y = z - H * state_pred */
float innovation[2];
innovation[0] = z_radar[0] - state_pred[0];
innovation[1] = z_radar[1] - state_pred[1];
/* Innovation covariance: S = H * P_pred * H' + R */
float S[2][2];
S[0][0] = P_pred[0][0] + R_radar;
S[1][1] = P_pred[1][1] + R_radar;
S[0][1] = P_pred[0][1];
S[1][0] = P_pred[1][0];
/* Kalman gain: K = P_pred * H' * S^-1 */
/* Simplified: K = P_pred / S (scalar approximation for diagonal S) */
float K[2][2];
K[0][0] = P_pred[0][0] / S[0][0];
K[1][1] = P_pred[1][1] / S[1][1];
K[0][1] = 0.0f;
K[1][0] = 0.0f;
/* State update: state = state_pred + K * innovation */
state[0] = state_pred[0] + (K[0][0] * innovation[0]);
state[1] = state_pred[1] + (K[1][1] * innovation[1]);
/* Covariance update: P = (I - K * H) * P_pred */
covariance[0][0] = (1.0f - K[0][0]) * P_pred[0][0];
covariance[1][1] = (1.0f - K[1][1]) * P_pred[1][1];
/* --- CAMERA FUSION (if valid) --- */
if (camera_valid == true)
{
/* Innovation from camera (distance only) */
float camera_innovation = camera_distance_m - state[0];
/* Kalman gain for camera */
float S_camera = covariance[0][0] + R_camera;
float K_camera = covariance[0][0] / S_camera;
/* Update state with camera measurement */
state[0] += K_camera * camera_innovation;
/* Update covariance */
covariance[0][0] = (1.0f - K_camera) * covariance[0][0];
}
else
{
/* Camera invalid, radar-only mode (MISRA 15.7: mandatory else) */
}
/* --- OUTPUT --- */
*fused_distance_m = state[0];
*fused_velocity_mps = state[1];
/* Confidence metric: inverse of trace(P) (lower covariance = higher confidence) */
float trace_P = covariance[0][0] + covariance[1][1];
if (trace_P > 0.001f)
{
*confidence = 1.0f / trace_P; /* Range: 0-1000 */
}
else
{
*confidence = 1000.0f; /* Maximum confidence */
}
}
Developer Review (30% effort):
- [PASS] Algorithm structure correct
- [WARN] FIX NEEDED: Full matrix operations simplified (introduce error)
- [WARN] FIX NEEDED: Add input validation (range checks)
- [WARN] FIX NEEDED: Handle matrix inversion for non-diagonal S
Lesson: Copilot excellent for boilerplate, but complex math requires expert review.
AI-Generated Code Review Checklist: For safety-critical code, apply this checklist to AI-generated implementations: (1) Input validation present, (2) Range checks on calculations, (3) Division-by-zero protection, (4) MISRA compliance verified, (5) Safety saturation limits, (6) Documented assumptions. See Chapter 35 for comprehensive review guidance.
MISRA C Compliance with AI
Static Analysis Integration
Tool: LDRA TBvision (MISRA C:2012 checker)
Process:
- Developer writes code with Copilot assistance
- Pre-commit hook runs MISRA check
- Violations flagged, Copilot suggests fixes
Example Violation:
$ ldra_check src/ACC_Control.c
MISRA C:2012 Rule 10.4 Violation:
Line 45: Operands of arithmetic operation have different essential types
Code: float output = target_distance_m - actual_distance_m;
^
Issue: Mixed float and double (actual_distance_m is double)
AI-Assisted Fix (Copilot suggestion):
// Before (violation)
float output = target_distance_m - actual_distance_m; // actual_distance_m is double
// After (Copilot fix)
float output = target_distance_m - (float)actual_distance_m; /* Explicit cast (MISRA 10.4) */
MISRA Compliance Results:
- Before AI: 12 violations/1000 SLOC (manual coding)
- After AI + Review: 2 violations/1000 SLOC (83% reduction)
- Compliance Rate: 99.8% (0.2% = advisory rules, acceptable)
Static Analysis Tool Integration: LDRA TBvision is used in this example, but alternatives include Polyspace (MathWorks), PC-lint Plus (Gimpel), QA-C (Perforce), and Parasoft C/C++test. The key is integrating the tool into your pre-commit or CI workflow for continuous compliance checking.
Unit Test Generation (SWE.4)
AI-Generated Test Cases
Tool: GitHub Copilot + VectorCAST
Prompt:
/**
* Unit tests for ACC_PID_Controller()
* Requirements: [SWE-022] Speed Controller
* Coverage target: 85% branch coverage (ASIL-B)
*
* Test scenarios:
* 1. Normal operation: target > actual (accelerate)
* 2. Normal operation: target < actual (decelerate)
* 3. Edge case: target = actual (no change)
* 4. Boundary: output saturation (+3 m/s²)
* 5. Boundary: output saturation (-3 m/s²)
* 6. Invalid input: negative distance
* 7. Invalid input: distance > 200m
*/
void test_ACC_PID_Controller(void)
{
// Copilot: Generate test cases
Copilot Generated Tests:
#include "unity.h" /* Unity test framework */
#include "ACC_Control.h"
/* Test 1: Accelerate scenario */
void test_PID_Accelerate(void)
{
float target = 60.0f; /* Target: 60 meters */
float actual = 50.0f; /* Actual: 50 meters */
float dt = 0.05f; /* 50ms */
float output = ACC_PID_Controller(target, actual, dt);
/* Expected: positive output (accelerate to close gap) */
TEST_ASSERT_GREATER_THAN(0.0f, output);
TEST_ASSERT_LESS_OR_EQUAL(3.0f, output); /* Within saturation limit */
}
/* Test 2: Decelerate scenario */
void test_PID_Decelerate(void)
{
float target = 50.0f;
float actual = 60.0f;
float dt = 0.05f;
float output = ACC_PID_Controller(target, actual, dt);
/* Expected: negative output (decelerate, increase gap) */
TEST_ASSERT_LESS_THAN(0.0f, output);
TEST_ASSERT_GREATER_OR_EQUAL(-3.0f, output);
}
/* Test 3: Steady state */
void test_PID_SteadyState(void)
{
float target = 55.0f;
float actual = 55.0f;
float dt = 0.05f;
float output = ACC_PID_Controller(target, actual, dt);
/* Expected: output near zero (no correction needed) */
TEST_ASSERT_FLOAT_WITHIN(0.1f, 0.0f, output);
}
/* Test 4: Saturation (max acceleration) */
void test_PID_SaturationPositive(void)
{
float target = 100.0f; /* Large error */
float actual = 10.0f;
float dt = 0.05f;
float output = ACC_PID_Controller(target, actual, dt);
/* Expected: saturated at +3 m/s² */
TEST_ASSERT_EQUAL_FLOAT(3.0f, output);
}
/* Test 5: Saturation (max deceleration) */
void test_PID_SaturationNegative(void)
{
float target = 10.0f;
float actual = 100.0f; /* Large negative error */
float dt = 0.05f;
float output = ACC_PID_Controller(target, actual, dt);
/* Expected: saturated at -3 m/s² */
TEST_ASSERT_EQUAL_FLOAT(-3.0f, output);
}
/* Test 6: Invalid input (negative distance) */
void test_PID_InvalidInputNegative(void)
{
float target = -10.0f; /* Invalid */
float actual = 50.0f;
float dt = 0.05f;
float output = ACC_PID_Controller(target, actual, dt);
/* Expected: safe default (0 acceleration) */
TEST_ASSERT_EQUAL_FLOAT(0.0f, output);
}
/* Test 7: Invalid input (distance out of range) */
void test_PID_InvalidInputOutOfRange(void)
{
float target = 250.0f; /* > 200m limit */
float actual = 50.0f;
float dt = 0.05f;
float output = ACC_PID_Controller(target, actual, dt);
/* Expected: safe default */
TEST_ASSERT_EQUAL_FLOAT(0.0f, output);
}
/* Test suite runner */
int main(void)
{
UNITY_BEGIN();
RUN_TEST(test_PID_Accelerate);
RUN_TEST(test_PID_Decelerate);
RUN_TEST(test_PID_SteadyState);
RUN_TEST(test_PID_SaturationPositive);
RUN_TEST(test_PID_SaturationNegative);
RUN_TEST(test_PID_InvalidInputNegative);
RUN_TEST(test_PID_InvalidInputOutOfRange);
return UNITY_END();
}
Coverage Results (VectorCAST):
Function: ACC_PID_Controller()
Statement Coverage: 100% (28/28 statements)
Branch Coverage: 92% (11/12 branches)
MC/DC Coverage: 88% (ASIL-B requires 85% [PASS])
Uncovered Branch:
Line 67: else clause for (dt > 0.001f) never executed
Rationale: dt always 50ms in normal operation, edge case in fault mode
Action: Add fault injection test for dt=0 scenario
Time Saved: 6 hours (manual test writing) → 1.5 hours (AI + review) = 75% reduction
Summary: AI Productivity Gains
Measured Results (Month 3-8, 25,000 SLOC)
| Activity | Traditional Time | AI-Assisted Time | Savings |
|---|---|---|---|
| Function Implementation | 200 hours | 120 hours | 40% |
| MISRA Compliance | 80 hours | 30 hours | 62% |
| Unit Test Development | 150 hours | 40 hours | 73% |
| Code Review | 100 hours | 80 hours | 20% |
| Documentation (Doxygen) | 60 hours | 15 hours | 75% |
| Total | 590 hours | 285 hours | 52% |
Overall Productivity: 52% time reduction with AI assistance
Quality Impact:
- Defect density: 1.6 defects/KLOC (better than 2.0 target)
- MISRA compliance: 99.8% (exceeds 95% target)
- Unit test coverage: 89% (exceeds 85% ASIL-B requirement)
Next: Verification and validation (25.04).