Skip to main content

motor_control/
motor_control.rs

1use fuzzy_logic_engine_rs::{
2    fis::{FisType, FuzzyInferenceSystem},
3    membership::MembershipKind as M,
4    rule::{Connective, Rule},
5    term::Term,
6    variable::{LinguisticVariable, Range},
7};
8
9fn main() -> Result<(), Box<dyn std::error::Error>> {
10    let mut system = FuzzyInferenceSystem::new("Motor Control");
11
12    // Define output variable (motor speed)
13    let mut motor = LinguisticVariable::new(
14        "Speed",
15        Range {
16            min: 0.0,
17            max: 2000.0,
18        },
19    );
20    motor.add_term(Term::new(
21        "fast",
22        M::Trapezoid {
23            a: 1000.0,
24            b: 1200.0,
25            c: 1500.0,
26            d: 2000.0,
27        },
28    ));
29    motor.add_term(Term::new(
30        "slow",
31        M::Trapezoid {
32            a: 0.0,
33            b: 0.0,
34            c: 800.0,
35            d: 1200.0,
36        },
37    ));
38    system.add_output(motor);
39
40    // Define input variable: Temperature
41    let mut temp = LinguisticVariable::new(
42        "Temperature",
43        Range {
44            min: -80.0,
45            max: 80.0,
46        },
47    );
48    temp.add_term(Term::new(
49        "cold",
50        M::Trapezoid {
51            a: -80.0,
52            b: -80.0,
53            c: 0.0,
54            d: 20.0,
55        },
56    ));
57    temp.add_term(Term::new(
58        "hot",
59        M::Trapezoid {
60            a: 15.0,
61            b: 20.0,
62            c: 80.0,
63            d: 80.0,
64        },
65    ));
66    system.add_input(temp);
67
68    // Define input variable: Humidity
69    let mut hum = LinguisticVariable::new(
70        "Humidity",
71        Range {
72            min: 0.0,
73            max: 100.0,
74        },
75    );
76    hum.add_term(Term::new(
77        "dry",
78        M::Trapezoid {
79            a: 0.0,
80            b: 0.0,
81            c: 20.0,
82            d: 50.0,
83        },
84    ));
85    hum.add_term(Term::new(
86        "wet",
87        M::Trapezoid {
88            a: 40.0,
89            b: 70.0,
90            c: 100.0,
91            d: 100.0,
92        },
93    ));
94    system.add_input(hum);
95
96    // Rules
97    // IF temp is hot AND hum is dry THEN motor is fast
98    let r1 = Rule::new(
99        vec![Some("hot".into()), Some("dry".into())],
100        vec!["fast".into()],
101        Connective::And,
102    );
103
104    // IF temp is cold AND hum is dry THEN motor is very slow (approximate hedge by reusing "slow")
105    let r2 = Rule::new(
106        vec![Some("cold".into()), Some("dry".into())],
107        vec!["slow".into()],
108        Connective::And,
109    );
110
111    // IF temp is hot AND hum is wet THEN motor is very fast (approximate hedge by reusing "fast")
112    let r3 = Rule::new(
113        vec![Some("hot".into()), Some("wet".into())],
114        vec!["fast".into()],
115        Connective::And,
116    );
117
118    // IF temp is cold AND hum is wet THEN motor is slow
119    let r4 = Rule::new(
120        vec![Some("cold".into()), Some("wet".into())],
121        vec!["slow".into()],
122        Connective::And,
123    );
124
125    system.set_rules(vec![r1, r2, r3, r4]);
126
127    // Evaluate
128    let temp = 42.0;
129    let hum = 45.0;
130    let inputs = vec![temp, hum];
131
132    let result = system.compute(FisType::Mamdani, &inputs);
133    let out = result.unwrap();
134    println!(
135        "Inputs: temp={:?}, hum={:?} => motor speed ≈ {:?}",
136        temp, hum, out
137    );
138    assert!(out[0] > 1480.0);
139    assert!(out[0] < 1490.0);
140
141    match system.compute_verbose(FisType::Mamdani, &inputs) {
142        Ok(outputs) => {
143            for out in outputs {
144                println!("{}", out.describe());
145            }
146        }
147        Err(e) => eprintln!("compute_verbose() - Error: {}", e),
148    }
149
150    Ok(())
151}