—
layout: default
—
Roboracer 2nd day
Ubuntu Installation with Virtualbox is done so it is time to install Docker in Ubuntu.
Open Terminal in Ubuntu
- update system : sudo apt update
- install docker: sudo apt install docker.io -y
- append user: sudo usermod -aG docker $USER
- reboot(for user rights): sudo reboot
- check docker: docker –version
[moving on to lab 1] Now we have VirtualBox VM (Ubuntu) and Docker, we will use 2.2 (Docker) for lab1
- Make working directory: mkdir -p ~/lab1_ws/src
- Download ROS2 Foxy image and run docker container: docker run -it -v ~/lab1_ws/src:/lab1_ws/src –name f1tenth_lab1 ros:foxy
- install tmux for multiple terminal inside Docker Container: apt update && apt install tmux
[How to use tmux] type tmux in terminal to start tmux session. Ctrl+b, then press next keys: c: new terminal n: next terminal d: detach terminal
[ROS2 basics working fine] source /opt/ros/foxy/setup.bash ros2 topic list
/parameter_events /rosout
Create workspace before creating a package cd /lab1_ws colcon build source install/setup.bash
[Creating a package] Deliverable 1:
cd /lab1_ws/src ros2 pkg create lab1_pkg –build-type ament_cmake –dependencies rclcpp rclpy ackermann_msgs
- lab1_pkg - package name
- ament_cmake - supports both C++ and Python
- dependencies - Libraries:
- rclcpp - C++ ROS2 library
- rclpy - Python ROS2 library
- ackermann_msgs - message type for vehicle control
[If declared properly the depencies could be installed using rosdep] cd /lab1_ws rosdep install -i –from-path src –rosdistro foxy -y
[Creating nodes with publishers and subscribers] cd /lab1_ws/src/lab1_pkg mkdir -p scripts nano scripts/talker.py
editor pops up, code: #!/usr/bin/env python3 import rclpy from rclpy.node import Node from ackermann_msgs.msg import AckermannDriveStamped
class Talker(Node): def init(self): super().init(‘talker’) self.declare_parameter(‘v’, 0.0) self.declare_parameter(‘d’, 0.0) self.publisher = self.create_publisher(AckermannDriveStamped, ‘drive’, 10) self.timer = self.create_timer(0.1, self.timer_callback)
def timer_callback(self):
msg = AckermannDriveStamped()
msg.drive.speed = self.get_parameter('v').value
msg.drive.steering_angle = self.get_parameter('d').value
self.publisher.publish(msg)
def main(args=None): rclpy.init(args=args) node = Talker() rclpy.spin(node) node.destroy_node() rclpy.shutdown()
if name == ‘main’: main()
ctrl x, y, enter for save for rights: chmod +x scripts/talker.py
explanation: required Deliverable 2: talker node creation AckermannDriveStamped message publishing in drive topic v parameter → speed field d parameter → steering_angle field
code: Node class inheritence - ROS2 node creation declare_parameter - v, d parameter declaration create_publisher - publisher creation in drive topic timer_callback - message per 0.1 second
for clipboard sharing with virtual machine, we are going to install guest additions first get out of Docker with exit command
then sudo apt update sudo apt install virtualbox-guest-utils virtualbox-guest-x11 -y sudo reboot
then we will set Devices → Shared Clipboard → Bidirectional
This didn’t work because the screen of Ubuntu was cracking we had to deleted all guestAddition sudo /opt/VBoxGuestAdditions-*/uninstall.sh sudo reboot
and eject the guest additions cd image
[Start the Docker container again (after reboot)] docker start -i f1tenth_lab1
back here [Creating nodes with publishers and subscribers] cd /lab1_ws/src/lab1_pkg mkdir -p scripts nano scripts/talker.py
need to install nano first (good for beginners) apt update && apt install nano -y
back to talker.py nano scripts/talker.py
editor pops up, code: #!/usr/bin/env python3 import rclpy from rclpy.node import Node from ackermann_msgs.msg import AckermannDriveStamped
class Talker(Node): def init(self): super().init(‘talker’) self.declare_parameter(‘v’, 0.0) self.declare_parameter(‘d’, 0.0) self.publisher = self.create_publisher(AckermannDriveStamped, ‘drive’, 10) self.timer = self.create_timer(0.1, self.timer_callback)
def timer_callback(self):
msg = AckermannDriveStamped()
msg.drive.speed = self.get_parameter('v').value
msg.drive.steering_angle = self.get_parameter('d').value
self.publisher.publish(msg)
def main(args=None): rclpy.init(args=args) node = Talker() rclpy.spin(node) node.destroy_node() rclpy.shutdown()
if name == ‘main’: main()
ctrl+x, y, enter for save for rights: chmod +x scripts/talker.py
explanation: required Deliverable 2: talker node creation AckermannDriveStamped message publishing in drive topic v parameter → speed field d parameter → steering_angle field
code: Node class inheritence - ROS2 node creation declare_parameter - v, d parameter declaration create_publisher - publisher creation in drive topic timer_callback - message per 0.1 second
[creating relay node] nano scripts/relay.py
#!/usr/bin/env python3 import rclpy from rclpy.node import Node from ackermann_msgs.msg import AckermannDriveStamped
class Relay(Node): def init(self): super().init(‘relay’) self.subscription = self.create_subscription( AckermannDriveStamped, ‘drive’, self.listener_callback, 10) self.publisher = self.create_publisher(AckermannDriveStamped, ‘drive_relay’, 10)
def listener_callback(self, msg):
new_msg = AckermannDriveStamped()
new_msg.drive.speed = msg.drive.speed * 3.0 #as lab1 guideline
new_msg.drive.steering_angle = msg.drive.steering_angle * 3.0 #as lab1 guideline
self.publisher.publish(msg)
def main(args=None): rclpy.init(args=args) node = Relay() rclpy.spin(node) node.destroy_node() rclpy.shutdown()
if name == ‘main’: main()
ctrl+x, y, then enter for save rights: chmod +x scripts/relay.py
[update before build] (make sure working in lab1_pkg directory with cd command) nano cMakeLists.txt
add this right above ament_package()
install(PROGRAMS scripts/talker.py scripts/relay.py DESTINATION lib/${PROJECT_NAME} )
ament_package()
[build] cd /lab1_ws colcon build source install/setup.bash
(opening Docker Again after VM reboot) docker start -i f1tenth_lab1
[Deliverable 3 making launch file] cd /lab1_ws/src/lab1_pkg mkdir -p launch nano launch/lab1_launch.py
from launch import LaunchDescription from launch_ros.actions import Node
def generate_launch_description(): return LaunchDescription([ Node( package=’lab1_pkg’, executable=’talker.py’, name=’talker’, parameters=[{‘v’: 1.0, ‘d’: 0.5}] ), Node( package=’lab1_pkg’, executable=’relay.py’, name=’relay’ ) ])
As lab1 guideline: Launching both nodes and setting talker node parameters
[update CMakeLists.txt: used for ROS2 build with code colcon build, define file’s install location and make Python script executable, without install() section the scripts will not be installed thus will not become executable] nano CMakeLists.txt
add codes below install(PROGRAMS
install(DIRECTORY launch DESTINATION share/${PROJECT_NAME} )
[build] cd /lab1_ws colcon build source install/setup.bash
[test launch file] ros2 launch lab1_pkg lab1_launch.py
after few error messages I found a typo, ‘parameter’ should be ‘parameters’ in the launch file also ‘pythond’ in talker.py should be ‘python’ and the indentations within python scripts should be made with ‘spaces’ not ‘tabs’ in ubuntu terminal
seems to be working, ran it in tmux for multiple terminals
[ROS2 commands]
commands need /, when it cannot find something but it is in there
seems to be working with subscription and publishing, so I would like to move on to SUBMISSION.md
Lab 1: Intro to ROS 2 Written Questions Q1: During this assignment, you’ve probably ran these two following commands at some point: source /opt/ros/foxy/setup.bash and source install/local_setup.bash. Functionally what is the difference between the two? Answer:
- source /opt/ros/foxy/setup.bash is for setting up ROS2 FOXY system overall such as rclpy, ackermann_msgs, and ros2 commands such as ros2 launch
- source install/local_setup.bash is for setting up my workspace such as lab1_pkg, adding talker.py and relay.py also. this includes the first ROS2 foxy source because it is built upon that.
Q2: What does the queue_size argument control when creating a subscriber or a publisher? How does different queue_size affect how messages are handled? Answer: The messages would be saved in the buffer for the maximum size of queue_size when the messages are not processed yet, and delete old ones when the queue_size is full. We could make it store more messages but it will require more memory space.
create_publisher(message type, topic, queue_size)
Q3: Do you have to call colcon build again after you’ve changed a launch file in your package? (Hint: consider two cases: calling ros2 launch in the directory where the launch file is, and calling it when the launch file is installed with the package.) Answer: We have to call colcon build when the launch file has to be copied from /src to /install So when we are launching in directory(/src) where the launch file is, colcon build is not needed, but when we are launching file in installed package, colcon build is necessary.