[68호]스마트 쇼핑 카트
2021 ICT 융합 프로젝트 공모전 우수상
스마트 쇼핑 카트
글 | 영남대학교 양성은, 박유나, 이유진, 김형덕
1. 심사평
칩센 작품은 상품의 구매와 위치 측량의 두 가지 큰 목표로 보입니다. 우선 상품 취득과 결제 부분에 있어서는 목표량을 어느 정도 달성한 것으로 보입니다. 또 다른 목표였던 위치측량 관련하여 상품의 위치를 통한 navigating 기능을 구현하기 위하여 사용자의 위치를 측정해야 하는 구조로 이해됩니다. 작품을 개발하며 목표로 한 내역에 대하여는 어느정도 위치 측량을 성공하였다고 볼수도 있지만, 실제로 상용화에 있어서는 위치 측량에 대한 많은 변수들이 존재하여 실내의 Map이 함께 조합되어 정확한 실내 위치를 파악하게 하는 등의 다양한 방식의 알고리즘과 방안이 적용되고 있고, 이러한 부분에 대한 추가적인 연구 검토를 한다면 더욱 개선된 제품을 제작할 수 있을 것으로 보입니다.
펌테크 아이디어와 실용성이 돋보이며 짜임새 있게 잘 구성한 수준급 작품이라고 생각합니다. 실내 위치 측정을 위한 비컨 연동 과정에서의 시행착오가 있었음에도 불구하고 전체적으로 시스템 구성을 위한 각각의 난이도 있는 소프트웨어 구성을 효율적으로 접목하여 기획의도에 맞게 시스템을 안정적이고 완성도 높게 구현된 스마트카트 제품이라고 생각이 듭니다. 추후 작품 완성도를 높인다면 상업적으로도 충분히 활용될 수 있는 상품성을 가진 훌륭한 작품이 되리라 생각됩니다.
위드로봇 학습 용도로는 좋은 주제이지만, 실용적인 측면에서는 위치 측량, 결제 등 해결해야 할 문제가 많은 작품입니다.
뉴티씨 배려심이 느껴지는 작품입니다. 코로나19로 여러 가지로 어려운 상황에서, 같은 작품을 해도 어떤 마음으로 하는 가에 따라서, 의도가 다르므로 전혀 다른 결과가 나올 수 있습니다. 그런데, 몸을 움직이는 것이 불편하신 어르신들을 생각하여, 자동으로 계산이 되는 스마트쇼핑카트를 생각할 수 있었다는 것이 매우 중요한 가치라고 생각됩니다. 스마트 쇼핑카트라는 것은 오래전부터 인기 있는 작품의 주제로 만들어져왔지만, 이 작품은 비콘을 이용한 삼각측량법으로 위치인식까지 고려하여 제작하여 제품을 빠른 경로로 찾으러 갈 수 있도록 하는 부분도 함께 작성되었네요. 매우 좋은 작품을 제작하였습니다. 다양한 분야에서 활용될 수 있을 것 같고, 학생들이 좀 더 힘내서, 좋은 분야로의 응용을 기대하겠습니다.
2. 작품 개요
스마트 쇼핑 카트는 거동이 불편한 사람들에게 편리한 쇼핑 환경을 제공해 주기 위한 보조 장치이다. 이 프로젝트를 생각하게 된 계기는 마트에서 쇼핑을 하다가 물건이 많아 카트를 끌고 계셨지만, 몸이 불편하셔서 카트를 끌기조차 매우 어려워 보이는 분을 보고 ‘거동이 불편하신 분들도 대형마트에서 편하게 쇼핑을 할 수 있게 할 방법이 없을까?’ 라고 생각하다가 개발하게 됐다. 프로젝트의 구현으로는 대형 마트 내에서 실내 측위 시스템을 사용하여 구매하고자 하는 물건의 위치까지 최단 경로를 알려주어 효율적인 쇼핑을 가능하게 한다. 카트에 부착된 바코드 스캐너에 구매 물품의 바코드를 찍으면 데이터베이스 내에 존재하는 물품의 정보를 자동으로 관리할 수 있게 하고, 구매 상품의 행사 정보를 음성으로 알려준다. 결제 버튼을 누를 시, App에서 간단하게 결제할 수 있도록 한다. 현재의 전동 카트는 원하는 상품 코너로 이동하는 것 정도로 발전되어 있는데, 거기에 우리 팀의 프로젝트는 최단거리 알고리즘(Traveling Salesman’s Problem)을 적용하고, 결제 서비스까지 연동하여 사물 인터넷 개념을 적용해 현대에 어울리는 더욱 스마트한 카트로 발전시킨다.
2.1. 개발 목표
거동이 불편한 사람들의 오프라인 쇼핑을 도울 수 있는 카트를 개발하여, 기존 쇼핑 방식보다 쉽고(easy), 편리하고(convenient), 안전한(safe) 쇼핑을 제공하여 더 나은 소비 활동을 할 수 있도록 돕는다. 더 나아가 스마트 카트가 보급화 된다면 거동이 불편한 사람뿐만 아니라, 바쁜 현대인들에게도 최단 경로로 원하는 물품이 어디에 있는지 바로바로 알 수 있고, 결제까지 한 번에 해결하는 효율적인 쇼핑 수단이 될 것이다.
2.2. 개발 작품의 필요성
일반 사람들도 쇼핑을 할 때 원하는 물건이 어디 있는지 자주 구매하는 물품이 아니라면 알기 어려운데, 거동이 불편한 사람들이나 장시간 쇼핑이 어려운 노약자들은 그것으로 인해 불편한 몸을 이끌고 물건을 가지러 갔다가 헤매고 다시 계산하러 계산대까지 이동한다면, 일반 사람들보다 몇 배는 힘들고 제한될 것이다. 하지만 우리 프로젝트를 통해 이동 동선을 최소화하고, 시선이 닿지 않는 곳에 기재된 할인 정보를 음성으로 접할 수 있게 됨과 동시에 결제까지 스마트 카트 하나로 끝낼 수 있어서 보통 사람들처럼 불편함 없는 쇼핑이 가능하여 더 나은 쇼핑이 가능하게 한다.
2.3. 기대효과
· 거동이 불편한 사람들이 쇼핑에서 불편함을 느낄 수 있는 부분들을 지원하여 더욱 나은 쇼핑 생활을 가능케 한다.
· 스마트 쇼핑 카트가 여기에서 더 나아가 발전하고 보급된다면 일반 사람들도 기존의 쇼핑 방식 보다 더욱 효율적인 쇼핑 할 수 있다.
· 탈부착이 가능하도록 구성하여 유연성을 가지고 있으며, 효율적인 활용이 가능하다.
· 실내 위치 측위의 발전 가능성을 기대할 수 있다.
3. 작품 설명
3.1. 주요 동작 및 특징
3.1.1. 주요 기능 소개
전체적 구성은 라즈베리파이에 모니터와 바코드스캐너와 스피커가 연결되어있다. 이는 쇼핑 카트에 탈부착 할 수 있으며 또한 결제 어플과 연동된다.
기능 1(실내 측위): RF모듈의 RSSI 값으로 삼변측량법을 이용한다. Raspberry Pi가 3개의 RF모듈을 통해 얻은 RSSI 값으로 거리를 구하여 마트 내에서 구매자의 위치를 파악한다. 파악한 위치를 통해 구매자와 구매하고자 하는 상품코너와의 거리를 파악할 수 있다.
기능 2(최단 경로 안내): 삽변측량법과 같이 Traveling Salesman’s Problem을 이용하여 사용자가 물품 구매 시 최단 경로로 이동할 수 있도록 한다. 구매하고자 하는 상품들을 선택할 시, 실내 측위 기술을 통해 구매자의 위치를 기준으로 가장 짧고 빠르게 상품까지 도달할 수 있는 경로를 제공한다.
기능 3(장바구니 & 상품 Database 설명): 바코드 스캔을 통해 데이터베이스를 조회하여 상품의 행사 정보를 음성으로 알려주고 장바구니에 담긴 구매 물품들을 자동으로 관리할 수 있게 한다. 또 디스플레이로 장바구니 목록을 보여줌으로써 삭제 또는 추가 등의 자유로운 수정이 가능하다.
기능 4(결제기능): 카트에 부착된 모니터에서 결제버튼을 누르게 되면, 연동된 어플리케이션에서 결제가 가능하다.
3.1.2. RSSI 알고리즘 동작 및 특징
RF 비콘을 3개 생성하여 삼각측량법에 이용할 수 있도록 구성하였다. 비콘의 신호를 감지하기 위해 라즈베리파이를 오른쪽과 같이 비콘 수신기로 구성하였다. 비콘의 신호를 수신하여 rssi값으로 거리를 측정하고 현재의 위치를 추적할 수 있도록 한다.
Raspberry Pi가 RF Beacon에게 Data를 얻어와 TXpower와 RSSI값을 분리하여, RSSI에 따른 거리를 구한다. 3개의 비콘 모두 거리를 구해, 삼변측량법을 사용하여 목표위치를 파악할 수 있다.
비콘의 RSSI 값을 이용하여 직선거리를 구하는 공식을 이용하였습니다. 공식을 적용하기 위 TX Power 와 RSSI 값을 정제하여 거리 공식에 대입하였다.
3개 비콘의 각각의 좌표와 측정한 직선거리를 이용하여 삼변 측량법을 적용해 사용자의 현재 좌표를 출력하였다.
3.1.3. 최단 경로 안내 알고리즘 동작 및 특징
TSP(Traveling Salesperson Problem)을 이용하였다. TSP 알고리즘이란 원래 여러 도시들이 있을 때 한 도시로부터 시작해서 모든 도시를 단 한 번씩만 방문하여 다시 시작점으로 돌아오는데 드는 최단거리를 구하는 문제이다. 여기서 우리는 도시를 상품의 코너로 가정하였다. 입구에서 출발하여 각 선택된 코너들을 거치고 다시 입구로 돌아오는 식으로 최단경로 안내 문제를 해결하였다. 중간에 생각하지 못했던 필요한 물품이 생길 시 코너를 추가 선택한 후 안내를 누르면 다시 그 자리에서 시작하는 최단 경로를 시각화 하여 카트에 부착된 모니터로 안내해 준다. 전수 조사 방식으로 진행하여서 각 경로를 기억하기 위해 스택을 사용했다. 거리를 구하고 스택에서 각 경로의 거리 중 가장 짧은 경로를 선정하여 사용자에게 안내해 준다.
3.1.4. 장바구니 & 상품 Database 알고리즘 동작 및 특징
상품 Database: 먼저 MySql DB를 라즈베리파이에 설치한다. 명령어를 통해 데이터베이스를 생성한 후 데이터베이스 내에서 테이블을 생성한다. 테이블을 생성할 때에 바코드번호, 상품 이름, 상품 가격을 받아오도록 자료형을 지정해주고 테이블을 만들어준다.
장바구니 기능: while문을 통해 항시 입력을 대기하며, 바코드 스캐너로 물품의 바코드를 찍으면 Database Table에서 해당 물품의 정보를 가져와 목록에 저장을 한다. 생성해 놓은 데이터베이스를 파이썬과 연동하여 데이터베이스를 조회할 수 있도록 구성하였다.
연동 방법은 pymysql이라는 파이썬 라이브러리를 설치해주었다.
저장한 목록은 디스플레이에 출력하여 사용자가 구매할 물품이 장바구니에 담긴 것을 시각정인 정보로 제공한다. Pandas를 이용하여 시각화하였다. 아래의 사진을 보면 시각화된 모습을 볼 수 있다.
장바구니에 담긴 물품들 중, 구매하지 않을 물품을 삭제할 때 입력창에 1을 입력하면 delete mode로 바뀐다. 디스플레이에서 제공하는 상품의 목록을 통해 삭제할 물품의 인덱스 번호를 입력하면 쉽게 삭제가 가능하다.
행사 정보 안내 기능: 사용자에게 물품의 행사 정보를 쉽고, 간편하게 제공할 수 있는 방법에는 음성 안내 기능이 있다. 구매하려는 물품의 바코드를 스캔하면, 장바구니 목록에 담김과 동시에 해당 물품의 행사 정보를 음성으로 안내해준다. 음성 안내 기능은 TTS(Text to Sound)로 구현하였으며, 문자열로 넘겨주도록 했다.
3.1.5. 결제기능 동작 및 특징
Application과 Raspberry Pi간의 소켓통신으로 장바구니에 담긴 최종 금액을 APP으로 넘겨준다.(소스코드 [첨부 19] 참고) 통신 방식은 소켓통신을 이용하였다. 라즈베리파이가 클라이언트가 되도록 구성하고 App이 서버가 되도록 구성하였다. App에서 제공해주는 IP를 입력한 후 데이터를 전송하게 된다.
넘겨받은 데이터를 토대로 결제 기능을 제공하며, 해당 결제 기능은 안드로이드 스튜디오에 Bootpay SDK를 연동하여 결제 테스트를 할 수 있도록 구성하였다. 안드로이드용 Application ID를 Bootpay 관리자에서 가져와 연동하였다. 안드로이드 라이브러리는 내부적으로 WebView를 이용하여 구현되어 있다. Javascript SDK를 안드로이드 WebView에서 구현한 방식으로, 결제연동, 결제결과에 대한 라이프 사이클 함수가 제공된다. 따라서 안드로이드 레이아웃에 View를 줌으로써 결제 창을 띄우도록 구성하였다.
3.1.6 프로그램 사용법
처음 모드선택에서 0번을 선택할 시 경로안내 모드로 들어가게 된다.
화면에서 처음에 방문하고자 하는 코너를 선택할 수 있다. 코너를 다 선택하면 최단경로가 시각적 정보로 사용자에게 안내된다.
안내 후 다시 모드선택으로 되돌아온다. 여기서 1번을 선택하게 되면 장바구니 모드로 들어가게 된다. 장바구니 모드에서 바코드 스캔을 통해 장바구니를 추가할지 구성된 장바구니 목록을 삭제할지 결제 할지를 선택할 수 있다.
먼저, 바코드를 스캔하면 TTS(Text to Speech)로 상품의 행사정보를 사용자에게 음성안내를 해준다. 모니터에는 상품이 추가된 장바구니 목록을 볼 수 있다.
다른 상품의 바코드를 찍으면, 장바구니 목록에 새로운 상품이 추가된 것을 볼 수 있다.
같은 상품을 여러 번 찍으면 목록이 새로 추가되는 것이 아니라 해당 상품의 수량만 늘어나는 것을 볼 수 있다.
바코드 스캔 대신 1을 2번 입력하면 삭제 모드로 들어간다. 현재까지 구성된 장바구니 목록을 보여주며 삭제하고자 하는 목록의 인덱스를 입력하면 삭제가 된다. 다음 사진을 보면 삭제가 되는 것을 확인할 수 있다.
마찬가지로 바코드 스캔 대신 2를 2번 입력하면 결제 모드로 들어가게 된다. 앱에서 제공하는 IP정보를 입력하면 결제정보를 App으로 전송하며 결제 가능하다. 다음 사진을 보면 결제가 청구된 것을 확인할 수 있다.
3.1.7 전체 알고리즘 동작 및 특징
3.2. 전체 시스템 구성
3.2.1 하드웨어 구성
· Raspberry Pi
· Barcode scanner
· Speaker
· Monitor
3.2.2 소프트웨어 구성
· MySQL Database
· TSP algorithm source
· 삼변측량 algorithm source
· TTS source
3.2.3 주요 동작 및 특징
· Barcode scan을 통한 상품, 장바구니 database 구성
· Barcode scan을 통한 행사 정보 음성 안내 기능 TTS 구현
· 삼변측량법을 통한 실내 위치 측위
· TSP algorithm을 통한 최단경로 추적
3.3. 개발 환경
4. 단계별 제작 과정
4.1. Hardware
Raspberry PI에 보조배터리, 모니터, 스피커, 바코드 스캐너가 연결하였다. 전동 카트(장바구니)에 Raspberry Pi와 함께 전력을 공급해주는 보조배터리, 경로안내와 장바구니 목록을 시각화해줄 모니터, 해당 상품의 행사 정보를 음성으로 출력해줄 스피커를 부착한다. 또한, 바코드 스캐너를 쇼핑카트에 부착하였고, 스캔 시 UART 통신을 통해 라즈베리로 바코드 정보를 넘겨 상품을 장바구니 목록에 담을 수 있도록 한다. 담긴 상품의 목록은 모니터로 사용자에게 시각화 해줌으로써 사용자가 장바구니를 직접 보며 관리할 수 있도록 한다.
탈부착식 모듈
탈부착 식 모듈로 전동 카트뿐만 아니라 일반 카트에도 부착할 수 있다. 탈부착 식이므로 전동 카트의 개수가 아닌 한 매장에 필요한 개수만 구비해도 됨으로 가격적 부담도 줄어들도록 했다.
실내 측위를 위한 Bluetooth Beacon
위치 추적을 위해 최소 3개의 블루투스 비콘을 마트에 설치함으로써 실내에서의 실제 위치를 추적 가능하다. 각각의 비콘마다 코인건전지 CR2032 3V 2개로 전원공급을 한다. 하지만, 1m 밖의 거리에서 정확도가 떨어지는 RSSI값을 확인할 수 있었다. 짧은 통신 거리의 한계로 Beacon을 이용할 때 1m 내의 범위에서 시연을 진행하였다.
실내 측위를 위한 RF 통신
앞서 언급한 Buletooth Beacon의 짧은 통신 거리의 한계를 대체할 RF 통신을 구현하였다. RF통신은 통신 거리가 100m까지도 가능하기 때문에, 해당 문제점을 보완할 수 있다.
다음과 같이 Beacon을 세 곳으로 설치하여 RF통신 시연을 진행하였다.
시현 위치에서 1분 동안 측정한 데이터의 그래프이다. 그래프를 보면 RSSI값의 변화에서 값이 비교적 일정하게 나오는 것을 볼 수 있어 그 전의 블루투스 Beacon보다는 거리 측면에서나 정확도 측면에서나 뛰어난 성능을 보여주고 있다.
4.2 Software (Raspberry PI, Application)
4.2.1. 라즈베리파이
바코드 스캔 및 행사 정보 안내
상품을 장바구니에 담는 방법은 간단하다. 카트에 부착된 바코드 스캐너로 상품의 바코드를 스캔하면 장바구니에 담긴 것을 모니터로 확인이 가능하다. 같은 상품의 바코드를 여러 번 스캔 할 시 같은 목록이 여러 개 생기는 것이 아니라 같은 상품의 수량만 늘어나게 하였다. 모니터를 통해 장바구니 목록의 삭제, 수정을 제공한다. 또한 행사 중인 물품은 카트에 부착된 바코드 스캐너를 통해 바코드를 찍을 때 TTS(Text to Speech)로 상품의 이벤트 정보를 읽어준다. 해당 바코드에 찍힌 번호는 자료형을 int로 성언하면 오버로드가 되기 때문에 VARCHAR 형으로 자료형을 바꾸어 해결할 수 있다.
최단 경로
해당 매장의 코너의 데이터들은 모두 저장이 되어있다는 가정하에 진행이 된다. 사용자가 방문하고자 하는 코너를 모니터상으로 선택할 시, TSP (Traveling Salesperson Problem) 알고리즘을 이용한다. 실내 측위 정보로 현재 위치로부터 최단거리를 계산하게 된다. 최단의 이동경로를 모니터를 통해 사용자에게 안내해준다.
실내 측위
실내 측위 기능: 사용자에게 현재 어느 위치에 있는지 실시간으로 사용자에게 알려주고 최단 경로 안내에도 쓰인다. 건물에 설치되어 있는 비콘의 신호를 수신하여 삼각측량법을 통해 현재 위치를 계산한다.
장바구니
상품 정보의 관리는 MySQL DB를 이용하여 물품의 Database를 구축하여 상품정보를 등록해 놓았다. MySQL에서 기존에 만들어놓은 table을 삭제하지 않고 같은 이름으로 다시 생성하면 오류가 발생하기 때문에 기존 table을 삭제하고 다시 생성해야한다. Python과 연동하여 바코드 번호로 조회 할 수 있게 구성하였고, 카트에 연결된 모니터에 결제 버튼을 누르면 연동된 App(부트페이)으로 결제정보를 보냄으로써 결제 할 수 있게 하였다.
App은 원래의 마트나 (홈플러스, 이마트 등) 대형마트에서 제공하는 App으로 결제 정보를 보낸다고 가정했지만 실제 App을 수정할 수 없어 결제기능만 있는 어플을 따로 구현하였다.
상품목록 추가 : 상품의 바코드를 스캔할 시, 모니터 상으로 상품이 추가 된 것을 확인할 수 있다.
상품목록 삭제 : 필요하지 않은 상품은 삭제 모드로 들어가 해당 상품의 인덱스를 지정해 삭제할 수 있다.
GUI
경로 안내 모드에서 기존에 제시한 디스플레이는 텍스트 형식으로만 구성이 되어있었다. 이를 가독성있게 만들기 위해서 Python에서 사용하는 GUI를 이용해 시각화시켰다. 왼쪽의 메인 화면을 통해 모드를 선택할 수 있으며 경로와 장바구니 모드가 있다. 경로안내모드에서는 사용자가 원하는 코너를 선택하고 OK 버튼을 누를 수 있으며 취소하고 싶은 코너가 있다면 다시 한 번 누르고 OK 버튼을 누르면 된다.
장바구니 모드에서는 바코드 스캔이 주를 이룬다. 바코드로 상품을 스캔할 때마다 목록에 상품들이 쌓여간다. 삭제 기능도 제공하여 Check를 눌러 목록에서 삭제를 누를 수 있다.
마지막으로, 결제 버튼을 누르게 되면 사용자의 어플과 통신으로 해당 상품의 가격을 전송하게 된다.
4.2.2 어플리케이션
안드로이드 스튜디오와 부트페이 SDK를 연동하여 가상 결제 기능을 제공한다. 인앱 결제 방식은 구현 시, 유로 모듈 결제가 필요하기 때문에 무료로 제공하는 Bootpay 방식을 사용하였다. Bootpay 사이트에서 결제 연동 시, 필요한 ID를 받아올 때 WEB Application ID로 잘못 받아와 실패하였다. Android Application ID를 제대로 받아와서 연동 문제를 해결할 수 있다. 또한 Android Studio Build.gradle(app)에서 compileSdkVersion은 30으로 설정하고, targetSdkVersion은 27로 설정하여 오류가 발생하였다. targetSdkVersion30으로 수정할 시, 정상 동작하는 것을 확인할 수 있다.
4.3 주요 소스 코드 설명
#module Declaration
import blescan
import pymysql
import pandas as pd
from pandas import DataFrame as df
import os
import math
import socket
import sys
import bluetooth._bluetooth as bluez
from numpy import median
#Beacon Address
beacon1=”e1c56db5dffb48d2b060d0f5a71096e0″
beacon2=”e2c56db5dffb48d2b060d0f5a71096e0″
beacon3=”e3c56db5dffb48d2b060d0f5a71096e0″
dev_id=0
count=0
#Beacon Position Setting
position1=[45,90,0]
position2=[0,0,0]
position3=[90,0,0]
#Use queue
def push(element):
global top
top=top+1
stack[top]=element
def pop():
global top
ret=stack[top]
top=top-1
return ret
def show():
global top
global mincorner
global mincorv
for i in range(0,top+1):
mincorv +=” ->”+stack[i][0]
def getDistance(a,b):
return math.sqrt((a[1]-b[1])*(a[1]-b[1])+(a[2]-b[2])*(a[2]-b[2]))
#Traveling Salesperson Problem
def TSP(start, corner, number, sumv, now):
global minv
global totalCount
global mincorner
global mincorv
count=0
visited[start]=1
for i in range(0,number):
if visited[i]== 0:
count=count+1
visited[i]=1
push(corner[i])
TSP(start,corner, number,sumv+getDistance(corner[now], corner[i]),i)
visited[i]=0
pop()
if count == 0:
mincorv=mincorv+”->”+corner[start][0]
sumv=sumv+getDistance(corner[now], corner[start])
show()
mincorv+=”\nDistance: “+ str(sumv)
mincorner.append(mincorv)
mincorv=”"
if minv>sumv:
minv=sumv
totalCount=totalCount+1
def getTrilateration(position1, position2, position3): #Get Beacon Position
x1=position1[0]
y1=position1[1]
r1=position1[2]
x2=position2[0]
y2=position2[1]
r2=position2[2]
x3=position3[0]
y3=position3[1]
r3=position3[2]
S=(math.pow(x3,2.0)-math.pow(x2,2.0)+math.pow(y3,2.0)-math.pow(y2,2.0)+math.pow(r2,2.0)-math.pow(r3,2.0))/2.0
T=(math.pow(x1,2.0)-math.pow(x2,2.0)+math.pow(y1,2.0)-math.pow(y2,2.0)+math.pow(r2,2.0)-math.pow(r1,2.0))/2.0
y=((T*(x2-x3))-(S*(x2-x1)))/(((y1-y2)*(x2-x3))-((y3-y2)*(x2-x1)))
x=((y*(y1-y2))-T)/(x2-x1)
return x,y
#Initialization DataBase
stack=[0 for i in range(5)]
top = -1
#Setting corner position
corner=[("Enter", 75.1, 53.3),
("Dressed meat", 0.0, 5.1), ("Vegetable", 0.0, 10.2), ("Seafood", 0.0, 15.3), ("Fruit", 15.7, 19.1),
("Toy", 5.0, 5.5), ("Beverage", 5.0, 10.6), ("Home appliance", 28.7, 41.8), ("Kitchenware", 5.0, 20.8),
("Bathroom", 10.0, 5.9), ("Snack", 10.0, 10.0), ("Instant noodles", 40.9, 38.3), ("Egg", 10.0, 20.2),
("Diary products", 44.6, 24.6), ("Frozen food", 52.2, 59.6), ("Clothing", 15.0, 15.5), ("Shoes", 15.0, 20.6),
("Tool", 20.0, 5.7), ("Electronics", 20.0, 10.8), ("Pet goods", 20.0, 15.9), ("Beer", 20.0, 20.0)]
mincorner=[]
mincorv=”"
visited=[0 for i in range(5)]
minv=2147483647.0
totalCount=0
try:
sock = bluez.hci_open_dev(dev_id)
print “ble thread started”
except:
print “error accessing bluetooth device…”
blescan.hci_le_set_scan_parameters(sock)
blescan.hci_enable_le_scan(sock)
conn = pymysql.connect(host=’localhost’, user=’yang’, passwd=’1′, db=’goods’,charset=’utf8mb4′)
cur = conn.cursor()
DT = df({‘Goods List’: [],’Number of’:[]});
pd.options.display.float_format=’{:,.0f}’.format
#Initialization Socket
PORT=8888
s=socket.socket(socket.AF_INET, socket.SOCK_STREAM)
distance_avg=[]
while True:
returnedList = blescan.parse_events(sock, 10)
print “Select the Mode(0:Short Path, 1:Scan barcode, Exit is any Number): “,
mode=int(input())
if mode==0:
#print corner number
print “1.Dressed meat 2.Vegetable 3.Seafood 4.Fruit”
print “5.Toy 6.Beverage 7.Home appliances 8.Kitchenware”
print “9.Bathroom 10.Snack 11.Instant noodles 12.Dairy product”
print “13.Egg 14.Frozen food 15.Clothing 16.Shoes”
print “17.Tool 18.Electronics 19.Pet goods 20.Beer”
print “\nSelec the Corner: “,
num=(input()).split()
flag=[0 for i in range(21)]
vis=[0 for i in range(len(num))]
#print corner map
print “=========”
for j in range(0,len(num)):
flag[int(num[j])]=1
vis[j]=corner[int(num[j])]
for i in range(1,21):
if flag[i] == 1:
print corner[i][0],
for j in range(0,16-len(corner[i][0])):
print ” “,
else:
print ” “,
if i%4==0 and i!=0:
print “\n”
print ” “,
print corner[0][0]
print “========\n”
for beacon in returnedList:
if beacon[18:18+len(beacon3)]==beacon1:
distance_avg.insert(count,(10**((float(beacon[61:64])-(float(beacon[65:])))/20.0))*100)
count=count+1
if count == 10:
if median(distance_avg)<1:
position1[2]=median(distance_avg)
count=0
del distance_avg[:]
if beacon[18:18+len(beacon3)]==beacon2:
distance_avg.insert(count,(10**((float(beacon[61:64])-(float(beacon[65:])))/20.0))*100)
count=count+1
if count == 10:
if median(distance_avg)<1:
position2[2]=median(distance_avg)
count=0
del distance_avg[:]
if beacon[18:18+len(beacon3)]==beacon3:
distance_avg.insert(count,(10**((float(beacon[61:64])-(float(beacon[65:])))/20.0))*100)
count=count+1
if count == 10:
if median(distance_avg)<1:
position3[2]=median(distance_avg)
count=0
del distance_avg[:]
if beacon[18:18+len(beacon3)]==beacon3 and beacon[18:18+len(beacon3)]==beacon2 and beacon[18:18+len(beacon3)]==beacon1:
X,Y=getTrilateration(position1,position2,position3)
#find current location
for i in range(0,21):
if abs(X-coner[i][1])<1 and abs(Y-coner[i][2])<1:
myplace=i
#print short path
TSP(i,vis,len(vis),0,0)
print “Total Path Num: “,totalCount
for i in range(0,len(mincorner)):
if mincorner[i].find(str(minv)) != -1:
n=i
print “Shortest Path: “,mincorner[n]
print “\n”
mincorner=["" for i in range(len(mincorner))]
minv=2147483647
elif mode==1:
while True:
print “Scan barcode(1:Delete, 2:Pay): “,
goods_cnt=1
scan_in,n=[input() for _ in range (2)]
scan_in.strip(‘\n\n’)
if scan_in is ‘q’:
break
elif scan_in is ’1′:
print “=======
print(DT)
num=int(input(“delete (-1:return):”))
#while(num==)
if num== -1:
continue
else:
DT.drop(num,inplace=True)
DT.reset_index(inplace=True)
DT.drop(‘index’, axis=1,inplace=True)
print(“{0} delete”.format(num))
print(DT)
elif scan_in is ’2′:
A=[0 for i in range(len(DT))]
sumf=0
ip=input(“Input IP of App: “)
s.connect((ip,PORT)) #Connect App
for i in range(0,len(DT)):
A[i]=str(DT.iloc[i]).split(‘,’)
B=A[i][3].split(‘Number of’) #The number of product
C=(B[1].replace(” “,”")) #The price of product
sumf+=int(A[i][2])*int(C[0])
sumf=str(sumf)
s.send(sumf.encode(‘utf-8′)) #Total price
s.close()
break
else:
sql=”SELECT * FROM list WHERE barcode LIKE %s”
cur.execute(sql,scan_in)
for row in cur:
cp=str(row)
empty=str(DT[DT['Goods List'].isin([cp])])
if (empty.find(“Empty”) is not 0):
i=DT[DT['Goods List'].isin([cp])].index
num=DT[DT['Goods List']==cp]['Number of'].tolist()
num=DT.loc[i,['Number of']]=(num[0]+1)
else:
new_data={‘Goods List’:cp, ‘Number of’:goods_cnt}
DT=DT.append(new_data, ignore_index=True)
text=str(new_data).split(‘,’)
text=text[3].replace(‘)”‘,”")
os.system(‘echo Event is %s | festival –tts’ %text)
print(DT)
else:
break
cur.close()
conn.close()
5. 사용한 제품목록
제품명 | 디바 상품번호 |
블루이노2 키트보드 (BI-200(K)) | 1287076 |
microSD Cards – TS16GUSDC10M [16GB] | 12139535 |
[RASPBERRY-PI] 라즈베리파이 3 Model B+ | 1377518 |
[(주)블루이노] 블루이노2 (Blueinno) 다운로드 툴 | 1272986 |
아두이노 라즈베리파이 바코드 스캐너 모듈 V3.0 USB to UART 인터페이싱 지원 |
- |
스피커 | - |
RF 모듈 | - |
6. 기타
6.1 기능블록도
6.2 목표 달성 현황
장바구니
목표: 바코드 스캔을 통해 장바구니 목록에 넣을 수 있고, 삭제와 추가의 기능도 구현
달성: 바코드 스캔을 통한 물품 목록 추가와 삭제를 할 수 있음.
최단거리
목표: 실내 측위 정보로 현재 위치로부터 최단거리 계산
달성: 현재 위치로부터 최단거리를 계산할 수 있음.
위치측량
목표: 현재 위치를 작은 오차로 받아오도록 구현
달성: 블루투스 비콘에서 RF 비콘으로 변경하여 측정 반경 거리를 넓혀 사용성을 확대함. 약간의 오차는 개선방법을 추후 적용할 예정.
인터페이스
목표: 작성한 GUI틀과 프로그램 연동
달성: 코너의 위치 정보와 최단경로, 상품목록 등을 볼 수 있도록 구현하였음, 사용자 친화적인 인터페이스 화면 디자인 완성. 추후 프로그램과 GUI를 연동할 예정.
결제 앱
목표: 장바구니 목록에 있는 상품을 앱으로 결제 가능하도록 구현
달성: 장바구니 목록을 구성할 수 있고 결제가 가능함.
6.3 시연영상 주소
6.4 참고문헌
· https://gongdae58.tistory.com/73
· https://ko.wikipedia.org/wiki/%EC%82%BC%EB%B3%80%EC%B8%A1%EB%9F%89
· https://codeanalysis.tistory.com/2
· https://m.blog.naver.com/wlsdml1103/221159758141
· https://m.blog.naver.com/PostView.nhn?blogId=dsz08082&logNo=221852345347&proxyReferer=https:%2F%2Fwww.google.com%2F
· http://pythonstudy.xyz/python/article/408-pandas-%EB%8D%B0 %EC%9D%B4%ED%83%80-%EB%B6%84%EC%84%9D