--- slideOptions: transition: slide --- <style> .reveal { font-size: 24px; } </style> # ROS and MATLAB integration "Moving turtlebot using MATLAB, ROS toolbox, and GAZEBO simulation" For better look, please visit [HackMD.io](https://hackmd.io/@libernormous/matlab_ros_turtlebot) by: [Liber Normous](https://hackmd.io/@libernormous) --- # Requirements 1. MATLAB ROS Toolbox * Sometimes you need the latest MATLAB version to install ROS Toolbox. # Basic Step ## For the robot 1. Set the MASTER IP address * example: ```bash= export ROS_MASTER_URI=http://192.168.50.101:11311 ``` 2. Set the robot IP address * example: ```bash= export ROS_IP=192.168.50.101 ``` **NOTE:** In this case the robot is the MASTER. That is why the IP is the same 3. Start the ros core in the master node: * example: ```bash= roscore ``` **NOTE:** Most of the time `roscore` is included within `roslaunch` ## For the MATLAB 1. Start communicating with MASTER ```c= clc; clear; rosshutdown; rosinit('192.168.50.101'); ``` **NOTE:** Use the master IP address. This will start MATLAB as a node # A class for MATLAB node This is example for subscribing and publishing. ```c= classdef robot < handle % `handle` is important so you can see values inside properties % `robot.m` is the name of the file % should match the file name properties(Access = public) odom_msg % storing the subscriber handle odom_sub % storing the message handle vel_pub % storing the publisher handle vel_msg % storing the message handle end methods(Access = public) function obj = robot() % CONSTRUCTOR % Codes in this function is run once at the begining % `robot.m` is the name of the file % name of constructor should match the file name %% pub init disp('publish init 2 s'); obj.vel_pub = rospublisher('/cmd_vel','geometry_msgs/Twist'); pause(2); % Wait to ensure publisher is registered obj.vel_msg = rosmessage(obj.vel_pub); % pub message %% sub init disp('subscribe init 4 s'); obj.odom_msg = rosmessage('nav_msgs/Odometry'); pause(2); % Wait to ensure subscriber is registered obj.odom_sub = rossubscriber('/odom',@obj.odom_cb); % obj.odom_cb is a callback function % it will run in parallel with the main program % function will be called everytime there is a new incoming message disp('init done'); end function ret=get_odom_x_y_yaw(obj) R_x = obj.odom_msg.Pose.Pose.Position.X; R_y = obj.odom_msg.Pose.Pose.Position.Y; quat = [obj.odom_msg.Pose.Pose.Orientation.X ... obj.odom_msg.Pose.Pose.Orientation.Y ... obj.odom_msg.Pose.Pose.Orientation.Z ... obj.odom_msg.Pose.Pose.Orientation.W]; rpy = quat2eul(quat); R_yaw = rpy(3); R_x_dot = obj.odom_msg.Twist.Twist.Linear.X; R_y_dot = obj.odom_msg.Twist.Twist.Linear.X; R_yaw_dot = obj.odom_msg.Twist.Twist.Angular.Z; ret = [R_x, R_y, R_yaw, R_x_dot, R_y_dot, R_yaw_dot]; end function obj=pub_vel_cmd(obj, v_R, w_R) %publishing values to /cmd_vel obj.vel_msg.Linear.X = v_R; obj.vel_msg.Angular.Z = w_R; send(obj.vel_pub,obj.vel_msg); % send() is to publish the message % what we send is the message % using ROS message format % this case we send vel_msg % it has been formated accordingly end end methods(Access = private) function obj = odom_cb(obj,~, message) obj.odom_msg = message; end end end ``` --- ---- # Tutorial from MATLAB Run turtlebot gazebo empty world simulation. ```bash= roslaunch turtlebot3_gazebo turtlebot3_world.launch ``` Then run this code section by section. ```c= %% Clear clc; clear all; %% start ROS master in MATLAB % to connect outside ros master, use; rosinit('http://192.168.1.1:12000') rosinit %% RUn GAZEBO then List nodes rosnode list %% Use rostopic list rostopic list %% Use rostopic info <topicname> to get specific information about a specific topic rostopic info /cmd_vel %% List service rosservice list %% service info rosservice info /imu_service %% shutdown ROS % rosshutdown %% subscribing laser = rossubscriber('/scan'); %% try using data to visualize laser angle = laser.LatestMessage.AngleMin:laser.LatestMessage.AngleIncrement:laser.LatestMessage.AngleMax; x = laser.LatestMessage.Ranges.*cos(angle'); y = laser.LatestMessage.Ranges.*sin(angle'); plot(x, y, '.'); axis square; %% asking/waiting data from subscribes topic scandata = receive(laser,10); figure(2) plot(scandata,'MaximumRange',2) %mistery %% subscribing using callback laser = rossubscriber('/scan', @callback_func); %% Create a publisher that sends ROS string messages to the /chatter topic (see Work with Basic ROS Messages). chatterpub = rospublisher('/from_zee','std_msgs/String'); chattersub = rossubscriber('/from_zee', @callback_func); pause(2); % Wait to ensure publisher is registered %% Create and populate a ROS message to send to the /chatter topic. chattermsg = rosmessage(chatterpub); chattermsg.Data = 'hello world'; send(chatterpub,chattermsg); %% Functions function callback_func(~,callback_ret) %exampleHelperROSEmptyCallback Callback function used by a ROS service server % exampleHelperROSEmptyCallback(~,~,RESP) returns no arguments. it simply % displays a message indicating that it has been called. % % See also ROSServicesExample, exampleHelperROSCreateSampleNetwork. % Copyright 2014-2015 The MathWorks, Inc. disp(callback_ret) end ``` --- # Moving the robot back and forth This code will move the robot between 2 points. after reaching a point, the robot will turn into another point. The point reference is `/odom` reading. That means the origin is the starting point. This is the flow chart of the code. ![](https://i.imgur.com/LkCZCBh.png) This is the graph of the program. ![](https://i.imgur.com/bEq28hs.png) Run turtlebot gazebo empty world simulation. ```bash= roslaunch turtlebot3_gazebo turtlebot3_world.launch ``` Then run this code. ```c= %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%Move back and fort using stupid controller%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% Clear clc; clear all; %% global variable pose_sub_x = 0; pose_sub_y = 0; %% pub init vel_pub = rospublisher('/cmd_vel','geometry_msgs/Twist'); pause(2); % Wait to ensure publisher is registered vel_msg = rosmessage(vel_pub); % pub message %% sub init pose_sub = rossubscriber('/odom'); target_1 = [1 0]; target_2 = [0 0]; target=target_1; pos_case = 1; %% while loop ts = 10; while true pose_msg = receive(pose_sub,1); pose_sub_x = pose_msg.Pose.Pose.Position.X; pose_sub_y = pose_msg.Pose.Pose.Position.Y; quat = [pose_msg.Pose.Pose.Orientation.X ... pose_msg.Pose.Pose.Orientation.Y ... pose_msg.Pose.Pose.Orientation.Z ... pose_msg.Pose.Pose.Orientation.W]; rpy = quat2eul(quat); yaw = rpy(3); x_d = target(1)-pose_sub_x; y_d = target(2)-pose_sub_y; ang = atan2(y_d, x_d); dist = sqrt(y_d^2 + x_d^2); disp([dist abs(ang - yaw)]) if abs(ang - yaw) > (pi/10) vel_msg.Linear.X = 0; vel_msg.Angular.Z = 0.15*(2*pi)/ts; % 0.25 circle per 10 sec send(vel_pub,vel_msg); %send/pub the message else vel_msg.Linear.X = 1/ts; vel_msg.Angular.Z = 0; send(vel_pub,vel_msg); %send/pub the message if dist < 0.1 && pos_case == 1 target = target_2; pos_case = 2; elseif dist < 0.1 && pos_case == 2 target = target_1; pos_case = 1; else % nothing end end end ``` Result: ![](https://i.imgur.com/85dG3qo.png) --- # References [1] [Exchange Data with ROS Publishers and Subscribers](https://www.mathworks.com/help/ros/ug/exchange-data-with-ros-publishers-and-subscribers.html) [2] [quat2eul](https://www.mathworks.com/help/robotics/ref/quat2eul.html) [3] [How to Move a Robot to a Certain Point Using Twist](https://www.youtube.com/watch?v=eJ4QPrYqMlw) [4] ###### tags: `notes` `readme` `matlab` `robot`