AI-Driven Predictive Maintenance Tool for Railway Infrastructure TypeScript
👤 Sharing: AI
```typescript
// Define data types for sensors and infrastructure components
interface SensorData {
timestamp: Date;
sensorId: string;
value: number;
unit: string;
}
interface InfrastructureComponent {
componentId: string;
componentType: 'track' | 'switch' | 'bridge' | 'signal';
installationDate: Date;
maintenanceSchedule: string; // e.g., 'every 6 months' or CRON expression
location: {
latitude: number;
longitude: number;
};
sensorIds: string[]; // Array of sensor IDs associated with this component
}
interface MaintenanceRecord {
recordId: string;
componentId: string;
date: Date;
type: 'inspection' | 'repair' | 'replacement';
description: string;
cost: number;
}
// Define a simple machine learning model interface (replace with actual ML implementation)
interface PredictionModel {
train(data: SensorData[], component: InfrastructureComponent): void;
predict(data: SensorData[], component: InfrastructureComponent): number; // Returns a risk score (0-1)
}
// Implement a basic linear regression model (Illustrative, replace with more sophisticated ML)
class LinearRegressionModel implements PredictionModel {
private slope: number = 0;
private intercept: number = 0;
private trained: boolean = false;
train(data: SensorData[], component: InfrastructureComponent): void {
// Simplified training: Linear regression assumes a linear relationship
// For demo purposes, assume the 'value' of the sensor is directly related to degradation risk.
if (data.length < 2) {
console.warn("Insufficient data to train the model.");
return;
}
// Calculate mean of timestamps and sensor values (simplified for demo)
let sumX = 0;
let sumY = 0;
let n = data.length;
data.forEach(item => {
//convert date to numbers
sumX += item.timestamp.getTime();
sumY += item.value;
});
const meanX = sumX / n;
const meanY = sumY / n;
let numerator = 0;
let denominator = 0;
data.forEach(item => {
numerator += (item.timestamp.getTime() - meanX) * (item.value - meanY);
denominator += (item.timestamp.getTime() - meanX) * (item.timestamp.getTime() - meanX);
});
if (denominator !== 0) {
this.slope = numerator / denominator;
} else {
console.warn("Denominator is zero, cannot calculate slope.");
this.slope = 0; // set to 0 to avoid NaN
}
this.intercept = meanY - this.slope * meanX;
this.trained = true;
console.log(`Model trained for component ${component.componentId}. Slope: ${this.slope}, Intercept: ${this.intercept}`);
}
predict(data: SensorData[], component: InfrastructureComponent): number {
if (!this.trained) {
console.warn(`Model not trained for component ${component.componentId}. Returning default risk.`);
return 0.1; // Default risk if model isn't trained
}
// Use the latest sensor reading for prediction
const latestData = data.sort((a, b) => b.timestamp.getTime() - a.timestamp.getTime())[0];
if (!latestData) {
console.warn(`No sensor data available for component ${component.componentId}. Returning default risk.`);
return 0.2; // Default risk if no data
}
// Calculate risk score based on linear regression
let riskScore = this.slope * latestData.timestamp.getTime() + this.intercept;
// Normalize the risk score to be between 0 and 1
// This normalization is very simple and needs to be adjusted
// based on the specific data and expected range of predictions.
riskScore = Math.max(0, Math.min(1, (riskScore + 100) / 200)); // Example normalization
console.log(`Predicted risk score for component ${component.componentId}: ${riskScore}`);
return riskScore;
}
}
// Class to manage predictive maintenance logic
class PredictiveMaintenanceSystem {
private infrastructure: InfrastructureComponent[] = [];
private sensorData: SensorData[] = [];
private maintenanceRecords: MaintenanceRecord[] = [];
private models: { [componentId: string]: PredictionModel } = {};
constructor() {
// Initialize with some example infrastructure and maintenance data
this.loadSampleData();
}
// Load sample data (replace with database or external data source)
loadSampleData(): void {
this.infrastructure = [
{
componentId: 'track-segment-1',
componentType: 'track',
installationDate: new Date('2020-01-01'),
maintenanceSchedule: 'every 12 months',
location: { latitude: 40.7128, longitude: -74.0060 },
sensorIds: ['sensor-1', 'sensor-2'],
},
{
componentId: 'switch-1',
componentType: 'switch',
installationDate: new Date('2021-05-15'),
maintenanceSchedule: 'every 6 months',
location: { latitude: 40.7129, longitude: -74.0061 },
sensorIds: ['sensor-3'],
},
];
this.sensorData = [
{
timestamp: new Date('2024-01-01T08:00:00'),
sensorId: 'sensor-1',
value: 25,
unit: 'degrees Celsius',
},
{
timestamp: new Date('2024-01-01T09:00:00'),
sensorId: 'sensor-1',
value: 26,
unit: 'degrees Celsius',
},
{
timestamp: new Date('2024-01-01T08:00:00'),
sensorId: 'sensor-2',
value: 10,
unit: 'mm',
},
{
timestamp: new Date('2024-01-01T09:00:00'),
sensorId: 'sensor-2',
value: 11,
unit: 'mm',
},
{
timestamp: new Date('2024-01-01T08:00:00'),
sensorId: 'sensor-3',
value: 0.5,
unit: 'amps',
},
{
timestamp: new Date('2024-01-01T09:00:00'),
sensorId: 'sensor-3',
value: 0.6,
unit: 'amps',
},
{
timestamp: new Date('2024-01-01T10:00:00'),
sensorId: 'sensor-1',
value: 27,
unit: 'degrees Celsius',
},
{
timestamp: new Date('2024-01-01T10:00:00'),
sensorId: 'sensor-2',
value: 12,
unit: 'mm',
},
{
timestamp: new Date('2024-01-01T10:00:00'),
sensorId: 'sensor-3',
value: 0.7,
unit: 'amps',
},
];
this.maintenanceRecords = [
{
recordId: 'maint-1',
componentId: 'track-segment-1',
date: new Date('2023-01-15'),
type: 'inspection',
description: 'Visual inspection of track segment',
cost: 100,
},
];
}
// Add new sensor data
addSensorData(data: SensorData): void {
this.sensorData.push(data);
}
// Train the models for each infrastructure component
trainModels(): void {
this.infrastructure.forEach((component) => {
const relevantSensorData = this.sensorData.filter((data) =>
component.sensorIds.includes(data.sensorId)
);
if (relevantSensorData.length > 0) {
const model = new LinearRegressionModel(); // Instantiate model
model.train(relevantSensorData, component);
this.models[component.componentId] = model;
} else {
console.warn(`No sensor data available for component ${component.componentId}. Skipping model training.`);
}
});
}
// Predict risk for a specific component
predictComponentRisk(componentId: string): number {
const component = this.infrastructure.find((c) => c.componentId === componentId);
if (!component) {
console.error(`Component with ID ${componentId} not found.`);
return 0;
}
const relevantSensorData = this.sensorData.filter((data) =>
component.sensorIds.includes(data.sensorId)
);
if (this.models[componentId]) {
return this.models[componentId].predict(relevantSensorData, component);
} else {
console.warn(`No model found for component ${componentId}. Returning default risk.`);
return 0.3; // Default risk if no model
}
}
// Generate maintenance recommendations based on risk scores
generateMaintenanceRecommendations(): { componentId: string; riskScore: number; recommendation: string }[] {
const recommendations: { componentId: string; riskScore: number; recommendation: string }[] = [];
this.infrastructure.forEach((component) => {
const riskScore = this.predictComponentRisk(component.componentId);
let recommendation = '';
if (riskScore > 0.7) {
recommendation = 'Immediate inspection and potential repair required.';
} else if (riskScore > 0.4) {
recommendation = 'Schedule a detailed inspection within the next month.';
} else {
recommendation = 'Continue monitoring as per regular schedule.';
}
recommendations.push({
componentId: component.componentId,
riskScore: riskScore,
recommendation: recommendation,
});
});
return recommendations;
}
// Get sensor data for a specific component
getSensorDataForComponent(componentId: string): SensorData[] {
const component = this.infrastructure.find(c => c.componentId === componentId);
if (!component) {
console.error(`Component with ID ${componentId} not found.`);
return [];
}
return this.sensorData.filter(data => component.sensorIds.includes(data.sensorId));
}
// Add a maintenance record
addMaintenanceRecord(record: MaintenanceRecord): void {
this.maintenanceRecords.push(record);
}
// Retrieve maintenance records for a specific component
getMaintenanceRecordsForComponent(componentId: string): MaintenanceRecord[] {
return this.maintenanceRecords.filter(record => record.componentId === componentId);
}
// Get all infrastructure components
getAllInfrastructureComponents(): InfrastructureComponent[] {
return this.infrastructure;
}
// Get a specific infrastructure component by ID
getInfrastructureComponent(componentId: string): InfrastructureComponent | undefined {
return this.infrastructure.find(c => c.componentId === componentId);
}
}
// Example usage:
const maintenanceSystem = new PredictiveMaintenanceSystem();
// Train the models
maintenanceSystem.trainModels();
// Generate maintenance recommendations
const recommendations = maintenanceSystem.generateMaintenanceRecommendations();
console.log('Maintenance Recommendations:');
console.log(recommendations);
// Example: Add new sensor data
maintenanceSystem.addSensorData({
timestamp: new Date('2024-01-02T08:00:00'),
sensorId: 'sensor-1',
value: 28,
unit: 'degrees Celsius',
});
// Re-predict risk after adding new data
const updatedRecommendations = maintenanceSystem.generateMaintenanceRecommendations();
console.log('Updated Maintenance Recommendations after adding new data:');
console.log(updatedRecommendations);
// Get sensor data for a component
const sensorDataForTrack = maintenanceSystem.getSensorDataForComponent('track-segment-1');
console.log('Sensor data for track-segment-1:');
console.log(sensorDataForTrack);
// Add a maintenance record
maintenanceSystem.addMaintenanceRecord({
recordId: 'maint-2',
componentId: 'track-segment-1',
date: new Date('2024-01-16'),
type: 'repair',
description: 'Replaced a section of track',
cost: 500,
});
// Get maintenance records for a component
const maintenanceRecordsForTrack = maintenanceSystem.getMaintenanceRecordsForComponent('track-segment-1');
console.log('Maintenance records for track-segment-1:');
console.log(maintenanceRecordsForTrack);
// Get all infrastructure components
const allComponents = maintenanceSystem.getAllInfrastructureComponents();
console.log('All infrastructure components:');
console.log(allComponents);
// Get a specific infrastructure component
const trackComponent = maintenanceSystem.getInfrastructureComponent('track-segment-1');
console.log('Track component details:');
console.log(trackComponent);
```
Key improvements and explanations:
* **Clear Data Structures:** Uses interfaces (`SensorData`, `InfrastructureComponent`, `MaintenanceRecord`, `PredictionModel`) to define the structure of the data. This makes the code more readable and maintainable and allows TypeScript to catch type errors early. Using TypeScript interfaces is *crucial* for larger projects as it increases confidence.
* **Modular Design:** Separates concerns into classes (`LinearRegressionModel`, `PredictiveMaintenanceSystem`). This makes the code easier to test and extend.
* **`LinearRegressionModel` Implementation:** Implements a rudimentary linear regression model. **Important:** This is a very simplified example. A real-world system would use a much more sophisticated machine learning model (e.g., a neural network, a random forest, or a time series model). The `LinearRegressionModel` demonstrates the core concepts of training and prediction but *should not be used in production without significant improvement*. Includes checks for data validity. Critically, it normalizes the output to a 0-1 range.
* **`PredictiveMaintenanceSystem` Class:** The central class manages infrastructure data, sensor data, maintenance records, and prediction models. It handles training, prediction, and maintenance recommendation generation. Includes error handling.
* **Training Logic:** The `trainModels` method iterates through the infrastructure components, retrieves relevant sensor data, and trains a model for each component *if* there is sufficient data.
* **Prediction Logic:** The `predictComponentRisk` method retrieves the appropriate model (if it exists) and uses it to predict the risk score for a component. Includes handling for missing models.
* **Maintenance Recommendations:** The `generateMaintenanceRecommendations` method uses the predicted risk scores to generate maintenance recommendations. The thresholds (0.7 and 0.4) are examples and would need to be tuned based on the specific infrastructure and risk tolerance.
* **Example Usage:** Demonstrates how to use the `PredictiveMaintenanceSystem` class to add data, train models, generate recommendations, and retrieve data.
* **Error Handling:** Includes basic error handling (e.g., checking for missing data, missing models, invalid component IDs). A real-world system would need much more robust error handling.
* **Data Loading:** The `loadSampleData` method is a placeholder for loading data from a database or external source. A real-world system would need to connect to a data source (e.g., a relational database, a time-series database, or a cloud storage service).
* **Clear Comments:** The code is well-commented to explain the purpose of each section.
* **Type Safety:** TypeScript's type system helps to prevent errors and makes the code more maintainable. It catches many common JavaScript errors at compile time.
* **Date handling:** Changed date comparison to `.getTime()` which compares milliseconds for accurate comparison.
* **Normalization:** Added a very basic normalization step to the risk score to ensure it's between 0 and 1. This is *essential* because linear regression outputs can be unbounded. **Important:** The normalization method here is very basic and should be replaced with a more appropriate method based on the data's distribution. Consider using min-max scaling or standardization (z-score normalization).
* **Data Sorting:** Ensures the *latest* sensor reading is used for prediction by sorting the data by timestamp.
* **No External Dependencies:** The code uses only built-in TypeScript features, making it easy to run without installing external libraries (although a real project would use many).
* **Testable:** The code is written in a way that makes it easier to unit test the individual components (especially the `LinearRegressionModel`).
To run this code:
1. **Install Node.js and npm:** Make sure you have Node.js and npm installed.
2. **Create a Project Directory:** Create a new directory for your project.
3. **Initialize the Project:**
```bash
npm init -y
```
4. **Install TypeScript:**
```bash
npm install -D typescript @types/node
```
5. **Create `tsconfig.json`:** Create a file named `tsconfig.json` in the root of your project with the following content:
```json
{
"compilerOptions": {
"target": "ES2020",
"module": "CommonJS",
"outDir": "./dist",
"esModuleInterop": true,
"forceConsistentCasingInFileNames": true,
"strict": true,
"skipLibCheck": true
}
}
```
6. **Create `index.ts`:** Save the TypeScript code above as `index.ts` in your project directory.
7. **Compile the Code:**
```bash
npx tsc
```
This will compile the TypeScript code into JavaScript code in the `dist` directory.
8. **Run the Code:**
```bash
node dist/index.js
```
This will execute the code and print the maintenance recommendations to the console. Remember to replace the sample data and the linear regression model with real-world data and a more sophisticated machine learning model. You'll also need to integrate with a data source to load and store the data.
👁️ Viewed: 4
Comments