Containers

An operating system is built out of many components, in the case of Linux we typically have:

  • The kernel: manages devices, processes, memory, etc.
  • System manager: first and only process that the kernel starts, i.e. systemd.
  • On top of this you may run:
    • A window manager to provide a GUI.
    • Package manager to handle dependencies between software programs.

Hypervisor

A hypervisor is a virtual machine manager which separates the hardware layer from the software layers above, allowing two or more kernels to share system resources.

Link to original

Type 1 virtual machine

Type 1 virtual machines can act at the hardware level so when the computer is turned on, multiple OSes can start at the same time.

Link to original

Type 2 virtual machines run the hypervisor within another operating system. When starting the computer, a single OS is booted (host) and then the user starts the hypervisor which creates a virtualised isolated environment in which the guest OS runs in.

Containers are not virtual machines but instead use the kernel of the OS they are running in, they bundle their own file system with most system directories, and they are isolated from the main root file system. Processes inside the container believe that / is the root of the container not of the host. This has no compute overhead compared with virtual machines.

Jobs

Stream redirection

All processes we run on Linux has three streams, standard input, output and error.

We can append a > character in POSIX terminals to redirect an outgoing stream to some file, i.e. discard all stdout: roscore >/dev/null.

We can “pipe” between two processes like so:

  • ls -l ~ | grep Downloads

We can use a < character to read from a file:

  • grep text < my_file.txt

You can redirect a specific stream by specifying an integer, i.e. some comand 2> errors.txt

You can redirect both by using &> (stdout & stderr).

Job Management

You can stop any process and move it to the background by pressing CTRL + Z. This produces the output:

[1]+ Stopped     roscore

You can run this process in the background using bg 1. You can list all jobs by running jobs. You can bring a job to the foreground by running fg 1.

You can start a job in one go by appending &:

# ignore stdout and start background job
roscore >/dev/null &

Process Management

You can see a hierarchy of processes on the system by running the command pstree.

You can use ps in different ways to just list processes:

  • ps -e: more information
  • ps -ef: even more information
  • ps -eF: even even more information
  • ps -elF: long form even even more information
  • ps -U user: list by user
  • ps -C roscore: list by command

ROS Alias

You should setup an alias to drop into ROS.

Example, with fish, create a new fish configuration file /home/mink/.config/fish/functions/ros.fish:

function ros
  set -x ROS_MASTER_URI http://furry:11311/
  /usr/bin/env /home/mink/Applications/ros-container.sif $argv; 
end

ROS Packages

To create a ROS package, create a new workspace by just creating a new directory, i.e. ros_workspace. Inside the workspace, create a new directory src.

Drop into the container at this stage.

Now enter the src folder and run:

# abc is the name
# rospy, std_msgs are dependencies
catkin_create_pkg abc rospy std_msgs

You can now edit src/ros_pkg/package.xml with info.

Now create a new src/hello_node.py inside rospkg:

#!/usr/bin/env python3
 
import rospy
from std_msgs.msg import String
 
 
def run():
    pub = rospy.Publisher('hello', String, queue_size=10)
    rospy.init_node('hello_node', anonymous=True)
 
    rate = rospy.Rate(10)  # 10 Hz
    while not rospy.is_shutdown():
        hello_str = "hello!"
        pub.publish(hello_str)
        rate.sleep()
 
 
if __name__ == "__main__":
    try:
        run()
    except rospy.ROSInterruptException:
        pass

Now within the src folder run:

# run roscore if you haven't yet
roscore &
 
# add executable bit
chmod +x hello_node.py
 
# run hello_node
./hello_node.py