A compilation of concepts I want to remember...

Navigation
 » Home
 » About Me
 » Github

Raspimouse: Simple teleop program written in Rust

19 Aug 2017 » ROS, rust

tl;dr: Great event, and hopefully we see more events like this.

Intro

This is a quick write up of my work at the ROS Japan UG #12 Raspberry Pi Mouseハッカソン, hosted by RT Corporation, and Groove X. RT Corporation kindly provided the Raspimouse (20+ units), a differential drive robot powered by the raspberry pi, allowing participants to hack with a live robot while Groove X is a robotics company started by the “dad” of the Pepper robot.

github repo: https://github.com/surfertas/rustymouse

I had two focuses today, with the first being rewriting the teleop code in the Rust language. I was under the impression this would be trivial, but had some hiccups that consumed some time to resolve. The second was to move from simulation to the real world, though it appears I will not have sufficient time to complete part two on this occasion.

Teleop the Raspimouse in Rust

I started with the crate that Takashi Ogura [1] created, where he implements the “hello world” of ROS, a subscriber and publisher nodes, based on rosrust being developed by Adnan[2].

Main steps taken:

  1. Add geometry_msgs/Twist to build.rs file where the messages are defined rosmsg_main!(“std_msgs/String”, “geometry_msgs/Twist”). Currently message generation is being done through a build script, where the use of procedural macros is preferred. If there is any one with experience in procedural macros, please reach out to Adnan!
  2. Add the name of the binary to be created, in this case vel_publisher and path src/vel_publisher.rs to Cargo.toml.
  3. Finally, it was really about programming, where simple io, and pattern matching was sufficient. (In reality, I should remove the new line mark, \n, from the pattern matching to make the code more elegant…)
#[macro_use]
extern crate rosrust;
extern crate env_logger;

use rosrust::Ros;
use std::{thread, time};
use std::io;

rosmsg_include!();

fn main() {
    env_logger::init().unwrap();
    let mut ros = Ros::new("vel_publisher").

    let mut publisher = ros.publish("cmd_vel").unwrap(
    println!("w: forward, s: backward, a: left, d: right >");

    loop {
        let mut vel_cmd = msg::geometry_msgs::Twist::
        thread::sleep(time::Duration::

        let mut command = String::new();
        io::stdin().read_line(&mut command);

        match command.as_str() {
            "w\n" => vel_cmd.linear.x = 0.35,
            "s\n" => vel_cmd.linear.x = -0.35,
            "a\n" => vel_cmd.angular.z = 3.21,
            "d\n" => vel_cmd.angular.z = -3.21,
            "q\n" => break,
            _ => println!("Command not recognized"),
        }

        publisher.send(vel_cmd).
    }
}

raspi_mouse

Issues

One issue I had was that I needed to publish to the topic /raspimouse/diff_drive_controller/cmd_vel, which would allow me to teleop the mouse, but rosrust for some reason was not accepting this topic name. Reviewing the source code[3] I was not able to find an immediate solution, thus resulted in writing a python script to remap between cmd_vel and /raspimouse/diff_drive_controller/cmd_vel using the below python script. This allowed me to successfully teleop the mouse in simulation.

#!/usr/bin/env python
import rospy
from geometry_msgs.msg import Twist

def callback(msg):
    pub = rospy.Publisher('/raspimouse/diff_drive_controller/cmd_vel', Twist,
queue_size=10)
    pub.publish(msg)

def topic_mapper():
    rospy.init_node('mapper', anonymous=True)
    rospy.Subscriber("/cmd_vel", Twist, callback)
    rospy.spin()

if __name__ == '__main__':
    topic_mapper()

References

  1. https://github.com/OTL/rosrust_tutorial
  2. https://github.com/adnanademovic/rosrust
  3. https://github.com/adnanademovic/rosrust/blob/master/src/api/naming/mod.rs