Monday, June 5, 2023

How to sync the time between 2 Ubuntu systems on an isolated network

I wanted to match the times between two systems on an isolated network running Ubuntu 22. This can be done using chrony ( on the two systems - one system serves as the local time server to the other client system. 

Setting up the Server

  1. Optional. If chrony is not installed, run the following command in the Terminal to install it.

    $ sudo apt install chrony

  2. Using a text editor, add the following lines to the file /etc/chrony/chrony.conf.

    local stratum 8

    Note 1: The keyword local tells chrony to server isolated networks.
    Note 2: The allow keyword specifies the IP address of the client to server

  3. Restart the chrony service using the following command. Or you can reboot.

    $ sudo systemctl restart chronyd

Setting up the Client

  1.  Optional. If chrony is not installed, run the following command in the Terminal to install it.

    $ sudo apt install chrony

  2. Using a text editor, add the following to the file /etc/chrony/chrony.conf.

    server yyy.yyy.yyy.yyy minpoll 0 maxpoll 5 maxdelay 0.1

  3. Restart the chrony service using the following command. Or reboot.

    $ sudo systemctl restart chronyd

  4. To verify whether the syncing is working, the following command can be used.

    $ chronyc sources -v

    Note: If the sync is successful, the MS column should be showing the symbols ^* for the IP address of the server entry.


Monday, April 3, 2023

How to create a Arm64 Ubuntu virtual machine using Virt-Manager

I wanted to run Ubuntu on an Arm64/Aarch64 virtual machine on a host Intel Linux computer for the longest time for compiling binaries for Raspberry Pis and other SBC boards. I finally figured out how to do it with virt-manager, and it is quite simple as clicking and selecting options on the virt-manager graphical user interface. The instructions below show how it is done.

Download and install prerequisites

  1. In Ubuntu, open up a Terminal and enter the following commands to install the prerequisite software.

    $ sudo apt install qemu-kvm \
    libvirt-daemon-system \
    libvirt-clients \
    bridge-utils \
    virt-manager \
    qemu-system-arm \
    qemu-efi-aarch64 \

  2. Open up an Internet browser. Download an Ubuntu Arm64 image to install. For example:

 Create the virtual machine

  1. In Ubuntu, click the Virtual Machine Manager icon.

    The Virtual Machine Manager application appears.

  2. Select File | Create New Virtual Machine.

    The New VM dialog box pops up.

  3. Choose Local install media (ISO image or CDROM).

  4. In the Architecture options, choose aarch64 architecture. Click Forward.

    Step 2 of 5 pages appears.

  5. In the Choose ISO or CDROM install media field, choose the iso image downloaded previously.

  6. Click Forward. If necessary, change the memory size and the number of CPUs.

    Step 3 of 5 pages appear.

  7. Click Forward. If necessary, change the disk image size to a suitable size.

    Step 4 of 5 appears.

  8. Click Forward.

    Step 5 of 5 appears.

  9. Optional. In the Name field, type in a desired name.

  10. Toggle On the Customize configuration before install field.

  11. Click Finish.

    The 'vm name' on QEMU/KVM dialog box appears.

  12. In the Hypervisor Details group, change the Firmware to UEFI aarch64.

  13. Click Apply. Then click the Begin Installation button and follow the prompts to complete the installation.

    The installation begins...

Monday, March 27, 2023

Convert a sequence of JPG images into a MP4 video using FFMPEG

If you have a sequence of images like the screen shot below, it is quite straightforward to use ffmpeg to concatenate them into a single video file. 

Obviously, you need to specify the image file name and sequence pattern, the frame rate to show each image as shown in the example ffmpeg command below.

$ ffmpeg -hide_banner \
-f image2 \
-framerate 1 \
-start_number 1 \
-i %02d.jpeg \
-vcodec mpeg4  \

where -f specifies the input format as image,

-framerate specifies the rate in Hz at which to display each image frame,

-start_number specifies the starting number of the image frame sequence,

-i specifies the file name and sequence pattern, e.g. %02d means a pattern of 2 digits with a prefix character '0' for single digit numbers,

-vcodec tells ffmpeg to output mpeg4 format.

 Running the command will display the following output and generate the output video file output.mp4.

Monday, January 30, 2023

Fixing a kernel panic error when installing Ubuntu 20.04 in VirtualBox

I was trying to create an Ubuntu 20.04 virtual machine using Oracle VirtualBox but I kept encountering this error with the message "...end kernel panic - not syncing: Attempted to kill the idle task!..." The screenshot below shows the error in VirtualBox.

Eventually, I found out the error was caused by inadequate alllocated CPU resources in VirtualBox. By default, the number of CPU allocated for the VM is 1, as shown in the screen shot below.

Simply increasing the number of CPU to at least 2 helped to solve the kernel panic error in this case.

Monday, December 12, 2022

How to read an array from a ROS1 launch file into a C++ vector variable

I was having problems reading an array of doubles in a ROS launch file into a vector variable in a C++ ROS1 program node. After some digging around, I found I was doing it the wrong way; instead of using the <param> tag in the ROS launch file, I should be using the <rosparam> tag. 

The example ROS launch file listing shows the correct way to enter an array, e.g. [0.01, 0.1, 0.2] with the <rosparam> tag:

?xml version="1.0" encoding="UTF-8"?>
  <node pkg="learning_tutorial" type="my_node" name="my_node">
        <param name="my_string_param" value="hello" />
        <rosparam param="my_array_param">[0.01, 0.1, 0.2]</rosparam>

Then in the ROS C++ code, I could do the following to read the array:

// ...etc...

using namespace ros;
using namespace std;

vector<double> myArrayParam;
NodeHandle nh;

// Read the my_array_param from the launch file into the myArrayParam variable
nh.param<vector<double>> ( "my_array_param", myArrayParam, { 1, 2, 3});

// Just print out the array parameter
ROS_INFO ( "My array: %f, %f, %f", myArrayParam[0], myArrayParam[1], myArrayParam[2]);
// ...etc...

Hope this helps somebody.

Monday, December 5, 2022

Using GIMP to copy an image layer into a channel

In GIMP, it is possible to copy a colored image layer into a single grayscale channel. Here's how to do the job.

Create an empty channel

  1. In GIMP, open up the image file.

  2. Click the Channels tab on the bottom right.

  3. Then click the Create a new channel icon.

    The New Channel dialog box appears.

  4. Optional. In the Channel name field, type in a name, e.g. flats. In the Fill opacity field, slide to 50.0.
  5. Click OK.

    A new channel is created.

Copy and paste the colored image into the channel

  1. Click the Layers tab. Click the image layer, e.g. bored-tiger.jpg to make sure it is active.

  2. In the menu, choose Select | All. Then choose Edit | Copy.

    The layer is copied to the clipboard.

  3. Click the Channels tab. Click the previously created channel, e.g. flats.

  4. In the menu, select Edit | Paste in Place

  5. Then click the Layers tab.

    A Floating Selection (Pasted Layer) is visible in the Layers list.

  6. Click the green Anchor the floating layer icon.

    The pasted layer is added to the active channel.

  7. Optional. Click the Channels tab.

    Note the channel thumbnail has been updated with a grayscale image of the pasted layer.

Monday, November 28, 2022

Using GIMP's color channels to remove blue guide lines from inked line art

Penciled comic book art typically have blue guide lines (and text) as shown in the screen shot below. 

The sketch can be downloaded from this site if you want to practice with it. There are a number of ways to remove the blue lines from the image. I will be using the Color channels panel to remove the guide lines.

The steps:

Remove pixels from the Red and Green channels

  1. In GIMP, open up the image. Click the Channels tab on the bottom right.

  2. Click the Blue channel to deselect it.

  3. In the Tool palette, click the Fill icon.

  4. Toggle on the FG color fill. Make sure the foreground color is black since we want to remove the Red and Green channels data.

  5. Then, click anywhere on the canvas.

    The background becomes blue.

Create the line art in the Red and Green channels

  1.  In the Channels tab, press the mouse right click button on the Blue channel.

    A popup menu appears.

  2. Choose Channel to Selection.

    The blue channel's non-zero pixels are selected.

  3. In the Tool box, click the Fill icon. Toggle on the BG color fill option. (Note: the background color should be white). Then click anywhere in the selection on the canvas.

    The background becomes white.

  4. In the Channels tab, click the Blue channel to select it again.  Then in the menu, choose Select | None to clear the selection.

Use Threshold to clean up the line work

  1. In the menu, select Colors | Threshold.

    The Threshold dialog box appears.

  2.  Drag the black triangle until you are satisfied with the contrast between the line work and the background.

  3. Save your work.