2026년 9월 21일 월요일

Linux ROS(Robot Operating System)

 ROS의 핵심 특징 및 장점 (쉽게 이해하기)

ROS는 로봇을 만드는 데 필요한 모든 부품(센서, 모터, 컴퓨터 등)이 서로 대화를 나눌 수 있게 해주는 '통역사'이자 '표준 규격'입니다.
  • 바퀴 재발명 금지: 로봇이 스스로 주변을 인식하고 경로를 찾아가는 복잡한 알고리즘(SLAM, 네비게이션)이 이미 오픈소스로 전 세계에 공개되어 있습니다. 개발자는 이를 가져다 쓰기만 하면 됩니다.
  • 레고 블록 같은 조립식 구조: 카메라 노드, 바퀴 제어 노드, GPS 노드가 각각 독립적으로 작동하므로, 부품이 바뀌어도 해당 소프트웨어 블록만 갈아 끼우면 됩니다.
  • 강력한 시뮬레이션 지원: 장비나 차량이 실제로 없어도 컴퓨터 화면(Rviz, Gazebo) 안에서 가상으로 주행하고 센서 데이터를 테스트할 수 있어 개발 비용이 획기적으로 줄어듭니다.


  • 우분투와 ROS 버전 매칭: ROS는 우분투 버전에 따라 설치할 수 있는 버전이 정해져 있습니다.
    • 우분투 22.04 LTS ➡️ ROS 2 Humble (가장 안정적이고 널리 쓰임)
    • 우분투 24.04 LTS ➡️ ROS 2 Jazzy (최신 LTS 버전)
  • 저장 공간 관리: 256GB SSD는 개발용으로 충분하지만, ROS 라이브러리를 빌드하거나 3D 시뮬레이션(Gazebo 등)을 자주 하면 용량이 찰 수 있으니 주기적인 캐시 정리가 필요합니다.
  • 가벼운 IDE 추천: 램 8GB 환경에서는 무거운 무거운 툴보다는 가벼운 VS Code(Visual Studio Code)에 ROS/Python 확장 프로그램을 얹어 사용하는 것을 추천합니다.
  • 2026년 9월 14일 월요일

    raspberry pi 3 B+ tapo c545d CCTV RTSP stream

    cat > /tmp/run_dual.sh << 'SCRIPT_EOF'

    #!/bin/sh

    while true; do

        exec 9<>/dev/dri/card0 2>/dev/null

        if [ $? -ne 0 ]; then

            echo "DRM 장치 열기 실패, 3초 후 재시도" >> /tmp/dualplane5.log

            sleep 3

            continue

        fi


        > /tmp/dualplane5.log


        GST_DEBUG=3 gst-launch-1.0 \

        rtspsrc location="rtsp://tapoID:tapoPASSWD@192.168.0.2:554/stream2" latency=0 protocols=tcp name=src1 timeout=5000000 \

          src1. ! application/x-rtp,media=video ! rtph264depay ! h264parse ! avdec_h264 \

          ! kmssink sync=false skip-vsync=true fd=9 plane-id=96 render-rectangle="<0,0,960,1080>" \

        rtspsrc location="rtsp://tapoID:tapoPASSWD@192.168.0.2:554/stream7" latency=0 protocols=tcp name=src2 timeout=5000000 \

          src2. ! application/x-rtp,media=video ! rtph264depay ! h264parse ! avdec_h264 \

          ! kmssink sync=false skip-vsync=true fd=9 plane-id=107 render-rectangle="<960,0,960,1080>" \

          >> /tmp/dualplane5.log 2>&1 &


        GST_PID=$!

        LAST_SIZE=0

        STALL_COUNT=0


        while kill -0 $GST_PID 2>/dev/null; do

            sleep 5

            CUR_SIZE=$(wc -c < /tmp/dualplane5.log 2>/dev/null)


            if [ "$CUR_SIZE" = "$LAST_SIZE" ]; then

                STALL_COUNT=$((STALL_COUNT + 1))

            else

                STALL_COUNT=0

            fi

            LAST_SIZE=$CUR_SIZE


            # 15초(3회 연속) 동안 로그 크기 변화 없으면 = 멈춘 것으로 판단

            if [ $STALL_COUNT -ge 3 ]; then

                echo "15초간 활동 없음, 강제 재시작" >> /tmp/dualplane5.log

                kill -9 $GST_PID 2>/dev/null

                break

            fi

        done


        exec 9<&-

        echo "파이프라인 종료됨, 3초 후 재시작" >> /tmp/dualplane5.log

        sleep 3

    done

    SCRIPT_EOF

    chmod +x /tmp/run_dual.sh

    2026년 8월 31일 월요일

    2026년 7월 23일 목요일

    weintek cmt3072xh2 tapo c545d CCTV 화면 재생

     macro_command main()

    // 1. 문자열 배열 변수 선언과 동시에 명시적 빈칸 초기화 실행! (= "" 필수 ⚠️)

    // 한화면에서 비디오입력 오브젝트2개에 각각 CCTV 화면 입력 안됨. 한화면 하나만.

    char url_stream2[128] = ""

    char url_stream7[128] = ""

    unsigned short play_cmd = 0

    bool button_state = true


    // 2. 주간(stream2) 주소와 야간(stream7) 주소를 공백 없이 문자로 완벽히 복사 정의

    StringCopy("tapotapo1234:tapotapo321654987@192.168.0.2:554/stream2", url_stream2[0])

    StringCopy("tapotapo1234:tapotapo321654987@192.168.0.2:554/stream7", url_stream7[0])


    // 3. 토글 버튼(LB 50)의 현재 온/오프 상태를 읽어옴

    GetData(button_state, "Local HMI", LB, 50, 1)



    // [조건 1] 버튼을 한 번 눌러서 ON(true) 상태가 되었다면? ➡️ stream7(야간적외선) 주소 주입!

    if button_state == true then

        // 💡 안전 작동을 위해 현재 흐르던 비디오 소스를 완전히 OFF (값 0 전송)

        play_cmd = 0

        SetData(play_cmd, "Local HMI", LW, 0, 1) 

        DELAY(150)

        

        // 시스템이 지정해준 LW 2번 방에 stream7 주소 글자 전체를 통째로 덮어쓰기! (64개 워드 데이터 전송)

        SetData(url_stream7[0], "Local HMI", LW, 2, 64)

        DELAY(150)

        

        // 새로운 야간 주소로 비디오 창 전격 가동 개시! (값 1 전송)

        play_cmd = 1

        SetData(play_cmd, "Local HMI", LW, 0, 1)

    end if



    // [조건 2] 버튼을 한 번 더 눌러서 OFF(false) 상태가 되었다면? ➡️ stream2(주간컬러) 주소 주입!

    if button_state == false then

        // 기존 비디오 소스 OFF

        play_cmd = 0

        SetData(play_cmd, "Local HMI", LW, 0, 1)

        DELAY(150)

        

        // 시스템이 지정해준 LW 2번 방에 stream2 주소 글자 전체를 통째로 덮어쓰기! (64개 워드 데이터 전송)

        SetData(url_stream2[0], "Local HMI", LW, 2, 64)

        DELAY(150)

        

        // 새로운 주간 주소로 비디오 창 전격 가동 개시! (값 1 전송)

        play_cmd = 1

        SetData(play_cmd, "Local HMI", LW, 0, 1)

    end if


    end macro_command

    2025년 12월 20일 토요일

    openpnp 세팅 참조

     pakage >> nozzle type install

    board install >> boards >> set the board x,y and rotation
                               perform a fiducial check for the board


    bottom camera position >> nozzle calibration adjusting position


    job board z position seting and x, y position set



    2025년 2월 3일 월요일

    구조체

     struct { // Communication structures

    bool rf; // Receive flag, indicating if data has been received uint8_t tb[50]; // Transmit buffer (stores data to be transmitted) uint8_t rb[50]; // Receive buffer (stores received data) uint8_t tc; // Transmit count (tracks the number of bytes to be sent) uint8_t rc; // Receive count (tracks the number of bytes received) uint8_t rt; // Receive timeout (20ms * 5 = 100ms, used for handling communication timeouts) uint8_t fn; // Field name (used for identifying communication fields) uint8_t hi, lo; // Used for Modbus communication (high and low byte storage) } cm0; //----------------------- hw_timer_t *timer1 = NULL; // 25ms Timer instance for periodic tasks struct { // Timer-related variables uint8_t fg; // Flag to indicate timer-related events byte tc; // Timer counter for general use byte t100ms; // Counter for 100ms intervals byte t500ms; // Counter for 500ms intervals byte sec; // Second counter } tim; //----------------------- struct { uint16_t reg[50]; // Array for storing data (e.g., sensor values, Modbus registers) } ccu;

    참고!!