93
Microsoft Robotics Developer Studio 고고 고고고고고 고고 [Part 5] CCR 고 DSS 고고고 고고고고고 2008 로로로로 로로 로로로로로로로 로 로 로 로로 [email protected]

Microsoft Robotics Developer Studio 고급 프로그래밍 과정 [Part 5] CCR 및 DSS 서비스 프로그래밍

Embed Size (px)

DESCRIPTION

Microsoft Robotics Developer Studio 고급 프로그래밍 과정 [Part 5] CCR 및 DSS 서비스 프로그래밍. 2008 로보틱스 그룹 마이크로소프트. 김 영 준 수석 [email protected]. 목차. Part 1: CCR 프로그래밍 Part 2: 기본 DSS 서비스 개발 Part 3: 로봇 기본 서비스 개발 Part 4: 로봇 연결 서비스 개발 Part 5: UI 가 포함된 서비스 개발. CCR 프로그래밍. - PowerPoint PPT Presentation

Citation preview

Page 1: Microsoft Robotics Developer Studio 고급 프로그래밍 과정 [Part 5] CCR  및  DSS  서비스 프로그래밍

Microsoft Robotics Developer Studio

고급 프로그래밍 과정

[Part 5] CCR 및 DSS 서비스 프로그래밍

2008로보틱스 그룹

마이크로소프트

김 영 준 수석[email protected]

Page 2: Microsoft Robotics Developer Studio 고급 프로그래밍 과정 [Part 5] CCR  및  DSS  서비스 프로그래밍

2Microsoft Robotics Studio

목차

Part 1: CCR 프로그래밍 Part 2: 기본 DSS 서비스 개발 Part 3: 로봇 기본 서비스 개발 Part 4: 로봇 연결 서비스 개발 Part 5: UI 가 포함된 서비스 개발

Page 3: Microsoft Robotics Developer Studio 고급 프로그래밍 과정 [Part 5] CCR  및  DSS  서비스 프로그래밍

3Microsoft Robotics Studio

CCR 프로그래밍

Page 4: Microsoft Robotics Developer Studio 고급 프로그래밍 과정 [Part 5] CCR  및  DSS  서비스 프로그래밍

4Microsoft Robotics Studio

Dispatcher 와 DispatcherQueue

CCR 의 기본 처리 방식 뭔가 해야 할 일을 생성함 생성된 일을 작업 큐에 넣어 놓음 일을 처리하는 엔진이 큐에 있는 해야 할 일을 가져다가 처리함

CCR 에서는 뭔가 해야 할 일을 정의하기 위해 ITask 클래스 형태의 객체를 사용함

실제 일을 수행하는 엔진이라 할 수 있는 Dispacher 라는 것이 존재함 Dispacher 에 여러 개의 큐브를 만들어 놓을 수 있음 이 큐를 DispacherQueue 라고 함 이러한 큐들은 모두 Dispacher 가 관리를 함

Page 5: Microsoft Robotics Developer Studio 고급 프로그래밍 과정 [Part 5] CCR  및  DSS  서비스 프로그래밍

5Microsoft Robotics Studio

Dispatcher 와 DispatcherQueue

Page 6: Microsoft Robotics Developer Studio 고급 프로그래밍 과정 [Part 5] CCR  및  DSS  서비스 프로그래밍

6Microsoft Robotics Studio

Dispatcher 와 DispatcherQueue

private void button1_Click(object sender, EventArgs e) { //Dispather 를 생성한다 using (Dispatcher dispatcher = new Dispatcher(0, " 첫번째 예제 ")) { //Dispatcher 로 부터 DispatcherQueue 를 생성한다 . // 나중에 작업해야할 태스크들을 생성한 후 이 큐에 넣어 놓으면 CCR 엔진이 처리함 DispatcherQueue dq1 = new DispatcherQueue("DispatcherQueue1", dispatcher); DispatcherQueue dq2 = new DispatcherQueue("DispatcherQueue2", dispatcher);  // 간단하게 Dispacher 와 DispacherQueues 의 정보들을 표시함 listBox1.Items.Clear(); listBox1.Items.Add("Dispacher 이름 : " + dispatcher.Name); listBox1.Items.Add("PendingTaskCount : " + dispatcher.PendingTaskCount.ToString()); listBox1.Items.Add("ProcessedTaskCount : " + dispatcher.ProcessedTaskCount.ToString()); listBox1.Items.Add("WorkerThreadCount : " + dispatcher.WorkerThreadCount.ToString()); listBox1.Items.Add("DispatcherQueue Count : " + dispatcher.DispatcherQueues.Count.ToString());  //Dispacher 에 있는 DispacherQueses 들을 나열함 foreach (DispatcherQueue dq in dispatcher.DispatcherQueues) { listBox1.Items.Add("DispatcherQueue in Dispacher : " + dq.Name); } } } 

Page 7: Microsoft Robotics Developer Studio 고급 프로그래밍 과정 [Part 5] CCR  및  DSS  서비스 프로그래밍

7Microsoft Robotics Studio

CCR 의 ITask

Page 8: Microsoft Robotics Developer Studio 고급 프로그래밍 과정 [Part 5] CCR  및  DSS  서비스 프로그래밍

8Microsoft Robotics Studio

CCR 의 ITask

private void button1_Click(object sender, EventArgs e) { using (Dispatcher dispatcher = new Dispatcher(0, " 두번째 예제 ")) { DispatcherQueue dq = new DispatcherQueue("DispatcherQueue", dispatcher);  //Define handler of Anonymous method Handler myTaskHandler = delegate { System.Windows.Forms.MessageBox.Show("Hello"); };  //Define ITask ITask myTask = Arbiter.FromHandler(myTaskHandler);  //Insert into DispacherQueue dq.Enqueue(myTask);  //You can Also execute ITask as follow //Arbiter.Activate(dq, myTask); } } 

Page 9: Microsoft Robotics Developer Studio 고급 프로그래밍 과정 [Part 5] CCR  및  DSS  서비스 프로그래밍

9Microsoft Robotics Studio

CCR 의 ITask

private void button2_Click(object sender, EventArgs e) { using (Dispatcher dispatcher = new Dispatcher(0, " 두번째 예제 ")) { DispatcherQueue dq = new DispatcherQueue("DispatcherQueue", dispatcher);  //Define Itask using seperate handler procedure ITask myTask = Arbiter.FromHandler(myTimeHandler());  dq.Enqueue(myTask); // Or Arbiter.Activate(dq, myTask); } }  //This handler is converted into the ITask private Handler myTimeHandler() { //Insert current Time into the ListBox listBox1.Items.Add(System.DateTime.Now.ToString());  return null; }

 

Page 10: Microsoft Robotics Developer Studio 고급 프로그래밍 과정 [Part 5] CCR  및  DSS  서비스 프로그래밍

10Microsoft Robotics Studio

메시지를 전달하는 Portprivate void button1_Click(object sender, EventArgs e) { //Define Port with String Type //You also can use any type of class  Port<String> myPort = new Port<string>();  myPort.Post("Test String 1"); myPort.Post("Test String 2"); myPort.Post("Test String 3"); myPort.Post("Test String 4"); myPort.Post("Test String 5");   //Pick out the Item from Port // 여러가지 방법으로 데이터를 꺼낼 수 있음  //case 1 <- "Test String 1" will be picked out String myStr1 = (String)myPort.Test(); listBox1.Items.Add(myStr1);  //case 2 <- "Test String 2" will be picked out listBox1.Items.Add((String)myPort.Test());  //case 3 <- "Test String 3" will be picked out String myStr2 = null; myPort.Test(out myStr2);  listBox1.Items.Add(myStr2);  //case 4 <- "Test String 4, 5" will be picked out while (myPort.Test(out myStr2)) { listBox1.Items.Add(myStr2); } }

Page 11: Microsoft Robotics Developer Studio 고급 프로그래밍 과정 [Part 5] CCR  및  DSS  서비스 프로그래밍

11Microsoft Robotics Studio

멀티 형식의 메세지를 전달하는 PortSet

private void button1_Click(object sender, EventArgs e) { PortSet<int, String> myPortSet = new PortSet<int, String>();  myPortSet.Post(1); //or myPortSet.P0.Post(2);   myPortSet.Post("Hi"); //or myPortSet.P1.Post("Hello");  //Pick out from the first Port int retInt = 0;  while (myPortSet.P0.Test(out retInt)) { listBox1.Items.Add("Int:" + retInt.ToString()); }  //Pick out from the second Port String retStr = null;  while (myPortSet.P1.Test(out retStr)) { listBox1.Items.Add("String:" + retStr); } }

Page 12: Microsoft Robotics Developer Studio 고급 프로그래밍 과정 [Part 5] CCR  및  DSS  서비스 프로그래밍

12Microsoft Robotics Studio

Arbiter 를 이용해 Task 만들기

private void button1_Click(object sender, EventArgs e) { using (Dispatcher dispatcher = new Dispatcher(0, " 다섯번째 예제 ")) { DispatcherQueue dq = new DispatcherQueue("DispatcherQueue", dispatcher);  // 헨들러 타입으로 선언되어 있는 것을 ITask 형식으로 변환시킴 ITask myTask = Arbiter.FromHandler(myHandler());  Arbiter.Activate(dq, myTask); // 또는 dq,Enqueue(myTask); } }

// 수행해야할 작업들이 기술되어 있는 헨들러임 private Handler myHandler() { // 현재의 시간을 리스트박스에 출력합니다 . listBox1.Items.Add("Now is " + System.DateTime.Now.ToString());  return null; }

Page 13: Microsoft Robotics Developer Studio 고급 프로그래밍 과정 [Part 5] CCR  및  DSS  서비스 프로그래밍

13Microsoft Robotics Studio

Arbiter.Receive 를 이용해 메시지와 헨들러 연결하기

private void button1_Click(object sender, EventArgs e) { using (Dispatcher dispatcher = new Dispatcher(0, " 여섯번 째 예제 ")) { DispatcherQueue dq = new DispatcherQueue("DispatcherQueue", dispatcher);  // 메세지를 받을 포트를 정의함 Port<myStatus> mySatusPort = new Port<myStatus>();  myStatus myStatus1 = new myStatus(); myStatus myStatus2 = new myStatus();  myStatus1.inputStr = "Test String 1"; // 포트에 추가함 mySatusPort.Post(myStatus1);   // 해당 포트에 메시지가 수신되면 해당 헨들러가 수행되도록 하는 Task 를 생성함 ITask myTask = Arbiter.Receive(true, mySatusPort, myHandler);   myStatus2.inputStr = "Test String 2"; //Insert the item into the Port mySatusPort.Post(myStatus2);   Arbiter.Activate(dq, myTask); // Or dq,Enqueue(myTask);   // 잠시 기다렸다가 실행함 System.Threading.Thread.Sleep(300);  // 결과를 출력함 listBox1.Items.Add("[1] " + myStatus1.outputStr); listBox1.Items.Add("[2] " + myStatus2.outputStr); } }

Page 14: Microsoft Robotics Developer Studio 고급 프로그래밍 과정 [Part 5] CCR  및  DSS  서비스 프로그래밍

14Microsoft Robotics Studio

Arbiter.Receive 를 이용해 메시지와 헨들러 연결하기 #2

// 수신받을 메세지 타입을 클래스로 정의해야 함 public class myStatus { public String inputStr = null; public String outputStr = null; }

public void myHandler(myStatus myStatus) { // 입력받은 값에 현재 날짜와 시간을 더해서 outputStr 변수에 저장함 myStatus.outputStr = System.DateTime.Now.ToString() + " : " + myStatus.inputStr; }

Page 15: Microsoft Robotics Developer Studio 고급 프로그래밍 과정 [Part 5] CCR  및  DSS  서비스 프로그래밍

15Microsoft Robotics Studio

Arbiter.JoinedReceive 를 이용해 여러 개의 메시지와 헨들러 연결하기

private void button1_Click(object sender, EventArgs e) { using (Dispatcher dispatcher = new Dispatcher(0, " 일곱번째 예제 ")) { DispatcherQueue dq = new DispatcherQueue("DispatcherQueue", dispatcher);  //2 가지 타입의 변수들을 받아들이기 위한 포트 선언 Port<myStatus1> myPort1 = new Port<myStatus1>(); Port<myStatus2> myPort2 = new Port<myStatus2>();  myStatus1 myClass1 = new myStatus1(); myStatus2 myClass2 = new myStatus2();  myClass1.inputStr = " 첫번째 클래스 변수의 값입니다 ."; myPort1.Post(myClass1);  myClass2.inputStr = " 두번째 클래스 변수의 값입니다 ."; myPort2.Post(myClass2);  // 해야할 일을 ITask 형식으로 생성함 ITask myTask = Arbiter.JoinedReceive(false, myPort1, myPort2, myHandler);  Arbiter.Activate(dq, myTask); // Or dq,Enqueue(myTask);   //Waiting for the message processing System.Threading.Thread.Sleep(300);  listBox1.Items.Add("[ 결과 ] " + myClass1.outputStr); } } 

Page 16: Microsoft Robotics Developer Studio 고급 프로그래밍 과정 [Part 5] CCR  및  DSS  서비스 프로그래밍

16Microsoft Robotics Studio

Arbiter.JoinedReceive 를 이용해 여러 개의 메시지와 헨들러 연결하기 #2

// 수신받을 메세지 타입을 클래스로 정의해야 함 public class myStatus1 { public String inputStr = null; public String outputStr = null; }  public class myStatus2 { public String inputStr = null; public String outputStr = null; }

public void myHandler(myStatus1 myClass1, myStatus2 myClass2) { // 두 클래스 변수의 입력값을 연결하여 첫번째 클래스 변수의 outputStr 에 저장함 myClass1.outputStr = myClass1.inputStr + "+" + myClass2.inputStr; }

Page 17: Microsoft Robotics Developer Studio 고급 프로그래밍 과정 [Part 5] CCR  및  DSS  서비스 프로그래밍

17Microsoft Robotics Studio

Arbiter.Choice 를 이용해 여러 개의 메시지중 하나에 반응하기

private void button1_Click(object sender, EventArgs e) { using (Dispatcher dispatcher = new Dispatcher(0, " 여덟 번째 예제 ")) { DispatcherQueue dq = new DispatcherQueue("DispatcherQueue", dispatcher);  //PortSet 을 이용하여 두 가지 타입의 메세지를 받아들일 수 있도록 함 PortSet<myStatus1, myStatus2> myPortSet = new PortSet<myStatus1, myStatus2>();  // 클래스 초기화 myStatus1 myClass1 = new myStatus1(); myStatus2 myClass2 = new myStatus2();  // 두 개의 메시지 타입 중 한가지만 등록되도록 함 if (!checkBox1.Checked) { myClass1.inputStr = " 첫번째 값 "; myPortSet.P0.Post(myClass1); }  if (checkBox1.Checked) { myClass2.inputStr = " 두 번째 값 "; myPortSet.P1.Post(myClass2); }  // 해야 할 일을 ITask 로 변환함 ITask myTask = Arbiter.Choice(myPortSet, myHandler1, myHandler2);  Arbiter.Activate(dq, myTask); // Or dq,Enqueue(myTask);   //Waiting for the message processing System.Threading.Thread.Sleep(300);  listBox1.Items.Add("[Class1] " + myClass1.outputStr); listBox1.Items.Add("[Class2] " + myClass2.outputStr); } } 

Page 18: Microsoft Robotics Developer Studio 고급 프로그래밍 과정 [Part 5] CCR  및  DSS  서비스 프로그래밍

18Microsoft Robotics Studio

Arbiter.Choice 를 이용해 여러 개의 메시지중 하나에 반응하기 #2

// 수신받을 메세지 타입을 클래스로 정의해야 함 public class myStatus1 { public String inputStr = null; public String outputStr = null; }  public class myStatus2 { public String inputStr = null; public String outputStr = null; }

public void myHandler1(myStatus1 myClass1) { myClass1.outputStr = "Handler1 실행됨 : " + myClass1.inputStr; }  public void myHandler2(myStatus2 myClass2) { myClass2.outputStr = "Handler2 실행됨 : " + myClass2.inputStr; }

Page 19: Microsoft Robotics Developer Studio 고급 프로그래밍 과정 [Part 5] CCR  및  DSS  서비스 프로그래밍

19Microsoft Robotics Studio

Arbiter.Interleave 를 이용한 동시 작업 제어하기

private void button1_Click(object sender, EventArgs e) { using (Dispatcher dispatcher = new Dispatcher(0, " 아홉번째 예제 ")) { DispatcherQueue dq = new DispatcherQueue("DispatcherQueue", dispatcher);  //Define three Ports Port<myStatus1> myPort1 = new Port<myStatus1>(); Port<myStatus2> myPort2 = new Port<myStatus2>(); Port<myStatus3> myPort3 = new Port<myStatus3>();  //Initialize the class objects myStatus1 myClass1 = new myStatus1(); myStatus2 myClass2 = new myStatus2(); myStatus3 myClass3 = new myStatus3();  

Page 20: Microsoft Robotics Developer Studio 고급 프로그래밍 과정 [Part 5] CCR  및  DSS  서비스 프로그래밍

20Microsoft Robotics Studio

Arbiter.Interleave 를 이용한 동시 작업 제어하기 #2

//Choose one between the bellow three classes if (checkBox1.Checked) { myClass1.inputStr = " 첫 번째 "; myPort1.Post(myClass1); }  myClass2.inputStr = " 두 번째 "; myPort2.Post(myClass2);  myClass3.inputStr = " 세 번째 "; myPort3.Post(myClass3);  //Define ITask ITask myTask = Arbiter.Interleave( new TeardownReceiverGroup( Arbiter.Receive(false, myPort1, myHandler1) ), new ExclusiveReceiverGroup( Arbiter.Receive(true, myPort2, myHandler2) ), new ConcurrentReceiverGroup( Arbiter.Receive(true, myPort3, myHandler3) ) );  Arbiter.Activate(dq, myTask);  //Waiting for the message processing System.Threading.Thread.Sleep(300);  listBox1.Items.Add("[1 번 결과 ] " + myClass1.outputStr); listBox1.Items.Add("[2 번 결과 ] " + myClass2.outputStr); listBox1.Items.Add("[3 번 결과 ] " + myClass3.outputStr); } }

Page 21: Microsoft Robotics Developer Studio 고급 프로그래밍 과정 [Part 5] CCR  및  DSS  서비스 프로그래밍

21Microsoft Robotics Studio

Arbiter.Interleave 를 이용한 동시 작업 제어하기 #3

public class myStatus1 { public String inputStr = null; public String outputStr = null; }  public class myStatus2 { public String inputStr = null; public String outputStr = null; }  public class myStatus3 { public String inputStr = null; public String outputStr = null; } public void myHandler1(myStatus1 myClass1) { myClass1.outputStr = "Handler1 실행 : " + myClass1.inputStr; }  public void myHandler2(myStatus2 myClass2) { myClass2.outputStr = "Handler2 실행 : " + myClass2.inputStr; }  public void myHandler3(myStatus3 myClass3) { myClass3.outputStr = "Handler3 실행 : " + myClass3.inputStr; } 

Page 22: Microsoft Robotics Developer Studio 고급 프로그래밍 과정 [Part 5] CCR  및  DSS  서비스 프로그래밍

22Microsoft Robotics Studio

Demo: Concurrency processing

Page 23: Microsoft Robotics Developer Studio 고급 프로그래밍 과정 [Part 5] CCR  및  DSS  서비스 프로그래밍

23Microsoft Robotics Studio

Coding pattern for asynchronous task handling

//Do Task A-1yield return Arbiter.Choice( DoAsynchronousTask A-1, delegate(…) { do for successful result }, delegate(Exception e) { do exceptional case });

if (error) yield break;

//Do Task A-2yield return Arbiter.Choice( DoAsynchronousTask A-2, delegate(…) { do for successful result }, delegate(Exception e) { do exceptional case });…//Do Task A-3…

Page 24: Microsoft Robotics Developer Studio 고급 프로그래밍 과정 [Part 5] CCR  및  DSS  서비스 프로그래밍

24Microsoft Robotics Studio

Demo: Summation from 1 to 1000,000,000

- Use one thread

Page 25: Microsoft Robotics Developer Studio 고급 프로그래밍 과정 [Part 5] CCR  및  DSS  서비스 프로그래밍

25Microsoft Robotics Studio

Demo: Summation from 1 to 1000,000,000

- Use multi-core

Page 26: Microsoft Robotics Developer Studio 고급 프로그래밍 과정 [Part 5] CCR  및  DSS  서비스 프로그래밍

26Microsoft Robotics Studio

Demo: Sample code

dispatcher = new Dispatcher(0, "CCRSample");dq = new DispatcherQueue("DispatcherQueue", dispatcher);

//Start timeticks1 = System.DateTime.Now.Ticks;

//Summation between 1 ~ 500,000,000Arbiter.Activate(dq, Arbiter.FromIteratorHandler(myHandler1_2));

//Summation between 500,000,0001 ~ 1000,000,000Arbiter.Activate(dq, Arbiter.FromIteratorHandler(myHandler2_2));

//Merge result Arbiter.Activate(dq, Arbiter.JoinedReceive(false, p1, p2, delegate(long s1, long s2){

ticks2 = System.DateTime.Now.Ticks;

//Display final resultlistBox1.Items.Add("Total Sum: " + (s1 + s2).ToString());

//Display elapsed resultlistBox1.Items.Add("Elapsed Time (ms): " + ((ticks2 - ticks1) / 10000).ToString());

}));

Page 27: Microsoft Robotics Developer Studio 고급 프로그래밍 과정 [Part 5] CCR  및  DSS  서비스 프로그래밍

27Microsoft Robotics Studio

Massive calculation processing- Segmentation of calculation block

Matrix calculation

Server 1

Server 2

Server 3

Server 4

Calculation result

Manycore

Manycore

Manycore

Manycore

Page 28: Microsoft Robotics Developer Studio 고급 프로그래밍 과정 [Part 5] CCR  및  DSS  서비스 프로그래밍

28Microsoft Robotics Studio

Massive calculation processing- Sequential processing for isolated

data

Server 1

Manycore

Server 2

Manycore

Server 3

Manycore

Server 4

Manycore

Data n … Data 2 Data 1

CCR DSS

Page 29: Microsoft Robotics Developer Studio 고급 프로그래밍 과정 [Part 5] CCR  및  DSS  서비스 프로그래밍

29Microsoft Robotics Studio

Concurrent processing by utilizing manycore and multiprocessor

Core 1

Core 2

Core 3

Core n

Core 1

Core 2

Core 3

Core n

Core 1

Core 2

Core 3

Core n

Core 1

Core 2

Core 3

Core n

CPU 1 CPU 2 CPU 3 CPU n

Task 1

Task 2 Choice

Task 6

Task 4

Task 5

Choice

Task 8 Task 9

Join

Task 7

Task 3

Task

CCR

Page 30: Microsoft Robotics Developer Studio 고급 프로그래밍 과정 [Part 5] CCR  및  DSS  서비스 프로그래밍

30Microsoft Robotics Studio

High performance calculation with distributed concurrency platform

Image and signal processingPrecise orbit calculationFuel accountingCalculation for simulation

Core 1

Core 2

Core n

Core 1

Core 2

Core n

CPU 1 CPU n

… ……

Core 1

Core 2

Core n

Core 1

Core 2

Core n

CPU 1 CPU n

… ……

Core 1

Core 2

Core n

Core 1

Core 2

Core n

CPU 1 CPU n

… ………

Server 1 Server 2 Server n

Node Clusterfor Distributed and

Concurrent Processing

Page 31: Microsoft Robotics Developer Studio 고급 프로그래밍 과정 [Part 5] CCR  및  DSS  서비스 프로그래밍

31Microsoft Robotics Studio

기본 DSS 서비스 개발

Page 32: Microsoft Robotics Developer Studio 고급 프로그래밍 과정 [Part 5] CCR  및  DSS  서비스 프로그래밍

32Microsoft Robotics Studio

DSS 서비스란 ?

MSRS 에서 사용되는 모든 프로그램은 DSS 서비스 형태로 만들어 짐

입력 출력

서비스 인터페이스

Page 33: Microsoft Robotics Developer Studio 고급 프로그래밍 과정 [Part 5] CCR  및  DSS  서비스 프로그래밍

33Microsoft Robotics Studio

DSS 서비스의 구성

DSS 서비스

서비스에서 사용되는데이터를 보관하는

클래스 (State 라고 부름 )

Get인터페이스

Update인터페이스

Replace인터페이스

Subscribe인터페이스

Get핸들러

Update핸들러

Replace핸들러

Subscribe핸들러

Page 34: Microsoft Robotics Developer Studio 고급 프로그래밍 과정 [Part 5] CCR  및  DSS  서비스 프로그래밍

34Microsoft Robotics Studio

DSS 서비스 개발 과정

1 단계 MSRS 의 dssnewservice.exe 를 통해서 기본 템플릿 생성

2 단계 주고 받을 데이터 클래스 정의

3 단계 주고 받을 인터페이스 ( 포트 ) 정의

4 단계 해당 데이터를 처리하는 핸들러 모듈 구현

Page 35: Microsoft Robotics Developer Studio 고급 프로그래밍 과정 [Part 5] CCR  및  DSS  서비스 프로그래밍

35Microsoft Robotics Studio

DSS 서비스 개발의 특징

기존에 이미 정의되어 있는 클래스를 이용함 Get Update Replace Subscribe

위의 4 가지 패턴만 이용하면 모든 서비스들이 구현 가능

내부의 상태 값은 옵션 항목으로서 서비스 구현 시 반드시 사용되는 것은 아님

Page 36: Microsoft Robotics Developer Studio 고급 프로그래밍 과정 [Part 5] CCR  및  DSS  서비스 프로그래밍

36Microsoft Robotics Studio

Get 유형의 서비스

Get 은 서비스 내부에 저장되어 있는 상태 값을 리턴함

Get 요청 현재 시간 리턴

Page 37: Microsoft Robotics Developer Studio 고급 프로그래밍 과정 [Part 5] CCR  및  DSS  서비스 프로그래밍

37Microsoft Robotics Studio

Get 서비스 생성

1 단계 MSRS 의 dssnewservice.exe 를 통해서 기본 템플릿 생성 dssnewservice /namespace:MSRS.Lecture.DSS /service:MyClock

2 단계 주고 받을 데이터 클래스 정의 MyClockState 항목 안에 아래 코드 추가

3 단계 주고 받을 인터페이스 ( 포트 ) 정의 ( 이미 템플릿으로 만들어져 있기 때문에 생략 )

4 단계 해당 데이터를 처리하는 핸들러 모듈 구현 이미 만들어져 있는 Get 핸들러 안에 아래 코드 추가

5 단계 컴파일 후 VPL 에서 테스트

[DataContract()] public class MyClockState { [DataMember] public string CurrentDateTime = ""; }

[ServiceHandler(ServiceHandlerBehavior.Concurrent)] public virtual IEnumerator<ITask> GetHandler(Get get) { _state.CurrentDateTime = System.DateTime.Now.ToString();

get.ResponsePort.Post(_state); yield break; }

Page 38: Microsoft Robotics Developer Studio 고급 프로그래밍 과정 [Part 5] CCR  및  DSS  서비스 프로그래밍

38Microsoft Robotics Studio

Get 서비스 테스트

VPL 다이어그램

과제 속도 값을 가지는 두 개의 변수를 선언해서 값 읽어 오기

Page 39: Microsoft Robotics Developer Studio 고급 프로그래밍 과정 [Part 5] CCR  및  DSS  서비스 프로그래밍

39Microsoft Robotics Studio

Update 유형의 서비스

서비스 내부에 저장되어 있는 상태 값을 변경시킴

Update 할 값 전달 처리 결과 리턴

Page 40: Microsoft Robotics Developer Studio 고급 프로그래밍 과정 [Part 5] CCR  및  DSS  서비스 프로그래밍

40Microsoft Robotics Studio

Update 서비스 생성

1 단계 MSRS 의 dssnewservice.exe 를 통해서 기본 템플릿 생성 dssnewservice /namespace:MSRS.Lecture.DSS /service:MyWheels

2 단계 주고 받을 데이터 클래스 정의

3 단계 주고 받을 인터페이스 ( 포트 ) 정의

4 단계 해당 데이터를 처리하는 핸들러 모듈 구현

5 단계 컴파일 후 VPL 에서 테스트

[DataContract()] public class MyWheelsState { [DataMember] public double LeftWheel = 0;

[DataMember] public double RightWheel = 0; }

[ServiceHandler(ServiceHandlerBehavior.Exclusive)] public virtual IEnumerator<ITask> UpdateHandler(Update update) { _state.LeftWheel = update.Body.LeftWheel; _state.RightWheel = update.Body.RightWheel;

update.ResponsePort.Post(DefaultUpdateResponseType.Instance); yield break; }

public class Update : Update<MyWheelsState, PortSet<DefaultUpdateResponseType, Fault>> { }

[ServicePort()] public class MyWheelsOperations : PortSet<DsspDefaultLookup, DsspDefaultDrop, Get, Update> { }

Page 41: Microsoft Robotics Developer Studio 고급 프로그래밍 과정 [Part 5] CCR  및  DSS  서비스 프로그래밍

41Microsoft Robotics Studio

Update 서비스 테스트

값을 저장하는 VPL 다이어그램

과제 저장된 값을 확인하는 다이어그램 코드의 추가

Page 42: Microsoft Robotics Developer Studio 고급 프로그래밍 과정 [Part 5] CCR  및  DSS  서비스 프로그래밍

42Microsoft Robotics Studio

Replace 유형의 서비스

서비스 내부에 저장되어 있는 상태 값을 통째로 변경시킴

내부적으로는 Update 유형과 차이는 없음 Update 사용시에는 코드 내부에서 일부 필드만 사용될 경우를 가정함 Replace 사용시에는 내부 코드에서 통째로 State 가 변경되는 경우는

가정함

일반적으로는 State 값의 일부만 변경하는 경우가 대부분임으로 주로 Update 유형을 많이 적용함

Replace 할 값 전달 처리 결과 리턴

Page 43: Microsoft Robotics Developer Studio 고급 프로그래밍 과정 [Part 5] CCR  및  DSS  서비스 프로그래밍

43Microsoft Robotics Studio

Replace 서비스 생성

1 단계 MSRS 의 dssnewservice.exe 를 통해서 기본 템플릿 생성

2 단계 주고 받을 데이터 클래스 정의

3 단계 주고 받을 인터페이스 ( 포트 ) 정의

4 단계 해당 데이터를 처리하는 핸들러 모듈 구현

5 단계 컴파일 후 VPL 에서 테스트

[ServiceHandler(ServiceHandlerBehavior.Exclusive)] public virtual IEnumerator<ITask> ReplaceHandler(Replace replace) { _state = replace.Body;

replace.ResponsePort.Post(DefaultReplaceResponseType.Instance); yield break; }

public class Replace : Replace<MyWheelsState, PortSet<DefaultReplaceResponseType, Fault>> { }

[ServicePort()] public class MyWheelsOperations : PortSet<DsspDefaultLookup, DsspDefaultDrop, Get, Update, Replace> { }

Page 44: Microsoft Robotics Developer Studio 고급 프로그래밍 과정 [Part 5] CCR  및  DSS  서비스 프로그래밍

44Microsoft Robotics Studio

Replace 서비스 테스트

값을 저장하는 VPL 다이어그램

과제 저장된 값을 확인하는 다이어그램 코드의 추가

Page 45: Microsoft Robotics Developer Studio 고급 프로그래밍 과정 [Part 5] CCR  및  DSS  서비스 프로그래밍

45Microsoft Robotics Studio

Subscribe 유형의 서비스

일종의 구독 신청 후 , 값을 전달 받는 방식으로서 , 통상적으로 이벤트를 구독 신청해 놓고 관련 이벤트가 발생할 때 마다 값을 받는 방식임

이벤트 결과 리턴

Page 46: Microsoft Robotics Developer Studio 고급 프로그래밍 과정 [Part 5] CCR  및  DSS  서비스 프로그래밍

46Microsoft Robotics Studio

Subscribe 서비스 생성

1 단계 MSRS 의 dssnewservice.exe 를 통해서 기본 템플릿 생성

2 단계 주고 받을 데이터 클래스 정의

3 단계 주고 받을 인터페이스 ( 포트 ) 정의

4 단계

5 단계 컴파일 후 VPL 에서 테스트

using submgr = Microsoft.Dss.Services.SubscriptionManager;

[Partner("SubMgr", Contract = submgr.Contract.Identifier, CreationPolicy = PartnerCreationPolicy.CreateAlways)] private submgr.SubscriptionManagerPort _submgrPort = new submgr.SubscriptionManagerPort();

public virtual IEnumerator<ITask> UpdateHandler(Update update){…SendNotification<Update>(_submgrPort, _state);…}

[ServiceHandler(ServiceHandlerBehavior.Exclusive)] public IEnumerator<ITask> SubscribeHandler(Subscribe subscribe) { yield return Arbiter.Choice( SubscribeHelper(_submgrPort, subscribe.Body, subscribe.ResponsePort), delegate(SuccessResult success) { }, delegate(Exception fault) { } ); }

public class Subscribe : Subscribe<SubscribeRequestType, PortSet<SubscribeResponseType, Fault>> { }

[ServicePort()] public class MyWheelsOperations : PortSet<DsspDefaultLookup, DsspDefaultDrop, Subscribe, Get, Update, Replace> { }

Page 47: Microsoft Robotics Developer Studio 고급 프로그래밍 과정 [Part 5] CCR  및  DSS  서비스 프로그래밍

47Microsoft Robotics Studio

Subscribe 서비스 테스트

변경된 값을 리턴하는 VPL 다이어그램

Page 48: Microsoft Robotics Developer Studio 고급 프로그래밍 과정 [Part 5] CCR  및  DSS  서비스 프로그래밍

Microsoft Robotics Developer Studio

고급 프로그래밍 과정

[Part 6] 로봇 서비스 프로그래밍

2008로보틱스 그룹

마이크로소프트

김 영 준 수석[email protected]

Page 49: Microsoft Robotics Developer Studio 고급 프로그래밍 과정 [Part 5] CCR  및  DSS  서비스 프로그래밍

49Microsoft Robotics Studio

로봇 기본 서비스 개발

Page 50: Microsoft Robotics Developer Studio 고급 프로그래밍 과정 [Part 5] CCR  및  DSS  서비스 프로그래밍

50Microsoft Robotics Studio

로봇 기본 서비스

로봇의 센서와 엑츄에이터 제어와 관련된 공통적인 인터페이스들을 MS 에서 미리 정의해 놓았음 Drive Contact Sensor Motor Web Cam

이미 관련 State 와 인터페이스들이 정의되어 있기 때문에 기존 정의된 항목들을 그대로 사용하면 됨

개발하는 절차는 기본 DSS 서비스 방식과 동일함

Page 51: Microsoft Robotics Developer Studio 고급 프로그래밍 과정 [Part 5] CCR  및  DSS  서비스 프로그래밍

51Microsoft Robotics Studio

Bumper 서비스 구현하기 #1

using Microsoft.Ccr.Core;

using Microsoft.Dss.Core;

using Microsoft.Dss.Core.Attributes;

using Microsoft.Dss.ServiceModel.Dssp;

using Microsoft.Dss.ServiceModel.DsspServiceBase;

using System;

using System.Collections.Generic;

using System.ComponentModel;

using System.Xml;

using myfirstbrick = MyFirstBrick;

using drive = Microsoft.Robotics.Services.Drive.Proxy;

using bumper = Microsoft.Robotics.Services.ContactSensor.Proxy;

using motor = Microsoft.Robotics.Services.Motor.Proxy;

using submgr = Microsoft.Dss.Services.SubscriptionManager;

Page 52: Microsoft Robotics Developer Studio 고급 프로그래밍 과정 [Part 5] CCR  및  DSS  서비스 프로그래밍

52Microsoft Robotics Studio

Bumper 서비스 구현하기 #2

namespace MyFirstBrickBumper

{

public sealed class Contract

{ public const String Identifier = "http://schemas.tempuri.org/2007/10/myfirstbrickbumper.html";

}

[DisplayName("MyFirstBrickBumper")]

[Description("The MyFirstBrickBumper Service")]

[Contract(Contract.Identifier)]

[AlternateContract(bumper.Contract.Identifier)]

public class MyFirstBumperService : DsspServiceBase

{

private bumper.ContactSensor _state = new bumper.ContactSensor();

[ServicePort("/myfirstbrickbumper", AllowMultipleInstances = false)]

private bumper.ContactSensorArrayOperations _mainPort = new bumper.ContactSensorArrayOperations();

// 구독기능을위해항상추가되어하는코드임 [Partner("SubMgr", Contract = submgr.Contract.Identifier, CreationPolicy = PartnerCreationPolicy.CreateAlways)]

private submgr.SubscriptionManagerPort _submgr = new submgr.SubscriptionManagerPort();

// 새로추가한타이머라인 private Port<DateTime> _timerPort = new Port<DateTime>();

 

public MyFirstBumperService(DsspServiceCreationPort creationPort)

: base(creationPort)

{ }

Page 53: Microsoft Robotics Developer Studio 고급 프로그래밍 과정 [Part 5] CCR  및  DSS  서비스 프로그래밍

53Microsoft Robotics Studio

Bumper 서비스 구현하기 #3

protected override void Start()

{ base.Start();

// 타이머최초구동명령 _timerPort.Post(DateTime.Now);

Activate(Arbiter.Receive(true, _timerPort, TimerHandler));

}

// 주기적으로호출되는타이머모듈 void TimerHandler(DateTime signal)

{

//Bumper 신호를가상으로생성함 bumper.ContactSensor _newSensor = new bumper.ContactSensor();

_newSensor.HardwareIdentifier = 1;

_newSensor.Name = "front";

_newSensor.Pressed = true;

 

// 구독관리자에값을전달함 SendNotification<bumper.Update>(_submgr, _newSensor);

 

Activate(

Arbiter.Receive(false, TimeoutPort(1000), //1 초간격으로다시호출함 delegate(DateTime time)

{

_timerPort.Post(time);

}

)

);

}

Page 54: Microsoft Robotics Developer Studio 고급 프로그래밍 과정 [Part 5] CCR  및  DSS  서비스 프로그래밍

54Microsoft Robotics Studio

Bumper 서비스 구현하기 #4

//Update 헨들러를위해추가된코드 //bumper.ContactSensor 는 Update 헨들러를통해전달됨 // 전달받은센서의상태값을 state 변수에저장함 [ServiceHandler(ServiceHandlerBehavior.Exclusive)]

public virtual IEnumerator<ITask> UpdateHandler(bumper.Update update)

{ _state = update.Body;

// 구독관리자에값을전달함 SendNotification<bumper.Update>(_submgr, _state);

update.ResponsePort.Post(DefaultUpdateResponseType.Instance);

yield break;

}

// 구독기능을위해기본적으로항상추가되어야하는모듈임 [ServiceHandler(ServiceHandlerBehavior.Concurrent)]

public virtual IEnumerator<ITask> SubscribeHandler(bumper.Subscribe subscribe)

{ SubscribeHelper(_submgr, subscribe.Body, subscribe.ResponsePort);

yield break;

}

}}

Page 55: Microsoft Robotics Developer Studio 고급 프로그래밍 과정 [Part 5] CCR  및  DSS  서비스 프로그래밍

55Microsoft Robotics Studio

Bumper 서비스 테스트

과제 VPL 에서 Bumper 서비스가 넘겨 주는 값을 확인해 보기 바람

Page 56: Microsoft Robotics Developer Studio 고급 프로그래밍 과정 [Part 5] CCR  및  DSS  서비스 프로그래밍

56Microsoft Robotics Studio

Motor 서비스 구현하기 #1

using Microsoft.Ccr.Core;using Microsoft.Dss.Core;using Microsoft.Dss.Core.Attributes;using Microsoft.Dss.ServiceModel.Dssp;using Microsoft.Dss.ServiceModel.DsspServiceBase;using System;using System.Collections.Generic;using System.ComponentModel;using System.Xml;using myfirstbrick = MyFirstBrick;

using drive = Microsoft.Robotics.Services.Drive.Proxy;using bumper = Microsoft.Robotics.Services.ContactSensor.Proxy;using motor = Microsoft.Robotics.Services.Motor.Proxy;using submgr = Microsoft.Dss.Services.SubscriptionManager;

Page 57: Microsoft Robotics Developer Studio 고급 프로그래밍 과정 [Part 5] CCR  및  DSS  서비스 프로그래밍

57Microsoft Robotics Studio

Motor 서비스 구현하기 #2

namespace MyFirstBrickMotor{ public sealed class Contract { public const String Identifier = "http://schemas.tempuri.org/2007/10/myfirstbrickmotor.html"; }

[DisplayName("MyFirstBrickMotor")] [Description("The MyFirstBrickMotor Service")] [Contract(Contract.Identifier)] [AlternateContract(motor.Contract.Identifier)] public class MyFirstMotorService : DsspServiceBase { private motor.SetMotorPower _state = new motor.SetMotorPower();

[ServicePort("/myfirstbrickmotor", AllowMultipleInstances = false)] private motor.MotorOperations _mainPort = new motor.MotorOperations();

//Brick 서비스에데이터를전달하기위해 Brick 서비스의 mainport 를사용함 //Brick 서비스에데이터를전달하기위해서는단순히아해포트에데이터를 Post 하기만하면됨

//[Partner("MyFirstBrick", Contract = myfirstbrick.Contract.Identifier, CreationPolicy = PartnerCreationPolicy.UseExistingOrCreate)]

//private myfirstbrick.MyFirstBrickOperations _brickPort = new myfirstbrick.MyFirstBrickOperations();

Page 58: Microsoft Robotics Developer Studio 고급 프로그래밍 과정 [Part 5] CCR  및  DSS  서비스 프로그래밍

58Microsoft Robotics Studio

Motor 서비스 구현하기 #3

public MyFirstMotorService(DsspServiceCreationPort creationPort) : base(creationPort) { }

protected override void Start() { base.Start(); }

[ServiceHandler(ServiceHandlerBehavior.Exclusive)] public virtual IEnumerator<ITask> UpdateHandler(motor.SetMotorPower update) { LogInfo(LogGroups.Console, "[[[Motor 서비스 ]]] " + update.Body.TargetPower.ToString());

//Motor 값을수신하였으면 , 해당값을 Brick 서비스로전달함 //_brickPort.Post(new MyFirstBrick.UpdateMotor(update.Body));

update.ResponsePort.Post(DefaultUpdateResponseType.Instance); yield break; } }}

Page 59: Microsoft Robotics Developer Studio 고급 프로그래밍 과정 [Part 5] CCR  및  DSS  서비스 프로그래밍

59Microsoft Robotics Studio

Motor 서비스 테스트

과제 VPL 에서 모터 서비스에 값을 넘겨 주고 결과를 확인 바람

Page 60: Microsoft Robotics Developer Studio 고급 프로그래밍 과정 [Part 5] CCR  및  DSS  서비스 프로그래밍

60Microsoft Robotics Studio

Drive 서비스 구현하기 #1

using Microsoft.Ccr.Core;using Microsoft.Dss.Core;using Microsoft.Dss.Core.Attributes;using Microsoft.Dss.ServiceModel.Dssp;using Microsoft.Dss.ServiceModel.DsspServiceBase;using System;using System.Collections.Generic;using System.ComponentModel;using System.Xml;using myfirstbrick = MyFirstBrick;

using drive = Microsoft.Robotics.Services.Drive.Proxy;using bumper = Microsoft.Robotics.Services.ContactSensor.Proxy;using motor = Microsoft.Robotics.Services.Motor.Proxy;using submgr = Microsoft.Dss.Services.SubscriptionManager;

Page 61: Microsoft Robotics Developer Studio 고급 프로그래밍 과정 [Part 5] CCR  및  DSS  서비스 프로그래밍

61Microsoft Robotics Studio

Drive 서비스 구현하기 #2

namespace MyFirstBrickDrive{ public sealed class Contract { public const String Identifier = "http://schemas.tempuri.org/2007/10/myfirstbrickdrive.html"; }

[DisplayName("MyFirstBrickDrive")] [Description("The MyFirstBrickDrive Service")] [Contract(Contract.Identifier)] [AlternateContract(drive.Contract.Identifier)] public class MyFirstBrickDriveService : DsspServiceBase { [ServicePort("/myfirstbrickdrive", AllowMultipleInstances = false)] private drive.DriveOperations _mainPort = new drive.DriveOperations();

//Brick 서비스에데이터를전달하기위해 Brick 서비스의 mainport 를사용함 //Brick 서비스에데이터를전달하기위해서는단순히아해포트에데이터를 Post 하기만하면됨

//[Partner("MyFirstBrick", Contract = myfirstbrick.Contract.Identifier, CreationPolicy = PartnerCreationPolicy.UseExistingOrCreate)]

//private myfirstbrick.MyFirstBrickOperations _brickPort = new myfirstbrick.MyFirstBrickOperations();

Page 62: Microsoft Robotics Developer Studio 고급 프로그래밍 과정 [Part 5] CCR  및  DSS  서비스 프로그래밍

62Microsoft Robotics Studio

Drive 서비스 구현하기 #3

public MyFirstBrickDriveService(DsspServiceCreationPort creationPort) : base(creationPort) { }

protected override void Start() { base.Start(); }

[ServiceHandler(ServiceHandlerBehavior.Exclusive)] public virtual IEnumerator<ITask> UpdateHandler(drive.SetDrivePower update) { LogInfo(LogGroups.Console, "[[[Drive 서비스 ]]] " + update.Body.LeftWheelPower.ToString() + " " +

update.Body.RightWheelPower.ToString());

//Drive 값을수신하였으면 , 해당값을 Brick 서비스로전달함 //_brickPort.Post(new MyFirstBrick.UpdateDrive(update.Body));

update.ResponsePort.Post(DefaultUpdateResponseType.Instance); yield break; } }}

Page 63: Microsoft Robotics Developer Studio 고급 프로그래밍 과정 [Part 5] CCR  및  DSS  서비스 프로그래밍

63Microsoft Robotics Studio

Drive 서비스 테스트

과제 VPL 에서 Drive 서비스에 값을 넘겨 주고 결과를 확인 바람

Page 64: Microsoft Robotics Developer Studio 고급 프로그래밍 과정 [Part 5] CCR  및  DSS  서비스 프로그래밍

64Microsoft Robotics Studio

로봇 연결 서비스 개발

Page 65: Microsoft Robotics Developer Studio 고급 프로그래밍 과정 [Part 5] CCR  및  DSS  서비스 프로그래밍

65Microsoft Robotics Studio

로봇 연결 서비스

유형 1 유형 2

Page 66: Microsoft Robotics Developer Studio 고급 프로그래밍 과정 [Part 5] CCR  및  DSS  서비스 프로그래밍

66Microsoft Robotics Studio

로봇 연결 서비스 #1

using Microsoft.Ccr.Core;using Microsoft.Dss.Core;using Microsoft.Dss.Core.Attributes;using Microsoft.Dss.ServiceModel.Dssp;using Microsoft.Dss.ServiceModel.DsspServiceBase;using System;using System.Collections.Generic;using System.ComponentModel;using System.Xml;using myfirstbrick = MyFirstBrick;

using drive = Microsoft.Robotics.Services.Drive.Proxy;using bumper = Microsoft.Robotics.Services.ContactSensor.Proxy;using motor = Microsoft.Robotics.Services.Motor.Proxy;using submgr = Microsoft.Dss.Services.SubscriptionManager;

Page 67: Microsoft Robotics Developer Studio 고급 프로그래밍 과정 [Part 5] CCR  및  DSS  서비스 프로그래밍

67Microsoft Robotics Studio

로봇 연결 서비스 #2

namespace MyFirstBrick

{

[DisplayName("MyFirstBrick")]

[Description("The MyFirstBrick Service")]

[Contract(Contract.Identifier)]

public class MyFirstBrickService : DsspServiceBase

{ private MyFirstBrickState _state = new MyFirstBrickState();

[ServicePort("/myfirstbrick", AllowMultipleInstances = false)]

private MyFirstBrickOperations _mainPort = new MyFirstBrickOperations();

//Bumber 서비스에데이터를전달하기위해서는대상서비스를사전에파트너로지정해서오픈시켜야한다 .

[Partner("MyFirstBrickBumper", Contract = MyFirstBrickBumper.Contract.Identifier, CreationPolicy = PartnerCreationPolicy.UseExistingOrCreate)]

private bumper.ContactSensorArrayOperations _brickBumperPort = new bumper.ContactSensorArrayOperations();

//Bumber 데이터를자동으로생성하기위해타이머포트정의 ( 임시로정의한것임 )

private Port<DateTime> _timerPort = new Port<DateTime>();

public MyFirstBrickService(DsspServiceCreationPort creationPort)

: base(creationPort)

{ }

protected override void Start()

{ base.Start();

//Bumper 데이터를 3 초간격으로자동으로생성하기위해추가한코드임 _timerPort.Post(DateTime.Now);

Activate(Arbiter.Receive(true, _timerPort, TimerHandler));

}

Page 68: Microsoft Robotics Developer Studio 고급 프로그래밍 과정 [Part 5] CCR  및  DSS  서비스 프로그래밍

68Microsoft Robotics Studio

로봇 연결 서비스 #3

// 이곳에서 Bumper 데이터를생성함 void TimerHandler(DateTime signal)

{ //Bumper 신호를가상으로생성함 bumper.ContactSensor _newSensor = new bumper.ContactSensor();

_newSensor.HardwareIdentifier = 1;

_newSensor.Name = "front";

_newSensor.Pressed = true;

_brickBumperPort.Post(new bumper.Update(_newSensor));

// 타이머를다시호출함 Activate(

Arbiter.Receive(false, TimeoutPort(3000), //3 초간격 delegate(DateTime time)

{ _timerPort.Post(time);

} ) ); }

[ServiceHandler(ServiceHandlerBehavior.Exclusive)]

public virtual IEnumerator<ITask> UpdateHandler(UpdateDrive update)

{ LogInfo(LogGroups.Console, "[[[Brick Drive 서비스 ]]] " + update.Body.LeftWheelPower.ToString() + " " + update.Body.RightWheelPower.ToString());

update.ResponsePort.Post(DefaultUpdateResponseType.Instance);

yield break;

}

Page 69: Microsoft Robotics Developer Studio 고급 프로그래밍 과정 [Part 5] CCR  및  DSS  서비스 프로그래밍

69Microsoft Robotics Studio

로봇 연결 서비스 #4

[ServiceHandler(ServiceHandlerBehavior.Exclusive)]

public virtual IEnumerator<ITask> UpdateHandler(UpdateMotor update)

{ LogInfo(LogGroups.Console, "[[[Brick Motor 서비스 ]]] " + update.Body.TargetPower.ToString());

update.ResponsePort.Post(DefaultUpdateResponseType.Instance);

yield break;

} }}

Page 70: Microsoft Robotics Developer Studio 고급 프로그래밍 과정 [Part 5] CCR  및  DSS  서비스 프로그래밍

70Microsoft Robotics Studio

Brick 서비스 테스트

과제 VPL 에서 Brick 서비스를 활용하는 예를 구현 바람

Page 71: Microsoft Robotics Developer Studio 고급 프로그래밍 과정 [Part 5] CCR  및  DSS  서비스 프로그래밍

71Microsoft Robotics Studio

UI 를 추가하는 방법

UI 와 서비스 간의 통신 유형 서비스 -> UI UI -> 서비스

실습 목적 화면을 생성하고 범퍼 데이터를 생성하는 UI 설계 모터서비스로 부터 모터 값을 받은 후 화면에 표시 드라이브 서비스로 부터 드라이브 값을 받은 후 화면에 표시

UI 추가 방법 C# 에서 Add-> New Item 선택 후 WinForm 추가

Page 72: Microsoft Robotics Developer Studio 고급 프로그래밍 과정 [Part 5] CCR  및  DSS  서비스 프로그래밍

72Microsoft Robotics Studio

UI 추가 코드 #1

using Microsoft.Ccr.Core;using Microsoft.Dss.Core;using Microsoft.Dss.Core.Attributes;using Microsoft.Dss.ServiceModel.Dssp;using Microsoft.Dss.ServiceModel.DsspServiceBase;using System;using System.Collections.Generic;using System.ComponentModel;using System.Xml;using W3C.Soap;

using System.Windows.Forms;using Microsoft.Ccr.Adapters.WinForms;using submgr = Microsoft.Dss.Services.SubscriptionManager;

Page 73: Microsoft Robotics Developer Studio 고급 프로그래밍 과정 [Part 5] CCR  및  DSS  서비스 프로그래밍

73Microsoft Robotics Studio

UI 추가 코드 #2

namespace MyApp1

{

[DisplayName("MyApp1")]

[Description("The MyApp1 Service")]

[Contract(Contract.Identifier)]

public class MyApp1Service : DsspServiceBase

{

private MyApp1State _state = new MyApp1State();

[ServicePort("/myapp1", AllowMultipleInstances=false)]

private MyApp1Operations _mainPort = new MyApp1Operations();

[Partner("SubMgr", Contract = submgr.Contract.Identifier, CreationPolicy = PartnerCreationPolicy.CreateAlways)]

private submgr.SubscriptionManagerPort _subMgrPort = new submgr.SubscriptionManagerPort();

public MyApp1Service(DsspServiceCreationPort creationPort) :

base(creationPort)

{ }

Form1 App1Form = null;

protected override void Start()

{ base.Start();

WinFormsServicePort.Post(new RunForm(CreateAppForm));

}

Page 74: Microsoft Robotics Developer Studio 고급 프로그래밍 과정 [Part 5] CCR  및  DSS  서비스 프로그래밍

74Microsoft Robotics Studio

UI 추가 코드 #3

Form1 _form;

Form CreateAppForm()

{ // 만약값을공유하는클래스가있다면 , 해당클래스도같이넘겨줄수있음 //_form = new Form1(_mainPort, _state);

_form = new Form1(_mainPort);

return _form;

}

[ServiceHandler(ServiceHandlerBehavior.Concurrent)]

public virtual IEnumerator<ITask> GetHandler(Get get)

{ get.ResponsePort.Post(_state);

yield break;

}

[ServiceHandler(ServiceHandlerBehavior.Exclusive)]

public virtual IEnumerator<ITask> UpdateHandler(Update update)

{ LogInfo(LogGroups.Console, update.Body.CustName);

SendNotification<Update>(_subMgrPort, update.Body);

//update.ResponsePort.Post(DefaultUpdateResponseType.Instance);

yield break;

}

[ServiceHandler(ServiceHandlerBehavior.Concurrent)]

public IEnumerator<ITask> SubscribeHandler(Subscribe subscribe)

{ SubscribeHelper(_subMgrPort, subscribe.Body, subscribe.ResponsePort);

yield break;

} }}

Page 75: Microsoft Robotics Developer Studio 고급 프로그래밍 과정 [Part 5] CCR  및  DSS  서비스 프로그래밍

75Microsoft Robotics Studio

UI 추가 코드 #4

namespace MyApp1

{

public partial class Form1 : Form

{ private MyApp1Operations _mainPort;

public Form1(MyApp1Operations mainPort)

{ InitializeComponent();

_mainPort = mainPort;

}

private void button1_Click(object sender, EventArgs e)

{ MyApp1State _state = new MyApp1State();

_state.CustNo = textBox1.Text;

_state.CustName = textBox2.Text;

_state.OrderQty = textBox3.Text;

_state.Cost = textBox4.Text;

_mainPort.Post(new Update(_state));

} }}

Page 76: Microsoft Robotics Developer Studio 고급 프로그래밍 과정 [Part 5] CCR  및  DSS  서비스 프로그래밍

76Microsoft Robotics Studio

UI 추가 코드 테스트

과제 이전의 UI 추가 패턴을 Brick 서비스의 범퍼 데이터 생성에 적용

Page 77: Microsoft Robotics Developer Studio 고급 프로그래밍 과정 [Part 5] CCR  및  DSS  서비스 프로그래밍

77Microsoft Robotics Studio

값을 표시하는 UI 작업 #1

서비스에 아래 코드 추가

[ServiceHandler(ServiceHandlerBehavior.Exclusive)] public virtual IEnumerator<ITask> UpdateHandler(Update update) { WinFormsServicePort.FormInvoke( delegate() { _form.ShowData(update.Body); } );

update.ResponsePort.Post(DefaultUpdateResponseType.Instance); yield break; }

Page 78: Microsoft Robotics Developer Studio 고급 프로그래밍 과정 [Part 5] CCR  및  DSS  서비스 프로그래밍

78Microsoft Robotics Studio

값을 표시하는 UI 작업 #2

UI 에 아래 코드 추가

namespace MyApp2{ public partial class Form1 : Form { public Form1() { InitializeComponent(); }

public void ShowData(MyApp2State _state) { textBox1.Text = _state.CustNo; textBox2.Text = _state.CustName; } }}

Page 79: Microsoft Robotics Developer Studio 고급 프로그래밍 과정 [Part 5] CCR  및  DSS  서비스 프로그래밍

79Microsoft Robotics Studio

UI 추가 코드 테스트

과제 이전의 UI 추가 패턴을 Brick 서비스의 모터와 드라이브 서비스 데이터

표시에 적용

Page 80: Microsoft Robotics Developer Studio 고급 프로그래밍 과정 [Part 5] CCR  및  DSS  서비스 프로그래밍

Microsoft Robotics Developer Studio

고급 프로그래밍 과정

[Part 7] 지능형 서비스 프로그래밍

2008로보틱스 그룹

마이크로소프트

김 영 준 수석[email protected]

Page 81: Microsoft Robotics Developer Studio 고급 프로그래밍 과정 [Part 5] CCR  및  DSS  서비스 프로그래밍

81Microsoft Robotics Studio

지능형 서비스 개발

Page 82: Microsoft Robotics Developer Studio 고급 프로그래밍 과정 [Part 5] CCR  및  DSS  서비스 프로그래밍

82Microsoft Robotics Studio

TTS 기능 이용하기

VPL 에서 TTS 기능 이용하기

Page 83: Microsoft Robotics Developer Studio 고급 프로그래밍 과정 [Part 5] CCR  및  DSS  서비스 프로그래밍

83Microsoft Robotics Studio

음성인식 이용하기

VPL 에서 음성인식 기능 이용하기

Page 84: Microsoft Robotics Developer Studio 고급 프로그래밍 과정 [Part 5] CCR  및  DSS  서비스 프로그래밍

84Microsoft Robotics Studio

간단한 비전처리 구현하기

VPL 에서 제스쳐 인식 결과 이용하기

Page 85: Microsoft Robotics Developer Studio 고급 프로그래밍 과정 [Part 5] CCR  및  DSS  서비스 프로그래밍

85Microsoft Robotics Studio

오늘의 날씨정보 표시하기 #1

using Microsoft.Ccr.Core;

using Microsoft.Dss.Core;

using Microsoft.Dss.Core.Attributes;

using Microsoft.Dss.ServiceModel.Dssp;

using Microsoft.Dss.ServiceModel.DsspServiceBase;

using System;

using System.Collections.Generic;

using System.ComponentModel;

using System.Xml;

using System.Net;

using System.IO;

using System.Text;

using W3C.Soap;

using googleweather = GoogleWeather;

Page 86: Microsoft Robotics Developer Studio 고급 프로그래밍 과정 [Part 5] CCR  및  DSS  서비스 프로그래밍

86Microsoft Robotics Studio

오늘의 날씨정보 표시하기 #2

namespace GoogleWeather.Today

{

[DisplayName("Google Today Weather")]

[Description("Google Today Weather")]

[Contract(Contract.Identifier)]

public class TodayWeatherService : DsspServiceBase

{ private TodayWeatherState _state = new TodayWeatherState();

[ServicePort("/googletodayweather", AllowMultipleInstances=false)]

private TodayWeatherOperations _mainPort = new TodayWeatherOperations();

public TodayWeatherService(DsspServiceCreationPort creationPort)

: base(creationPort)

{ }

protected override void Start()

{base.Start();

}

private const string _googleUrl = "http://www.google.co.kr";

Page 87: Microsoft Robotics Developer Studio 고급 프로그래밍 과정 [Part 5] CCR  및  DSS  서비스 프로그래밍

87Microsoft Robotics Studio

오늘의 날씨정보 표시하기 #3

[ServiceHandler(ServiceHandlerBehavior.Concurrent)]

public virtual IEnumerator<ITask> GetHandler(Get get)

{ if (get.Body.CityName != "")

{ GetTodayWeather(_googleUrl + "/ig/api?weather=" + get.Body.CityName, get.Body.CityName);

} else

GetTodayWeather("", "");

get.ResponsePort.Post(_state);

yield break;

}

Page 88: Microsoft Robotics Developer Studio 고급 프로그래밍 과정 [Part 5] CCR  및  DSS  서비스 프로그래밍

88Microsoft Robotics Studio

오늘의 날씨정보 표시하기 #4

private void GetTodayWeather(string strCityUrl, string cityName)

{ try

{ XmlDocument xmlDoc = new XmlDocument();

if (strCityUrl != "")

{ WebClient myWebClient = new WebClient();

Stream myStream = myWebClient.OpenRead(strCityUrl);

StreamReader sr = new StreamReader(myStream, Encoding.Default);

xmlDoc.Load(sr);

sr.Close();

sr.Dispose();

myStream.Close();

myStream.Dispose();

} else

{ xmlDoc.Load(@"C:\Microsoft Robotics Studio (1.5)\googleweather.xml");

}

XmlNodeList xWeatherNodeList = xmlDoc.SelectNodes("xml_api_reply/weather/forecast_conditions");

Page 89: Microsoft Robotics Developer Studio 고급 프로그래밍 과정 [Part 5] CCR  및  DSS  서비스 프로그래밍

89Microsoft Robotics Studio

오늘의 날씨정보 표시하기 #5

//for (int i = 0; i < xWeatherNodeList.Count; i++) for (int i = 0; i < 1; i++) //1: Today { _state.DayOfWeek = xWeatherNodeList.Item(i).SelectSingleNode("day_of_week").Attributes["data"].Value; _state.Low = xWeatherNodeList.Item(i).SelectSingleNode("low").Attributes["data"].Value; _state.High = xWeatherNodeList.Item(i).SelectSingleNode("high").Attributes["data"].Value; _state.IconPath = xWeatherNodeList.Item(i).SelectSingleNode("icon").Attributes["data"].Value; _state.TodayCondition = xWeatherNodeList.Item(i).SelectSingleNode("condition").Attributes["data"].Value;

_state.WeatherText = _state.DayOfWeek+" " + cityName+" 의날씨는 " + _state.TodayCondition+" 입니다 . "; _state.WeatherText = _state.WeatherText + " 낮최저기온은 " + _state.Low + " 도이고 , "; _state.WeatherText = _state.WeatherText + " 낮최고기온은 " + _state.High + " 도입니다 . "; }

XmlNode xWeatherNode = xmlDoc.SelectSingleNode("xml_api_reply/weather/current_conditions");

if (xWeatherNode != null) { _state.CurrentCondition = xWeatherNode.SelectSingleNode("condition").Attributes["data"].Value; _state.CurrentTempF = xWeatherNode.SelectSingleNode("temp_f").Attributes["data"].Value; _state.CurrentTempC = xWeatherNode.SelectSingleNode("temp_c").Attributes["data"].Value; _state.CurrentHumidity = xWeatherNode.SelectSingleNode("humidity").Attributes["data"].Value; _state.CurrentWind = xWeatherNode.SelectSingleNode("wind_condition").Attributes["data"].Value;

_state.WeatherText = _state.WeatherText + " 현재시각의날씨는 " + _state.CurrentCondition + " 이며 , "; _state.WeatherText = _state.WeatherText + " 기온은 " + _state.CurrentTempC + " 도이고 , "; _state.WeatherText = _state.WeatherText + " 그리고 " + _state.CurrentHumidity + " 이며 , "; _state.WeatherText = _state.WeatherText + _state.CurrentWind + " 입니다 . "; }

xmlDoc = null; } catch { // }

Page 90: Microsoft Robotics Developer Studio 고급 프로그래밍 과정 [Part 5] CCR  및  DSS  서비스 프로그래밍

90Microsoft Robotics Studio

오늘의 날씨정보 표시하기 #6

finally

{ // } } }

public sealed class Contract

{ public const String Identifier = "http://schemas.tempuri.org/2007/11/googletodayweather.html";

}

[DataContract()]

public class TodayWeatherState

{ [DataMember(IsRequired = false)]

public String DayOfWeek;

[DataMember(IsRequired = false)]

public String Low;

[DataMember(IsRequired = false)]

public String High;

[DataMember(IsRequired = false)]

public String IconPath;

[DataMember(IsRequired = false)]

public String TodayCondition;

[DataMember(IsRequired = false)]

public String CurrentCondition;

Page 91: Microsoft Robotics Developer Studio 고급 프로그래밍 과정 [Part 5] CCR  및  DSS  서비스 프로그래밍

91Microsoft Robotics Studio

오늘의 날씨정보 표시하기 #7

[DataMember(IsRequired = false)]

public String CurrentTempF;

[DataMember(IsRequired = false)]

public String CurrentTempC;

[DataMember(IsRequired = false)]

public String CurrentHumidity;

[DataMember(IsRequired = false)]

public String CurrentWind;

[DataMember(IsRequired = false)]

public String WeatherText;

}

[ServicePort()]

public class TodayWeatherOperations : PortSet<DsspDefaultLookup, DsspDefaultDrop, Get>

{ }

[DataContract]

public class GetWeatherRequest

{ [DataMember]

public String CityName;

}

Page 92: Microsoft Robotics Developer Studio 고급 프로그래밍 과정 [Part 5] CCR  및  DSS  서비스 프로그래밍

92Microsoft Robotics Studio

오늘의 날씨정보 표시하기 #8

public class Get : Get<GetWeatherRequest, PortSet<TodayWeatherState, Fault>>

{ public Get()

{ }

public Get(GetWeatherRequest body)

: base(body)

{ }

public Get(GetWeatherRequest body, Microsoft.Ccr.Core.PortSet<TodayWeatherState, W3C.Soap.Fault> responsePort)

: base(body, responsePort)

{ } }}

Page 93: Microsoft Robotics Developer Studio 고급 프로그래밍 과정 [Part 5] CCR  및  DSS  서비스 프로그래밍

93Microsoft Robotics Studio

VPL 을 통한 오늘의 날씨 이용하기

VPL 에서 서울의 날씨 정보를 읽어 오기

과제 날씨 정보를 TTS 에 연결하기