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:
- Add
geometry_msgs/Twist
tobuild.rs
file where the messages are definedrosmsg_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! - Add the name of the binary to be created, in this case
vel_publisher
and pathsrc/vel_publisher.rs
toCargo.toml
. - 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).
}
}
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()