Auto-docking to Recharge Battery – ArUco Marker and ROS 2

In this tutorial, I will show you have to perform auto-docking for a mobile robot using ROS 2, OpenCV, and an ArUco marker. Here is the output you will be able to generate if you follow this tutorial to the end:

navigate-to-charging-dock-aruco-marker

Prerequisites

You can find the code for this post here on GitHub.

Version 1 – Harcode the ArUco Marker Pose

Create the Base Link to ArUco Marker Transform

Create a new transformation file between the base_link to aruco_marker.

cd ~/dev_ws/src/two_wheeled_robot/scripts/transforms/base_link_aruco_marker
gedit base_link_to_aruco_marker_transform.py

Add this code.

Save the file, and close it.

Change the execution permissions.

chmod +x base_link_to_aruco_marker_transform.py

Add the script to your CMakeLists.txt file.

Create a launch file.

cd ~/dev_ws/src/two_wheeled_robot/launch/hospital_world/
gedit hospital_world_connect_to_charging_dock_v5.launch.py

Add this code.

Save and close the file.

Create the Navigation to Charging Dock Script

Add a new navigate-to-charging-dock script. We will call it navigate_to_charging_dock_v3.py.

cd ~/dev_ws/src/two_wheeled_robot/scripts
gedit navigate_to_charging_dock_v3.py

Add this code.

Save the file, and close it.

Change the execution permissions.

chmod +x navigate_to_charging_dock_v3.py

Create Battery Status Publishers to Simulate the Robot’s Battery

Now let’s add a full battery publisher. This publisher indicates the battery has sufficient voltage for navigation in an environment.

gedit full_battery_pub.py
#!/usr/bin/env python3 

"""
Description:
Publish the battery state at a specific time interval
In this case, the battery is a full battery.
-------
Publishing Topics:
/battery_status – sensor_msgs/BatteryState
-------
Subscription Topics:
None
-------
Author: Addison Sears-Collins
Website: AutomaticAddison.com
Date: January 13, 2022
"""
 
import rclpy # Import the ROS client library for Python
from rclpy.node import Node # Enables the use of rclpy's Node class
from sensor_msgs.msg import BatteryState # Enable use of the sensor_msgs/BatteryState message type
 
class BatteryStatePublisher(Node):
  """
  Create a BatteryStatePublisher class, which is a subclass of the Node class.
  The class publishes the battery state of an object at a specific time interval.
  """
  
  def __init__(self):
    """
    Class constructor to set up the node
    """
   
    # Initiate the Node class's constructor and give it a name
    super().__init__('battery_state_pub')
     
    # Create publisher(s)  
     
    # This node publishes the state of the battery.
    # Maximum queue size of 10. 
    self.publisher_battery_state = self.create_publisher(BatteryState, '/battery_status', 10)
     
    # Time interval in seconds
    timer_period = 0.1 
    self.timer = self.create_timer(timer_period, self.get_battery_state)
    
    # Initialize battery level
    self.voltage = 9.0 # Initialize the battery voltage level
    self.percentage = 1.0  # Initialize the percentage charge level
    self.power_supply_status = 3 # Initialize the power supply status (e.g. NOT CHARGING)
     
  def get_battery_state(self):
    """
    Callback function.
    This function reports the battery state at the specific time interval.
    """
    msg = BatteryState() # Create a message of this type 
    msg.voltage = self.voltage
    msg.percentage = self.percentage
    msg.power_supply_status = self.power_supply_status
    self.publisher_battery_state.publish(msg) # Publish BatteryState message 
   
def main(args=None):
 
  # Initialize the rclpy library
  rclpy.init(args=args)
 
  # Create the node
  battery_state_pub = BatteryStatePublisher()
 
  # Spin the node so the callback function is called.
  # Publish any pending messages to the topics.
  rclpy.spin(battery_state_pub)
 
  # Destroy the node explicitly
  # (optional - otherwise it will be done automatically
  # when the garbage collector destroys the node object)
  battery_state_pub.destroy_node()
 
  # Shutdown the ROS client library for Python
  rclpy.shutdown()
 
if __name__ == '__main__':
  main()

Now let’s add a low battery publisher. This publisher indicates the battery is low.

cd ~/dev_ws/src/two_wheeled_robot/scripts/battery_state
gedit low_battery_pub.py

Here is the code.

Now let’s add a charging battery publisher. This publisher indicates the battery is CHARGING (i.e. connected to the docking station).

cd ~/dev_ws/src/two_wheeled_robot/scripts/battery_state
gedit charging_battery_pub.py

Here is the code.

Don’t forget to update CMakeLists.txt with these new scripts.

Launch the Robot 

Open a new terminal window, and run the following node to indicate the battery is at full charge. 

ros2 run two_wheeled_robot full_battery_pub.py

Open a new terminal and launch the robot.

ros2 launch two_wheeled_robot hospital_world_connect_to_charging_dock_v5.launch.py

Select the Nav2 Goal button at the top of RViz and click somewhere on the map to command the robot to navigate to any reachable goal location.

The robot will move to the goal location.

While the robot is moving, stop the full_battery_pub.py node.

CTRL + C

Now run this command to indicate low battery:

ros2 run two_wheeled_robot low_battery_pub.py

The robot will plan a path to the staging area and then move along that path.

Once the robot reaches the staging area, the robot will navigate to the charging dock (i.e. ArUco marker) using the algorithm we developed earlier in this post. We assume the charging dock is located against a wall.

The algorithm (navigate_to_charging_dock_v3.py) works in four stages:

  1. Navigate to a staging area near the docking station once the battery gets below a certain level. 
  2. Navigate to an imaginary line that is perpendicular to the face of the ArUco marker.
  3. Face the direction of the ArUco marker.
  4. Move straight towards the ArUco marker, making small heading adjustments along the way.

This script uses the static transform publisher for the ArUco marker. In other words, it assumes we have hardcoded the position and orientation of the ArUco marker ahead of time. 

Once the robot has reached the charging dock, press CTRL + C to stop the low_battery_pub.py node, and type:

ros2 run two_wheeled_robot charging_battery_pub.py

That 1 for the power_supply_status indicates the battery is CHARGING.

Version 2: Do Not Hardcode the ArUco Marker Pose

Let’s create another navigation-to-charging dock script. In this script, we assume we have not hardcoded the exact pose of the ArUco marker ahead of time. The algorithm (navigate_to_charging_dock_v4.py) works in four stages:

  1. Navigate to a staging area near the docking station once the battery gets below a certain level. This staging area is 1.5 meters in front of the docking station.
  2. Rotate around to search for the ArUco marker using the robot’s camera.
  3. Once the ArUco marker is detected, move towards it, making minor heading adjustments as necessary.
  4. Stop once the robot gets close enough (<0.22 meters from the LIDAR) to the charging dock (or starts charging).
  5. Undock once the robot gets to a full charge.
  6. Wait for the next navigation goal.

We assume the charging dock is located against a wall.

Create an ArUco Marker Centroid Offset Publisher and an ArUco Marker Detector Boolean Publisher

Let’s create a script that will detect an ArUco marker and publish the ArUco marker’s centroid offset (along the horizontal axis of the camera image).

Go into the scripts section of your package.

cd ~/dev_ws/src/two_wheeled_robot/scripts
gedit aruco_marker_detector.py

Add this code.

#!/usr/bin/env python3 

# Detect an ArUco marker and publish the ArUco marker's centroid offset.
# The marker's centroid offset is along the horizontal axis of the camera image.
# Author:
# - Addison Sears-Collins
# - https://automaticaddison.com
  
# Import the necessary ROS 2 libraries
import rclpy # Python library for ROS 2
from rclpy.node import Node # Handles the creation of nodes
from rclpy.qos import qos_profile_sensor_data # Uses Best Effort reliability for camera
from cv_bridge import CvBridge # Package to convert between ROS and OpenCV Images
from geometry_msgs.msg import TransformStamped # Handles TransformStamped message
from sensor_msgs.msg import Image # Image is the message type
from std_msgs.msg import Bool # Handles boolean messages
from std_msgs.msg import Int32 # Handles int 32 type message

# Import Python libraries
import cv2 # OpenCV library
import numpy as np # Import Numpy library

# The different ArUco dictionaries built into the OpenCV library. 
ARUCO_DICT = {
  "DICT_4X4_50": cv2.aruco.DICT_4X4_50,
  "DICT_4X4_100": cv2.aruco.DICT_4X4_100,
  "DICT_4X4_250": cv2.aruco.DICT_4X4_250,
  "DICT_4X4_1000": cv2.aruco.DICT_4X4_1000,
  "DICT_5X5_50": cv2.aruco.DICT_5X5_50,
  "DICT_5X5_100": cv2.aruco.DICT_5X5_100,
  "DICT_5X5_250": cv2.aruco.DICT_5X5_250,
  "DICT_5X5_1000": cv2.aruco.DICT_5X5_1000,
  "DICT_6X6_50": cv2.aruco.DICT_6X6_50,
  "DICT_6X6_100": cv2.aruco.DICT_6X6_100,
  "DICT_6X6_250": cv2.aruco.DICT_6X6_250,
  "DICT_6X6_1000": cv2.aruco.DICT_6X6_1000,
  "DICT_7X7_50": cv2.aruco.DICT_7X7_50,
  "DICT_7X7_100": cv2.aruco.DICT_7X7_100,
  "DICT_7X7_250": cv2.aruco.DICT_7X7_250,
  "DICT_7X7_1000": cv2.aruco.DICT_7X7_1000,
  "DICT_ARUCO_ORIGINAL": cv2.aruco.DICT_ARUCO_ORIGINAL
}

class ArucoNode(Node):
  """
  Create an ArucoNode class, which is a subclass of the Node class.
  """
  def __init__(self):
    """
    Class constructor to set up the node
    """
    # Initiate the Node class's constructor and give it a name
    super().__init__('aruco_node')

    # Declare parameters
    self.declare_parameter("aruco_dictionary_name", "DICT_ARUCO_ORIGINAL")
    self.declare_parameter("aruco_marker_side_length", 0.05)
    self.declare_parameter("camera_calibration_parameters_filename", "/home/focalfossa/dev_ws/src/two_wheeled_robot/scripts/calibration_chessboard.yaml")
    self.declare_parameter("image_topic", "/depth_camera/image_raw")
    self.declare_parameter("aruco_marker_name", "aruco_marker")
    
    # Read parameters
    aruco_dictionary_name = self.get_parameter("aruco_dictionary_name").get_parameter_value().string_value
    self.aruco_marker_side_length = self.get_parameter("aruco_marker_side_length").get_parameter_value().double_value
    self.camera_calibration_parameters_filename = self.get_parameter(
      "camera_calibration_parameters_filename").get_parameter_value().string_value
    image_topic = self.get_parameter("image_topic").get_parameter_value().string_value
    self.aruco_marker_name = self.get_parameter("aruco_marker_name").get_parameter_value().string_value

    # Check that we have a valid ArUco marker
    if ARUCO_DICT.get(aruco_dictionary_name, None) is None:
      self.get_logger().info("[INFO] ArUCo tag of '{}' is not supported".format(
        args["type"]))
        
    # Load the camera parameters from the saved file
    cv_file = cv2.FileStorage(
      self.camera_calibration_parameters_filename, cv2.FILE_STORAGE_READ) 
    self.mtx = cv_file.getNode('K').mat()
    self.dst = cv_file.getNode('D').mat()
    cv_file.release()
    
    # Load the ArUco dictionary
    self.get_logger().info("[INFO] detecting '{}' markers...".format(
  	  aruco_dictionary_name))
    self.this_aruco_dictionary = cv2.aruco.Dictionary_get(ARUCO_DICT[aruco_dictionary_name])
    self.this_aruco_parameters = cv2.aruco.DetectorParameters_create()
    
    # Create the subscriber. This subscriber will receive an Image
    # from the image_topic. 
    self.subscription = self.create_subscription(
      Image, 
      image_topic, 
      self.listener_callback, 
      qos_profile=qos_profile_sensor_data)
    self.subscription # prevent unused variable warning
    
    # Create the publishers
    # Publishes if an ArUco marker was detected
    self.publisher_aruco_marker_detected = self.create_publisher(Bool, 'aruco_marker_detected', 10)
    
    # Publishes x-centroid offset with respect to the camera image
    self.publisher_offset_aruco_marker = self.create_publisher(Int32, 'aruco_marker_offset', 10)
    self.offset_aruco_marker = 0
      
    # Used to convert between ROS and OpenCV images
    self.bridge = CvBridge()
   
  def listener_callback(self, data):
    """
    Callback function.
    """
    # Convert ROS Image message to OpenCV image
    current_frame = self.bridge.imgmsg_to_cv2(data)
    
    # Detect ArUco markers in the video frame
    (corners, marker_ids, rejected) = cv2.aruco.detectMarkers(
      current_frame, self.this_aruco_dictionary, parameters=self.this_aruco_parameters,
      cameraMatrix=self.mtx, distCoeff=self.dst)
    
    # ArUco detected (True or False)
    aruco_detected_flag = Bool()
    aruco_detected_flag.data = False
    
    # ArUco center offset
    aruco_center_offset_msg = Int32()
    aruco_center_offset_msg.data = self.offset_aruco_marker
    
    image_width = current_frame.shape[1]

    # Check that at least one ArUco marker was detected
    if marker_ids is not None:
    
      # ArUco marker has been detected
      aruco_detected_flag.data = True
    
      # Draw a square around detected markers in the video frame
      cv2.aruco.drawDetectedMarkers(current_frame, corners, marker_ids)

      # Update the ArUco marker offset 
      M = cv2.moments(corners[0][0])
      cX = int(M["m10"] / M["m00"])
      cY = int(M["m01"] / M["m00"])
      
      self.offset_aruco_marker = cX - int(image_width/2)
      aruco_center_offset_msg.data = self.offset_aruco_marker

      cv2.putText(current_frame, "Center Offset: " + str(self.offset_aruco_marker), (cX - 40, cY - 40), 
        cv2.FONT_HERSHEY_COMPLEX, 0.7, (0, 255, 0), 2) 

    # Publish if ArUco marker has been detected or not
    self.publisher_aruco_marker_detected.publish(aruco_detected_flag)
    
    # Publish the center offset of the ArUco marker
    self.publisher_offset_aruco_marker.publish(aruco_center_offset_msg)
        
    # Display image for testing
    cv2.imshow("camera", current_frame)
    cv2.waitKey(1)
  
def main(args=None):
  
  # Initialize the rclpy library
  rclpy.init(args=args)
  
  # Create the node
  aruco_node = ArucoNode()
  
  # Spin the node so the callback function is called.
  rclpy.spin(aruco_node)
  
  # Destroy the node explicitly
  # (optional - otherwise it will be done automatically
  # when the garbage collector destroys the node object)
  aruco_node.destroy_node()
  
  # Shutdown the ROS client library for Python
  rclpy.shutdown()
  
if __name__ == '__main__':
  main()

Save the script and close.

Add execution permissions.

chmod +x aruco_marker_detector.py

Add the file to your CMakeLists.txt.

Create the Navigation Script

Go into the scripts section of your package.

cd ~/dev_ws/src/two_wheeled_robot/scripts
gedit navigate_to_charging_dock_v4.py

Add this code.

Save the script and close.

Add execution permissions.

chmod +x navigate_to_charging_dock_v4.py

Add the file to your CMakeLists.txt.

Create the Launch File

cd ~/dev_ws/src/two_wheeled_robot/launch/hospital_world/
gedit hospital_world_connect_to_charging_dock_v6.launch.py

Add this code.

Save and close the file.

Launch the Robot 

Open a new terminal window, and run the following node to indicate the battery is at full charge. 

ros2 run two_wheeled_robot full_battery_pub.py

Open a new terminal and launch the robot.

ros2 launch two_wheeled_robot hospital_world_connect_to_charging_dock_v6.launch.py

Select the Nav2 Goal button at the top of RViz and click somewhere on the map to command the robot to navigate to any reachable goal location.

The robot will move to the goal location.

While the robot is moving, stop the full_battery_pub.py node.

CTRL + C

Now run this command to indicate low battery:

ros2 run two_wheeled_robot low_battery_pub.py

The robot will plan a path to the staging area and then move along that path.

Once the robot reaches the staging area, the robot will navigate to the charging dock (i.e. ArUco marker) using the algorithm we developed earlier in this post. We assume the charging dock is located against a wall.

1-navigating-to-charging-dock
2-navigating-to-charging-dock-1

Once the robot has reached the charging dock, press CTRL + C to stop the low_battery_pub.py node, and type:

ros2 run two_wheeled_robot charging_battery_pub.py

That 1 for the power_supply_status indicates the battery is CHARGING.

You can now simulate the robot reaching full charge by typing:

ros2 run two_wheeled_robot full_battery_pub.py

The robot will undock from the docking station.

You can then give the robot a new goal using the RViz Nav2 Goal button, and repeat the entire process again.

The Importance of Having a Rear Camera

In a humanoid robotic application, you can alter the algorithm so the robot backs into the charging dock. This assumes that you have a camera on the rear of the robot. You can see an implementation like this on this YouTube video.

The benefit of the robot backing into the charging dock is the robot is ready to navigate when it receives a goal….no backing up needed.

You can also add magnetic charging contacts like on this Youtube video to facilitate the connection.

That’s it! Keep building!

How to Install Ubuntu and VirtualBox on a Windows PC

In this project, we will get started on our Robot Operating System (ROS) programming journey by installing Ubuntu. Ubuntu is a popular distribution (i.e. flavor) of the Linux operating system and is fully supported by ROS, the most popular framework for writing robotics software. If you have a Windows PC (I have Windows 11), I recommend you install a VirtualBox first and then install Ubuntu in the Virtual Box. I’ll show you how to do all that below.

The process for installing Ubuntu has a lot of steps, so hold on tight, don’t give up if something goes wrong, and go slowly so that you get your installation setup properly. Let’s get started!

Requirements

Here are the project requirements:

  • Install Ubuntu
  • Install Virtual Box
  • Install Ubuntu on VirtualBox
  • Learn Important Linux Terminal Commands

You Will Need

The following components are used in this project. You will need:

Directions

Download the Ubuntu Image

Check Ubuntu Releases to find the latest version of Ubuntu that has long term support (LTS). As of this writing, the latest release is Ubuntu 22.04 LTS (Jammy Jellyfish). You can download 22.04 if you want, but I will download Ubuntu 20.04 (Focal Fossa) since I need it for my ROS 2 Galactic work.

ubuntu_releases_2022

Click on the latest release of Ubuntu, and download the 64-bit PC (AMD64) desktop image (.iso file). The download process will take a while since it is a large file.

Before installing Ubuntu, you need to install Virtual Box. Virtual Box extends the capabilities of your host computer (i.e. your laptop or desktop PC) by enabling you to install and run an operating system in a new environment on top of your current operating system (Windows 11 in my case). The environment the new operating system will run in is known as a virtual machine (or guest).

Install VirtualBox

Let’s download VirtualBox. Go to VirtualBox downloads.

Select the platform package for Windows hosts to download the executable (.exe) file.

virtual_box

Detailed installation instructions for all operating systems (Windows, Mac OS, Linux, and Solaris) can be found in the instruction manual. Let’s go through the steps.

Double-click on the executable file.

setup_wizard_vbox

Click Next to begin the installation process.

Click Next to install the VirtualBox in the default location.

1-virtual-box-default-location

Click Next to choose the default features.

2-keep-everything-as-default

You will see a warning about network interfaces. Ignore it, and click Yes to proceed.

3-ignore-warning

You are now ready to install VirtualBox. Click Install to proceed.

4-ready-to-install

Click Finish to run VirtualBox.

5-click-finish

You can optionally delete the original executable file for VirtualBox (the one with the .exe extension). You don’t need it anymore.

Create a Virtual Machine

Now that VirtualBox is installed on your computer, we need to now create a new virtual machine.

Click the New button in the toolbar.

10-start-virtual-boxJPG

Type in a descriptive name for your operating system. You can stick with the default machine folder. The machine folder is where your virtual machines will be stored.

Also, select the operating system that you want to later install (Linux in this case).

12-virtualbox-name-operating-systemJPG

Click Next to proceed.

The default memory size for me is 1024 MB. That is not enough. Raise it to 6470 MB, and then click Next to proceed.

13-select-recommended-ramJPG

Make sure “Create a virtual hard disk now” is selected, and click Create.

14-create-virtual-hard-diskJPG

Select “VirtualBox Disk Image (VDI)”, and click Next.

Choose a Fixed size virtual hard disk so that you have better performance, and click next.

15-fixed-sizeJPG

You can stick with the default hard disk space (10GB as of the time of this writing) or go with something like 50 GB. I went with 50 GB. I also prefer to save my hard disk on my D drive (which has more space than my C drive). Then click Create.

16-default-hard-disk-sizeJPG
17-creating-virtual-diskJPG

Double-click on the left panel where it says “Ubuntu 18.04.” A startup window will appear.

18-new-virtual-machineJPG

Click the Folder icon next to Empty and select the Ubuntu image you downloaded earlier in this tutorial. It is a .iso file. You can make sure that your .iso file is somewhere in your C drive (doesn’t have to be on your Desktop). Then click Start to proceed.

19-startup-windowJPG

You might get an error that looks like this.

20-errorJPG

Click Close VM.

Enable Virtualization Technology on Your Computer

The error above arises because virtualization technology is disabled on your computer by default. We need to enable it. Let’s do that now.

Go down to the search area on your computer in the bottom left of your screen, and searched for “Advanced Startup”.

21-searchJPG

Click “Change Advanced Startup Options.”

Click Restart Now.

Click Troubleshoot.

Click Advanced Options.

Click UEFI Firmware Settings.

Click Restart to change the UEFI Firmware Settings.

Click F10 BIOS Setup.

Press the right arrow to go to System Configuration.

Scroll down to Virtualization Technology.

Press Enter to select Enabled.

Press the down arrow and then Enter to select Enabled.

Press F10 to save and exit.

Press Enter on Yes to save the changes.

Your computer will reboot.

Double-click on the VirtualBox icon to start it.

Click on the left panel of the window to start the Ubuntu virtual machine. Or you can just click Start in the toolbar.

22-restart-virtual-boxJPG

You should see the Ubuntu window appear.

Install Ubuntu

Click on “Install Ubuntu” to install Ubuntu.

23-ubuntu-startJPG

Click “Continue” to save the keyboard layout. The default English one is fine.

Keep clicking Continue through all the prompts. The options you want selected as you go through the prompts are the following:

  • Download updates while installing Ubuntu
  • Erase disk and install Ubuntu

You will get to a point where you will need to set your time zone. It will be a big map of the world that should automatically detect your location.

Type in a computer name and pick a username and password. I select the “Log in automatically” option.

When installation is complete, click “Restart Now.”

If you get a message that says “Please remove the installation medium. Then press ENTER,” just press ENTER.

When you reboot, you will go to the Ubuntu desktop.

25-welcome-to-ubuntuJPG

If at any time you want to exit Ubuntu, go to File → Close. You will be given the option to save your machine state so that you can pick up where you left off the next time you login to Ubuntu.

27-save-machine-stateJPG

Two additional notes….when you power up your VirtualBox, it is a good idea to go to Settings → Display and change your Video Memory to 128 MB. This will give you ample video memory.

32-video-memoryJPG

Also go to Settings → System → Processor, and adjust the number of CPUs to 4.

33-number-of-cpusJPG

If you at any point in the future run out of hard drive space for your virtual machine, you can move it to another drive (e.g. D drive) by following this article at Tech Republic.

Here are the complete settings on my Windows machine.

34-my-settingsJPG

Getting Used to Ubuntu

Similar to the C drive in Windows 10, Linux has a file system (everything branches from the / symbol). You can find it by clicking the icon of the file cabinet on the right side of the desktop. It is the third icon down in the image below.

28-file-cabinetJPG

Click “Other Locations.”

29-other-locationsJPG

Click “Computer.”

You will see all the files. For example, the path to the bin file is /bin 

30-ubuntu-file-managerJPG

You can find popular software applications for download in the Ubuntu Software module. It is the sixth icon in the left-hand panel. 

31-ubuntu-softwareJPG

Linux Terminal Commands With the Ubuntu Command-Line Interface

We could certainly navigate around Ubuntu using the graphical user interface, but we would miss out on being able to run advanced processes for ROS. This is where the Terminal application comes in handy. The Terminal application is the Ubuntu command-line interface and is similar to the Command Prompt on a Windows 10 system. It enables us to use Linux terminal commands.

To open the Terminal, click the bottom left where you see those nine white dots and search for “Terminal” at the top. 

35-nine-white-dotsJPG

Click on Terminal.

36-terminal-searchJPG
37-terminal-windowJPG

If you do a Google search for “common Linux terminal commands,” you should find some nice cheat sheets to use as a reference. Let’s try a few common commands below.

The following command retrieves a list of all the files and folders in the current directory.

ls
38-ls-commandJPG

If you want to change to the desktop, type:

cd Desktop

If you want to get the path to the current directory, type:

pwd

To go up one directory, type:

cd ~

To update the list of packages, type:

sudo apt-get update

The sudo keyword enables you to run a command as an administrator.

At this stage, it would be useful for you to install htop, an interactive system-monitor process-viewer and process-manager. To install it, type the following command:

sudo apt-get install htop

If at any point you want to remove it, you can type the following command:

sudo apt-get remove htop

To run, htop, you type:

htop

You can reboot the system using the following command:

sudo reboot

Finally, to shutdown the system, you type the following command:

sudo poweroff

How to Display the Path to a ROS 2 Package

Let’s suppose you want to display the full path to a ROS 2 package so that you know which directory on your computer the package is located in. Let’s suppose you are using ROS 2 Galactic (you will replace ‘galactic’ with whatever ROS 2 distribution you are using).

For example, suppose you want to know where the rviz2 package is located.

Here is what you do…

Open a terminal window, and type:

ros2 pkg prefix rviz2

Here is what the output would look like in a terminal window:

ros2pkgprefix

Then to get to the folder, type:

cd /opt/ros/galactic/share/rviz2