[카테고리:] 생활코딩

  • ros를 nvidia docker로 돌리기

    ros를 nvidia docker로 돌리기

    최신 ros docker 이미지로 gazebo를 그냥 돌리면 초당 4 frame으로 업데이트 된다. 참고 사용 사용하려다 느려 도저히 사용할 수 없어 방법을 찾아 봤다. nvidia-docker로 runtime을 nvidia로 입력해 주면 초 당 60 프레임으로 업데이트 된다. 금방 할 수 있어 찾은 보람이 있다.

    http://wiki.ros.org/docker/Tutorials/Hardware%20Acceleration

    위 사이트를 참조하여 아래 Dockerfile로 새롭게 이미지를 만들었다.

    FROM osrf/ros:noetic-desktop-full
    
    # nvidia-container-runtime
    ENV NVIDIA_VISIBLE_DEVICES \
        ${NVIDIA_VISIBLE_DEVICES:-all}
    ENV NVIDIA_DRIVER_CAPABILITIES \
        ${NVIDIA_DRIVER_CAPABILITIES:+$NVIDIA_DRIVER_CAPABILITIES,}graphics
    
    USER root
    RUN apt -y update
    RUN apt -y install vim
    COPY ./.bashrc /root/

    매번 입력하기 귀찮으니 ros 강의 자료에 있는 alias를 참조하여 .bashrc를 루트 홈에 넣었다. 처음 컨테이너를 실행할 때 entrypoint로 bashrc를 자동으로 실행하는데, 두번째 부터는 같은 컨테이너에 붙여도 bashrc를 실행하지 않는다. docker exec 옵션에 없는 듯 하다.

    now0930@amd2004:~/dockerBuild/ros$ docker exec -it noetic_ros /bin/bash
    root@amd2004:/# sds

    매번 컨테이너에 들어간 후 sds를 실행해야 하여 귀찮다.

    now0930@amd2004:~/dockerBuild/ros$ cat .bashrc 
    alias eb='vi ~/.bashrc'
    alias sb='source ~/.bashrc'
    alias cma='catkin_make -DCATKIN_WHITELIST_PACKAGES=""'
    alias cop='catkin_make --only-pkg-with-deps'
    alias sds='source /opt/ros/noetic/setup.bash'
    alias axclient='rosrun actionlib axclient.py'
    set -o vi

    xhost로 local을 추가하여 docker 출력을 돌린다. docer run을 다음과 같이 한다.

    now0930@amd2004:~/dockerBuild/ros$ sudo xhost +local:docker
    [sudo] now0930 암호: 
    non-network local connections being added to access control list
    now0930@amd2004:~/dockerBuild/ros$ xhost 
    access control enabled, only authorized clients can connect
    LOCAL:
    INET:localhost
    SI:localuser:now0930
    now0930@amd2004:~/dockerBuild/ros$ 
    #!/bin/bash
    nvidia-docker run -it -v /run/user/1000:/run/user/1000 -v /dev:/dev -v /tmp/.X11-unix:/tmp/.X11-unix:ro \
    	-v /home/now0930/ros_test:/home/ros_test --name noetic_ros \
    	--privileged --ipc=host --shm-size=512m --net=host -e DISPLAY=$DISPLAY \
    	-e XDG_RUNTIME_DIR=/run/user/1000 --runtime=nvidia \
    	osrf/ros_custom:noetic-desktop-full 
  • 서버 재설치 feat. docker

    mysql을 8.0으로 업데이트 하면서 기존 데이터 베이스가 날아갔고, 다시 복구되지도 않았다. 이번 기회에 서버를 재설치 하고 요즘 뜨는 docker로 서비스를 돌리기로 해다. 의지는 있지만 docker 기본 개념과 철학을 잘 이해하지 못한 상태에서 apache, mysql을 연동하는데 너무나 어려웠다.

    • docker container는 한 개 daemon만 실행한다.
    • 여러 daemon이 필요하면 container를 새로 만든다.
    • docker build 옵션 중 cmd ,entrypoint는 마지막 한 개만 유효하다.
    • docker run에 –link 옵션으로 다른 container를 연결하면 hosts 파일에 container 이름이 추가된다. 다른 container에 이름으로 접근할 수 있다.
    • docker run 중 -p 옵션으로 포트를 설정하지 않으면 expose 옵션으로 열린 포트를 외부에서 접근할 수 없다.
    • mysql docker image에 bind-address 옵션이 없고, 넣어도 역할을 하지 않는다.
    • link 옵션 대신 network으로 추가할 수 있는데, 힘들어서 못 하겠다.
    • mysql 로 MYSQL_ROOT_PASSWORD로 실행한 후 mysql < file.sql로 복구한 뒤, flush priviliges로 복구 파일 password를 적용시켜야 한다. 파일에 저장된 root password로 데이터 베이스 비밀번호를 초기화 할 수 있다.
    • https 설정시 lets encrypt로 받은 키를 configure file에 default에 넣지 않고 별도 virtual host를 설정하면SSL_ERROR_RX_RECORD_TOO_LONG 가 뜬다.
    • apache에서 database에 접근하기 위한 사용자 이름, 패스워드를 별도 파일을 만들어 접근할 때, docker container에 넣어 줘야 한다.

    이 밖에도 수 많은 시행 착오가 있었다. 게다가 가장 최근 백업 파일이 두 달 전 파일이었다. 주중에 한 번씩 백업 하도록 수정했다. 설정하기는 힘들었어도 사용해 보니 편하다. 간단한 업데이트로 서버를 재설장 한다는게 말도 안되지만 잦은 빈도로 발생한다. phpmyadmin도 설치해야 하는데, 지금 엄두가 안 난다.

    두 달치 기록을 날리고 값진 경험을 했다. 아직도 복구 중…

  • sensehat 온도 + LED matrix(2)

    sensehat 온도 + LED matrix(2)

    제한된 화면에 온도, 습도를 어떻게 표시할까 고민하다, 디바이스를 2개를 만들로 했다. 사용자가 디바이스 개수를 제한 없이 만들 수 있는 점이 좋다. 2개를 만들어 온도로 한 개, 습도로 한 개를 할당 했다.

    위 그림에서 사용자가 rs-tmpre1를 읽어(read) module이 저장한 HTS221 온도 관련 레지스터 값을 얻는다. 사용자가 받은 값으로 온도를 계산한 후 LED Matrix를 빨강으로 설정하고, 커널로 쓴다(write). 사용자가 rs-tempre2를 읽어(read) module이 저장한 HTS221 습도 관련 레지스터 값을 얻는다. 역시 받은 값으로 습도를 계산하고, LED Matrix를 녹색으로 설정, 커널로 쓴다(write). 사용자 프로그램이 일정 주기로 계속한다.

    LED Matrix가 숫자를 보여주는 방식이 너무 촌스럽다. 좀 개선해야 겠다.

    1. 부팅
    2. 내가 만든 모듈 로딩
    3. 사용자 프로그램 실행

    1 ~ 3번을 자동으로 하고 싶었다. 이게 좀 까다롭다. 처음에는 간단하게 crontab으로 @reboot로 설정했으나, 실패했다. 모듈이 올라가기 전에 사용자 프로그램이 실행된다. 찾던 중 udev가 이벤트를 감지(디바이스 추가, 삭제)하여 사용자 정의 행동을 한다고 알았다.

    udev에 등록하려면 디바이스 정보를 알아야 된다. 왜 class로 추가하는지 느꼈다. 인터넷 검색으로 다음과 같이 알아냈다.

    pi@raspberrypi:~ $ udevadm info /dev/rs-tmpre1
    P: /devices/virtual/rpi-sensehat/rs-tmpre1
    N: rs-tmpre1
    L: 0
    E: DEVPATH=/devices/virtual/rpi-sensehat/rs-tmpre1
    E: DEVNAME=/dev/rs-tmpre1
    E: DEVMODE=0666
    E: MAJOR=235
    E: MINOR=0
    E: SUBSYSTEM=rpi-sensehat
    
    pi@raspberrypi:~ $ udevadm info /dev/rs-tmpre2
    P: /devices/virtual/rpi-sensehat/rs-tmpre2
    N: rs-tmpre2
    L: 0
    E: DEVPATH=/devices/virtual/rpi-sensehat/rs-tmpre2
    E: DEVNAME=/dev/rs-tmpre2
    E: DEVMODE=0666
    E: MAJOR=235
    E: MINOR=1
    E: SUBSYSTEM=rpi-sensehat
    
    pi@raspberrypi:/dev $ udevadm info -a -n /dev/rs-tmpre1
    
    Udevadm info starts with the device specified by the devpath and then
    walks up the chain of parent devices. It prints for every device
    found, all possible attributes in the udev rules key format.
    A rule to match, can be composed by the attributes of the device
    and the attributes from one single parent device.
    
      looking at device '/devices/virtual/rpi-sensehat/rs-tmpre1':
        KERNEL=="rs-tmpre1"
        SUBSYSTEM=="rpi-sensehat"
        DRIVER==""
        ATTR{power/control}=="auto"
        ATTR{power/runtime_active_time}=="0"
        ATTR{power/runtime_status}=="unsupported"
        ATTR{power/runtime_suspended_time}=="0"

    아래 스크립트와 같이 사용자 정의 rules를 만들면 전원이 들어가면서 실행됨을 확인 했다.

    pi@raspberrypi:/etc/udev/rules.d $ pwd
    /etc/udev/rules.d
    pi@raspberrypi:/etc/udev/rules.d $ cat 100-sensehat.rules 
    ACTION=="add", SUBSYSTEM=="rpi-sense-tmpre", KERNEL=="rs-tmpre2", RUN+="/bin/sensehat_display"

    아쉽게도 udev로 등록한 프로세가 오래 못산다. 이벤트가 끝나면 process가 죽는다. systemctl로 서비스 형식으로 등록해야 한다. 참조하여 아래와 같이 설정했다. 잘 된다. 이제 LED matrix를 어떻게 해 봐야겠다.

    pi@raspberrypi:/etc/systemd/system $ cat sensehat_display.service 
    [Unit]
    Description=SenseHat Temperatur & Humidity Monitor
    
    [Service]
    Type=simple
    ExecStart=/usr/bin/sensehat_display
    
    [Install]
    https://github.com/now0930/sensehat_toy

    참조 사이트

  • sensehat 온도 + LED matrix(1)

    sensehat 온도 + LED matrix(1)

    온도를 LED Matrix에 표시하기

    나름 쓸만한 디바이스를 만들기 위해 온도계를 구상해 봤다. 지마켓에서 온도, 습도, 시각을 측정하는 디바이스를 5,400원에 구매할 수 있다. 라즈베리 파이 + sensehat = 120,000원 정도 하려나? 약 20배 비싸지만 인터넷에 연결되어 싸다고 세뇌시키고 있다. ^^! 그런데, sensehat에 있는 hts221이 보드에 붙어 있다. 실내 온도를 측정하지 않고 보드 온도를 측정 하고 있다.

    HTS221로 받은 온도를 LED matrix에 표시했다. 숫자를 바로 LED matrix에 표시할 수 없어, 각 숫자에 맞춰 8 * 8 * 3가지 색을 정의 해야 한다. 이게 참 시간을 잡아먹는다. 왜 frame buffer를 써야 되는지 알 만했다.

    기본 설정으로는 온도를 바로바로 측정할 수 없다. 02h 레지스터 ODR을 1Hz로 설정해야 바로 측정할 수 있다. 12.5Hz로 측정하면 왜 안되는지 잘 모르겠다.

    kernel에서 float 형식을 사용할 수 없다. 모든 데이터를 받아 사용자 영역에서 float 형식으로 온도를 계산해야 할 듯 하다. 지금은 user program이 led matrix를 써 주면 바로 표시하지만, timer나 workqueue를 추가하여 필요할 때 표시하게 수정할 것 이다. 아니면 습도도 받아 그래프로 표시하던가. 온도, 습도를 표시하려면 그래프가 좋아 보인다.

    코드

    참조 사이트

    https://github.com/ControlEverythingCommunity/HTS221/blob/master/C/HTS221.c

  • sensehat i2c led2472g(2)

    pixel 제어하기

    8 * 8 LED matrix 색, 위치를 개별 제어하려면 픽셀 주소, 색을 알아야 한다. 가로 8, 세로 8, 1 점 당 rgb 3개 = 192개 주소가 rgb 값을 갖는다. 여러 삽질과 인터넷 검색으로 아래 정보를 확인 했다. 개별 소자를 다음과 같이 제어할 수 있다.

    $>i2cset 1(i2c 채널 번호) 0x47?(노드 번호) 0x1(점 주소) 0x10(색 값)

    각 점별 최대 0x63을 입력할 수 있다. 0x63을 넘어가면 다른 픽셀에 영향을 미치는지 깜박였던 것 같다. python으로 작성한 LED matrix display 코드를 그대로 사용해도 된다. 각 좌표에서 1을 빼야 된다.

    픽셀로 제어하다 보니 폰트, 그림 이런 거 없다. 왜 frame buffer로 제어했는지 이제 이해간다!!

    참조 사이트