HSM을 활용한 레고 장난감 만들기

기억하기 위해서 기록해 놓음..

처음 다이어그램인데..수정.
12113378_1289445931071053_7620380557359358782_o

수정 다이어그램은 아래와 같다.
20160908_225320

기존 대비 S11을 지워 버렸다. S10에서 S11로 transiton이 발생할 때, 모터 동작이 끝나기 때문에 굳이 S11을 만들 필요가 없다. self transition으로 처리했다. state machine을 내가 제대로 이해하고 있는지 모르겠으나..

S13에서도 self transition을 추가 했는데, 회전 동작시 장애물을 완전하게 피했는지를 확인하기 위해서이다. S13에서 이벤트를 다시 한번 확인하고, 장애물에 걸리면 전진동작 없이 회피 동작을 하도록 했다.

가장 고민했던 부분은 S0은 event driven program이고 S1은 data driven program 방식으로 접근해야 할 것 같은데, 모든 ir센서로 읽어 들이는 모든 데이터를 event로 분류하기가 힘들었다. 이벤트로 설정하려면 배타적 관계도 확인해 봐야 하는데, 버튼 눌림여부 * 버퍼의 수치별 이벤트를 한개의 event로 처리하려면 경우의 수가 너무 많았다. 쿨하게 evnet는 아래와 같이 몇가지 경우만 잡았다. 나머지는 S1에 들어갔으므로 대략 무시하기로 했다.

package hsm;

import lejos.hardware.Button;

public class Event {
	  
	  public enum mEvent {EnterPressed,DownPressed,GapIsWide,GapIsNarrow,Nothing};
	  
	  //Ir센서를 읽기 위한 부분..
	  private float irValue;
	  
	  public Event(float tmp){
		  this.irValue = tmp;
	  }
	 /* 
	  public void setEventBuffer(float value){
		  this.irValue = value;
	  }
	  */
	  
	  public mEvent getID(){
		  
		  mEvent thisEvent = mEvent.Nothing;
		  
		  //버퍼에서 데이터를 읽어 들임 

		  if(Button.ENTER.isDown() == true)
			  return mEvent.EnterPressed;

		  if(Button.DOWN.isDown() == true)
			  return mEvent.DownPressed;
		  
		  if(irValue > 10)
		  	return mEvent.GapIsWide;
		  
		  if(irValue <= 10)
			  return mEvent.GapIsNarrow;
		 		  
		  return thisEvent;
	  }
	  
	  


}

일단 S1에 들어가면, irRead -> ir 버퍼 가공 -> 모터 동작의 방식으로 처리했는데, 이 방법도 좋지 않았다. 각 state별 process가 다른데, thread로 돌리면 이를 구분할 수 없게 된다. 따라서 아래와 같이 수정했다.

S10,S13에서만 irRead 동작, S10,S12,S13에서는 모터 동작, 각 transition에 따른 버퍼값 수정..

S0에서는 버튼이 눌림만 감시하기 때문에 event driven programming으로 접근했다.

hsm의 c++ -> java 이식은 인터넷의 코드를 그대로 사용했다.
hsm의 구조는 대략 아래와 같다.

package hsm;

import mypackage.IrBufferv2;
import mypackage.MotorData;

public class myHsmForLego extends Hsm{
	private MotorData mMotorData;
	
	Runnable myIrRun;
	Runnable myMotorRun;
	Runnable myProcessRun;

	


	public myHsmForLego(MotorData motor,Runnable irTh, Runnable motorTh, Runnable ProcessTh){
		this.mMotorData = motor;
		
		//thread를 전달하기 위한 부분
		this.myIrRun = irTh; 
		this.myMotorRun = motorTh;
		this.myProcessRun = ProcessTh;

	}
	
	@Override
	public void init() {
		// TODO Auto-generated method stub
		System.out.print("Top-INIT;" );
	    
	    //초기화시 모터 목표를 0으로 설정
		super.init();
	}

	@Override
	public State fireInit() {
		// TODO Auto-generated method stub
	    System.out.print("INIT>>s;" );
		return s0;
	}

	@Override
	public void enter() {
		// TODO Auto-generated method stub
	    System.out.print("ENTRY>>s;" );

	}
	
	@Override
	public State fireEvent(Event e) {
		// TODO Auto-generated method stub
		return getParent();
	}//fireEvent

	@Override
	public void exit() {
		// TODO Auto-generated method stub
	    System.out.print("EXIT<<s;" );
	    System.out.print("\n");


	}
	
	Hsm s = this;                 // This is just alias of current instance

	
	
	State s0 = new State(s){
		@Override
		public State fireEvent(Event e) {
			// TODO Auto-generated method stub
			switch(e.getID())
			{
				case EnterPressed :
					transition(s1);
					return null;

				default :
					  break;
			}
			
			return getParent();
		}//fireEvent
		
		@Override
		public State fireInit() {
			// TODO Auto-generated method stub
		    System.out.print("INIT>>s0;" );
			return null;
		}

		@Override
		public void enter() {
			// TODO Auto-generated method stub
		    System.out.print("ENTRY>>s0;" );
			
		}

		@Override
		public void exit() {
			// TODO Auto-generated method stub
		    System.out.print("EXIT<<s0;" );
		    System.out.print("\n");
		
		}
		
	};//sate s0
	
	State s1 = new State(s){

		@Override
		public State fireInit() {
			// TODO Auto-generated method stub
		    System.out.print("INIT>>s1;" );
			return s10;
		}

		@Override
		public void enter() {
			// TODO Auto-generated method stub
		    System.out.print("ENTRY>>s1;" );
	
		}

		@Override
		public State fireEvent(Event e) {
			// TODO Auto-generated method stub
			switch(e.getID())
				{
					case DownPressed :
						transition(s0);
						return null;

					default :
						  break;
				}
			return null;
		}

		@Override
		public void exit() {
			// TODO Auto-generated method stub
		    System.out.print("EXIT<<s1;" );
		    System.out.print("\n");
				
		}
		
	};//state s1;
	
	

	State s10 = new State(s1){

		@Override
		public State fireInit() {
			// TODO Auto-generated method stub
		    System.out.print("INIT>>s10;" );
			return null;
		}

		@Override
		public void enter() {
			// TODO Auto-generated method stub
			// IR 센서값을 버퍼에 저장..
			// 이벤트를 판단할 수 있게됨..
			myIrRun.run();
		    System.out.print("ENTRY>>s10;" );
	
		}

		@Override
		public State fireEvent(Event e) {
		
			// TODO Auto-generated method stub
			switch(e.getID())
			{
			case GapIsWide :
				//모터 이동부분 추가.
				// 아래 process run은 삭제필요..
				// thread를 인수로 줄수 없음..
				//myProcessRun.run();
				mMotorData.storeTargetDistance(10, 10);
				myMotorRun.run();
				
				//seft transition
				transition(s10);
				return null;

			case GapIsNarrow :
				mMotorData.storeTargetDistance(-50, -50);
				myMotorRun.run();

				transition(s12);
				return null;

			default :
				break;
			
			}
			return getParent();
		}//fireEvent

		
		@Override
		public void exit() {
			// TODO Auto-generated method stub
		    System.out.print("EXIT<<s10;" );
			System.out.print("\n");

		}
			
	};//state s10

	
	/* 아래 부분은 삭제..2016.09.08
	State s11 = new State(s1){

		@Override
		public State fireInit() {
			// TODO Auto-generated method stub
		    System.out.print("INIT>>s11;" );
			return null;
		}

		@Override
		public void enter() {
			// TODO Auto-generated method stub
		    System.out.print("ENTRY>>s11;" );
			
		}

		@Override
		public State fireEvent(Event e) {
			// TODO Auto-generated method stub
			switch(e.getID())
			{
			case GapIsWide:
				//seft transition
				//모터 이동부분 추가.
				myIrRun.run();
				myProcessRun.run();
				myMotorRun.run();
				transition(s11);
				//모터 이동부분 추가.
				return null;

			case GapIsNarrow:
				//모터 이동부분 추가.
				mMotorData.storeTargetDistance(-10, -10);
				myMotorRun.run();

				transition(s12);
				return null;

			default :
				break;
			
			}
			
			return getParent();
		}//fireEvent

		@Override
		public void exit() {
			// TODO Auto-generated method stub
			System.out.print("EXIT<<s11;" );
			System.out.print("\n");
		}
			
	};//State s11
	*/
	
	State s12 = new State(s1){

		@Override
		public State fireInit() {
			// TODO Auto-generated method stub
		    System.out.print("INIT>>s12;" );

			return null;
		}

		@Override
		public void enter() {
			// TODO Auto-generated method stub
		    System.out.print("ENTRY>>s12;" );
		}

		@Override
		public State fireEvent(Event e) {
			// TODO Auto-generated method stub
			//모터 이동부분 추가.
			mMotorData.storeTargetDistance(50, -50);
			myMotorRun.run();

			transition(s13);
			return getParent();

		}//fireEvent

		@Override
		public void exit() {
			// TODO Auto-generated method stub
			System.out.print("EXIT<<s12;" );
			System.out.print("\n");

		}
		
		
	};//State s12

	State s13 = new State(s1){

		@Override
		public State fireInit() {
			// TODO Auto-generated method stub
			System.out.print("INIT>>s13;" );

			return null;
		}

		@Override
		public void enter() {
			// TODO Auto-generated method stub
			// 충분하게 돌았는지 확인.
			myIrRun.run();
			System.out.print("ENTRY>>s13;" );

			
		}

		@Override
		public State fireEvent(Event e) {
			// TODO Auto-generated method stub
			switch(e.getID())
				{
					case GapIsWide :
						//모터 이동부분 추가.
						// 아래 process run은 삭제필요..
						// thread를 인수로 줄수 없음..
						//myProcessRun.run();
						transition(s10);
						return null;

					case GapIsNarrow :
						//충분하게 돌지 못해더 더 돌아야 된단고 판단.
						mMotorData.storeTargetDistance(50, -50);
						myMotorRun.run();
						transition(s10);
						return null;

					default :
						break;

			}
			return getParent();
		}//fireEvent

		@Override
		public void exit() {
			// TODO Auto-generated method stub
			System.out.print("EXIT<<s13;" );
			System.out.print("\n");

			
		}

		
	};//State 13


		
}//myHsmForLego

다음에는 iR센서에 모터를 달아서 한바퀴 돌려보고 몇도로 움직여야 판단까지 하고 싶으나, 갈길이 멀어 보인다. 일단 이걸 다 뜯을 생각을 하니 머리가 아프다..한번 뜯으면 다시 조립 못할 것 같다..
20160908_232920

mysql을 사용한 견적 산출 방법

필요 조건..
1. 최소 아이템을 입력으로
2. 업데이트는 빈번하게..
3. 한번 입력한 아이템은 다른 곳에서 사용할 수 있도록..

임시 테이블을 만들어서, (각 경우에 따른, 주제어반/보조제어반+메이커 조합)
어느 아이템이 들어갈지 정함..
이 임시 테이블에 수량에 대한 항목이 정해져 있어야 됨..

모든 테이블에서 해당하는 아이템을 뽑아내면, 사용 가능할 것 같음..

select * from `cost`;

create temporary table `주제어반_ABPLC` (`ItemID` int, `수량` int);


#제어반을 구성하기 위한 ID/수량 매핑

insert into `주제어반_ABPLC` values (7,1),(13,5),(17,1),(20,3);

select * from `주제어반_ABPLC`;

drop temporary table `주제어반_ABPLC`;


#각 항목에서 해당하는 ITEM, 수량을 산출하기 위한 식..

select '주제어반',`cost`.`모델명`, `cost`.`세부사양`,`cost`.`제작사`,`주제어반_ABPLC`.`수량`,`cost`.`개당가격` from `cost`
 inner join `주제어반_ABPLC` on `cost`.`ItemID`=`주제어반_ABPLC`.`ItemID`;

단점은 만들 임시 테이블이 너무 많음..

Gen8 Microserver cpu 업그레이드 완료

멕시코에 있을때, 주문해 놓은 cpu를 오늘 장착했다. 주문후, 일주일이면 판매자에게 금액이 자동으로 지급되었다. 오늘 이 cpu가 안되었다면 돈 날렸을 것이다.

전에 스크랩해 놓은 사이트를 방문해서 그대로 따라했다. 그 문서에는 cpu 교체에 대한 내용이 별로 없었다. 메인보드를 빼고, 펌웨어 업데이트 등, 총 약 두시간정도 걸렸다.
보드 거의 부실뻔했다!!1

1. bios, ilo를 최신 버전으로 업데이트..ok
bios 업데이트를 usb로 하는줄 알았는데, 이럴수가.. hp에서 iLO라고 서버를 점검할 수 있는 통로가 있다. 웹브라우저로 연결하면 이것저것 다 할수 있는데, 여기에 bios, iLO의 펌웨어 업데이트가 가능하다. 와~~ 이걸 모르고 bios를 usb 저장장치에 옮겨 부팅을 하려 했다..모니터 연결하고. 키보드 연결하고..–;

2. 메인보드를 케이스에서 뺀다.
망할. CPU는 보드 중앙에 조립되어 있어, 보드를 빼지 않고는 분리할 수 없다. 보드를 밖으로 빼야 되는데, 여러 케이블들이 걸려있다. 직관적으로 어떻게 빼는지 알수있는 케이블과 그렇지 않은 케이블이 있다. 특히4 f-io라고 적혀있는 케이블..양쪽에는 핀이 아니라

CPU를 빼려면 메인보드?를 케이스에서 빼내야 되는데, 안에 케이블들이 걸린 부분이 있다. 그걸 다 떼내어야 되는데, 잘 안빠진다. 무슨 케이블인지도 모르겠고..대충 빠지는데, F-IO인가로 표시된 케이블이 있다. 양쪽 끝이 핀이라서 살살했는데,그게 아니다. 양쪽끝에 힘을 줘야 빠진다. 부서질까봐 한참 고민했다.

3. CPU 교체
거대한 방열판이 있는데, 그 안에 CPU가 있다. 방열판은 볼트 4개를 풀러 뺀다. 뽑기 좋아보이는 나사가 있길래, 살살 돌려주었더니, 딱 소리와 함께 CPU 고정하는 장치가 분리되었다!!! 나사산이 안나간게 다행이지. thermal grease를 발라주고, CPU를 고정한다. 레버를 누른다음에 아까 볼트를 끼는줄 알았으나, 아니다. 볼트를 고정후 레버를 두번 누르면 고정장치가 볼트 안쪽으로 들어가게 되어있다. 구입한 CPU는 벌크라고 팔았는데, 아마 중고를 판듯 하다. 안에 써멀 그리즈 자국이 남아있었다.

4. 조립..
역순으로 조립하면 된다…

5. 와!!!엄청 빠르다?? plex mediaserver를 돌려보니, 역시 빠름이 느껴진다..다만 전기료가 얼마나 나올지 걱정이다.cpu_screen

워드프레스 플러그인 업데이트 및 권한설정

플러그인 업데이트를 위해서는 워드 프레스의 권한을 바꿔줘야 한다.

셋업시 사용자/그룹을 웹서비스 유저로 설정하고…

chown www-data:www-data  -R * # Let Apache be owner
find . -type d -exec chmod 755 {} \;  # Change directory permissions rwxr-xr-x
find . -type f -exec chmod 644 {} \;  # Change file permissions rw-r--r--

설정이 완료되면, 보안을 이유로..아래와 같이 설정한다..

chown <username>:<username>  -R * # Let your useraccount be owner
chown www-data:www-data -R wp-content/ # Let apache be owner of wp-content
#wordpress root에서
chgrp www-data *

wp-content는 www-data가 소유자로 그대로 둬야 한다. wp-content의 하부 디렉토리 권한을 안바꾸면 파일 업로드, 수정이 안된다.

http://stackoverflow.com/questions/18352682/correct-file-permissions-for-wordpress

TI6 본선

요즘 올림픽이다 난린데, 여긴 하나도 안보여준다…

올림픽보다..얼마전에 시작한 TI6가 볼만하네..한국의 유일한 출전팀 MVP가 본선 1차전에서 랭킹 1위를 씹어먹는 플레이..본선전 예선에는 0승으로 간신히 올라갔다는데..

3차전은 거의 학살이던데..

외국 다른팀들은 조용히 파밍하다가 나중에 한타로 승부를 내는데, 얘네들은 하루종일 줘패네…여기서 져도 상금 10억이라고 하니..밸브가 정말 돈을 어떻게 버는지 아는 회사이다..

내돈 만원도 들어가 있는데, 할수가 없네..

한국팀의 우승을 응원합니다!!!

2차전에서..아쉽게 패배…

상대가 MVP 천적이라는데, 치트키 켜고 겜하는줄 알았네..
트위치에서도 한국어 서비스를 해줬다..

Watch live video from Dota2_KR on www.twitch.tv

다른 게임대회들은 상금도 적고, 광고주에게서 돈이 나오는데..도타2는 그딴거 필요 없는듯..
프로 골퍼보다 나아보인다..