Startup/boot script with systemd issues

I’m trying run a TensorRT object detector at boot using the systemd method but I keep running into errors. My Jetson Nano 2GB is configured to auto-login to LXDE so I don’t have to input the password.

Build info. Jetpack 4.4.1
head -n 1 /etc/nv_tegra_release

#R32 (release), REVISION: 4.4, GCID: 23942405, BOARD: t210ref, EABI: aarch64, DATE: Fri Oct 16 19:44:43 UTC 2020

Here are the steps I took.

Created startup_detection_script.py

import os
os.system("cd /home/ag72/tensorrt_demos && python3 trt_ssd_async_ag.py --usb 0")

I tested it from the terminal and it runs fine.

Created custom_startup_detection_script_ag.service in /home/ag72/Startup.

[Unit]
Description=Execute this on boot
After=multi-user.target

[Service]
Type=idle
ExecStart=/usr/bin/python3 /home/ag72/Startup/startup_detection_script.py

[Install]
WantedBy=multi-user.target    

I also tried without After=multi-user.target and without Type=idle but I still got the same errors below.

Copied it to /etc/systemd/system.

sudo cp -i /home/ag72/Startup/custom_startup_detection_script_ag.service /etc/systemd/system

Then,

sudo systemctl start custom_startup_detection_script_ag
sudo systemctl status custom_startup_detection_script_ag
sudo systemctl enable custom_startup_detection_script_ag

Any time I edited, I did this.

sudo systemctl daemon-reload && sudo systemctl restart custom_startup_detection_script_ag

If I check the “status” as soon as it’s “started”, this is what I get.

custom_startup_detection_script_ag.service - Execute this on boot
   Loaded: loaded (/etc/systemd/system/custom_startup_detection_script_ag.service; enabled; vendor preset: enabled)
   Active: active (running) since Fri 2021-02-19 20:33:30 EST; 2s ago
 Main PID: 8590 (python3)
    Tasks: 6 (limit: 2282)
   CGroup: /system.slice/custom_startup_detection_script_ag.service
           ├─8590 /usr/bin/python3 /home/ag72/Startup/startup_detection_script.py
           ├─8613 sh -c cd /home/ag72/tensorrt_demos ; python3 trt_ssd_async_ag.py --usb 0
           └─8621 python3 trt_ssd_async_ag.py --usb 0

Feb 19 20:33:30 ag72 systemd[1]: Started Execute this on boot.

A few seconds later the LED on the webcam turns on only for a second. Then if I check the “status” again, this is what I get. I always get the OpenCV/Gstreamer warning when I run trt_ssd_async_ag.py from a terminal but the webcam and objection detection run fine, so I just ignore it.

custom_startup_detection_script_ag.service - Execute this on boot
   Loaded: loaded (/etc/systemd/system/custom_startup_detection_script_ag.service; enabled; vendor preset: enabled)
   Active: inactive (dead) since Fri 2021-02-19 16:49:27 EST; 3h 21min ago
  Process: 5363 ExecStart=/usr/bin/python3 /home/ag72/Startup/startup_detection_script.py (code=exited, status=0/SUCCESS)
 Main PID: 5363 (code=exited, status=0/SUCCESS)

Feb 19 16:49:16 ag72 systemd[1]: Started Execute this on boot.
Feb 19 16:49:26 ag72 python3[5363]: [ WARN:0] global /tmp/build_opencv/opencv/modules/videoio/src/cap_gstreamer.cpp (935) open OpenCV | GStreamer warning: Cannot query
Feb 19 16:49:26 ag72 python3[5363]: Unable to init server: Could not connect: Connection refused
Feb 19 16:49:26 ag72 python3[5561]: cannot open display:

I tried to incorporate some of the solutions in How to run a script on boot as well as adding startlxde and export DISPLAY=:1.0 without any luck.

Any help is much appreciated.

Hi,

Could you check if the script is launched after the DISPLAY is ready.
Or could you add some delay (ex. wait for 30 sec) to the script to make sure the DISPLAY is initialized and ready?

Thanks.

Hi @AastaLLL I tried adding time.sleep(30.0) in my code and the LED stays on for 30 seconds and then shuts off and produces the same error, except when I place it after open_window. I’m guessing that’s the issue but still haven’t found it by moving around the sleep.

Here is the def main() function in my object detection script.

def main():
    args = parse_args()
    cam = Camera(args)
    if not cam.isOpened():
        raise SystemExit('ERROR: failed to open camera!')

    cuda.init()  # init pycuda driver
    
    cls_dict = get_cls_dict(args.model.split('_')[3]) #'ag' is 4th word split by '_' in 'ssd_mobilenet_v2_ag_20k_b24'
    
    open_window(
        WINDOW_NAME, 'Camera TensorRT SSD Demo',
        cam.img_width, cam.img_height)
    time.sleep(5.0)
    vis = BBoxVisualization(cls_dict)
    arrows = ArrowVisualization(cls_dict) #AG added
    condition = threading.Condition()
    trt_thread = TrtThread(condition, cam, args.model, conf_th=0.3)
    trt_thread.start()  # start the child thread
    loop_and_display(condition, vis, arrows) #AG added arrows
    trt_thread.stop()   # stop the child thread
    
    GPIO.cleanup()  # Added by AG, cleanup all GPIOs

    cam.release()
    cv2.destroyAllWindows()


if __name__ == '__main__':
    main()

Here is the open_window code. If I sleep after the first line the LED just stays on and that’s it. After cv2.namedWindow it flashes and then shuts off like before.

def open_window(window_name, title, width=None, height=None):
    """Open the display window."""
    cv2.namedWindow(window_name, cv2.WINDOW_NORMAL)
    cv2.setWindowTitle(window_name, title)
    if width and height:
        cv2.resizeWindow(window_name, width, height)

I found a solution. Thanks for your help @AastaLLL.

It looks like it was my service script that was the issue. I added XAUTHORITY and DISPLAY and it works great now. ExecStartPre was also added just to delay the start of the script but wasn’t the reason for it working.

Working code looks like this:

[Unit]
Description=Execute this on boot
After=multi-user.target

[Service]
Environment=XAUTHORITY=/home/ag72/.Xauthority
Environment=DISPLAY=:0
ExecStartPre=/bin/sleep 10
ExecStart=/usr/bin/python3 /home/ag72/Startup/startup_detection_script.py

[Install]
WantedBy=multi-user.target

Good to know this!
Also thanks to share the experience with us.