Equivalent of global variables?

I'm trying to get a couple of 'if/then' statements to output data all at once.

The code continuously reads data from a source (a CAN reader outputting pitch/roll/yaw and linear acceleration over 3 CAN ID's), performs some calculations then outputs onto the screen. I've included the relevant part of my code below:

if canid == 372 {
       let ywrt:f32 = concathd(decon[1], decon[0]) as f32 *0.01 - 327.68;
       let lin_y:f32 = concathd(decon[5], decon[4]) as f32 *0.0002 - 6.55;
       println!("YAW = {:.4}   Acc Y = {:.4}", ywrt, lin_y);
       }
                
if canid == 376 {
       let rrt:f32 = concathd(decon[1], decon[0]) as f32 *0.01 - 327.68;
       let lin_x:f32 = concathd(decon[5], decon[4]) as f32 *0.0002 - 6.55;
       println!("ROLL = {:.4}   Acc X = {:.4}", rrt, lin_x);
       }
    
if canid == 380 {
       let prt:f32 = concathd(decon[1], decon[0]) as f32 *0.01 - 327.68;
       let lin_z:f32 = concathd(decon[5], decon[4]) as f32 *0.0002 - 6.55;
       println!("PITCH = {:.4}   Acc Z = {:.4}", prt, lin_z);
       }

Ideally, I'd like to calculate the various components within one section, then output the P/R/Y and X/Y/Z Acceleration at the end in a nice readable format.

I've been having some issues since the CAN Reader has got to loop (it only outputs one CAN ID at a time) and perform certain calculations based of the ID.

// /// //// ALTERNATVELY //// /// //

I was also thinking to do something like this:

if YAW == 1 && PITCH == 1 && ROLL == 1 {          // Once all calcs performed, clear screen
print!("\x1B[2J\x1B[1;1H");
}

(But that would require me to have global variables which I am unsure how to implement within the if statements).

Any help would be much appreciated!!

Logan

Do you want to use Option here?

let y = (canid == 372).then(|| (
    concathd(decon[1], decon[0]) as f32 *0.01 - 327.68,
    concathd(decon[5], decon[4]) as f32 *0.0002 - 6.55,
));
let x = (canid == 376).then(|| (
    concathd(decon[1], decon[0]) as f32 *0.01 - 327.68,
    concathd(decon[5], decon[4]) as f32 *0.0002 - 6.55,
));
let z = (canid == 380).then(|| (
    concathd(decon[1], decon[0]) as f32 *0.01 - 327.68,
    concathd(decon[5], decon[4]) as f32 *0.0002 - 6.55,
));

if let Some((ywrt, lin_y)) = y {
    println!("YAW = {:.4}   Acc Y = {:.4}", ywrt, lin_y);
}
if let Some((rrt, lin_x)) = x {
    println!("ROLL = {:.4}   Acc X = {:.4}", rrt, lin_x);
}
if let Some((prt, lin_z)) = z {
    println!("PITCH = {:.4}   Acc Z = {:.4}", prt, lin_z);
}

Firstly I'd suggest that you don't need global variables to do this. Assuming you mean "global variable" in the usual way programmers thing of them: Global variable - Wikipedia. This is generally regarded as a bad idea in programming.

I would be tempted to separate this code into two parts, likely in two different modules. One part does nothing but interface with the sensor. The other part does whatever you need to do with the sensor data, display it or whatever else.

As you say the sensor reading needs to run in a loop that sounds like a good candidate to run in its own thread. Then as it waits for sensor inputs it will not be holding up the processing of the rest of your code. std::thread - Rust

That leave the problem of communicating the sensor readings from your sensor thread to the rest of your code. For that you could use a channel: std::sync::mpsc::channel - Rust. When the sensor process has collected all the components of the sensor reading it writes them, as a struct, to the channel. The display code, then reads the struct from the channel and displays it.

1 Like

Struct fields are basically the same as globals, except they don't cause undue headaches most of the time. Playground

If you really want state to persist without explicit references, consider std::thread_local. But I don't think this is what you want.