Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Find a better way of interacting with nodes #243

Open
nnmm opened this issue Jul 31, 2022 · 1 comment
Open

Find a better way of interacting with nodes #243

nnmm opened this issue Jul 31, 2022 · 1 comment

Comments

@nnmm
Copy link
Contributor

nnmm commented Jul 31, 2022

As the tutorial shows, implementing a node with rclrs is currently very different from rclcpp/rclpy and comparatively difficult: In particular, a lot of locking is going on.

There probably is room for an abstraction that, at the very least, hides this from the user. For instance, perhaps callbacks could receive a mutable reference to the "node state" along with the message itself, which would correspond to the members of your Node class in C++.

@CoAuToSe
Copy link

CoAuToSe commented Aug 1, 2022

I did an internship in the company Pollen Robotics about transcription of Python ROS code to Rust ROS code. Here is the result with its Python equivalent inside of it. It may not be the best but in the end it worked as intended. I was using the client-service branch just before its merge with the main branch. I made some things to allow an easier usage of the ros2-rust crate, resolving partially the locking issue and the transcription from Python.

For the locking issue I resolved it by making the macro ameis (Arc Mutex Edit Inner Safely). The arc_mutex macro can be simplified, as it spam in debug profile but only for user friendliness purpose (to backtrack the usage of locks and therefore data) :

#[allow(unused_mut)]
macro_rules! arc_mutex {
    ($name_arc:ident => $name_var:ident) => {
        #[cfg(not(debug_assertions))]
        {
            $name_var = $name_arc.lock().unwrap();
        }
        #[cfg(debug_assertions)]
        loop {
            if let Ok(some) = $name_arc.try_lock() {
                $name_var = some;
                println!(
                    "macro getting lock of {}: {:?} at {:?}",
                    stringify!($name_arc),
                    line!(),
                    std::time::Instant::now()
                );
                break;
            } else {
                std::thread::sleep(std::time::Duration::from_millis(100));
                println!("macro {}: {:?}", stringify!($name_var), line!());
            }
        }
    };
}

macro_rules! ameis {
    ($am_var:ident => $var:ident; $some:block ) => {
        {
            #[allow(unused_mut)]
            let mut $var;
            arc_mutex!($am_var=>$var);
            $some
        }
    };
}

Simplified version with an example :

use std::sync::{Arc, Mutex}; 

macro_rules! ameis {
    ($am_var:ident => $var:ident; $some:block ) => {
        {
            #[allow(unused_mut)]
            let mut $var;
            $var = $am_var.lock().unwrap();
            $some
        }
    };
}

fn main() {
    println!("Hello, ArcMutex!");
    let var = Arc::new(Mutex::new(String::from("init")));
    println!("{:?}", var);
    ameis!(var=>temp_var;{*temp_var = String::from("inner")});
    println!("{:?}", var);
    ameis!(var => temp_var ; {
        println!("{}", temp_var);
        *temp_var = String::from("second");
    });
    println!("{:?}", var);
}

But this simplified version needs a correct usage of mutex to be safe to use as it wont help otherwise and could lock the code. It may imply some repetition in the code but allow a easier usage of the parameters, especially with a struct where you need to keep the Mutex alive.

It may need another place to be but in my internship I also made the crate cargo-rost which skips most of the boring stuff of the transcription of Python ROS to Rust ROS but it is currently oriented to be used on a class structured Python code (if it is how it is called) to work properly (tests were made on initials python codes of the intern ship ex: this one by running the following command cargo rost camera_focus.py).

It may not resolve the issue but adding a struct to contain Data that implement the Deref/DerefMut trait with the target type being a MutexGuard to the data (or maybe as the MutexGuard never drop after, the only easy way is the ameis macro). It would simplify the user experience but it may be something totally new for the ROS environment (I have not that much experience in ROS so I can not really say anything) but it may not be appreciated to be implemented as being a Rust only thing.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants