CHOU

[MSRDS] Robot Service - BumperSensor_2 본문

Tech/Microsoft Products

[MSRDS] Robot Service - BumperSensor_2

chobabo 2009. 4. 10. 18:23


MSRDS 서비스는 크게 4가지 구성 요소를 가지게 됩니다.

1) 주고 받는 메세지 클래스

프로젝트 이름 뒤에 state 가 붙어있는 클래스로 정의가 됩니다. 프로젝트명types.cs 에 선언되어 있습니다.

    [DataContract]
    public class testBumperServiceState
    {
    }

2) 메세지를 받을 포트들의 모음 (포트 셋)

프로젝트명types.cs 에 선언되어 있습니다.

    [ServicePort]
    public class testBumperServiceOperations : PortSet<DsspDefaultLookup, DsspDefaultDrop, Get, Subscribe>
    {
    }

3) 개별 메세지를 받아 들이는 포트

프로젝트명types.cs 에 선언되어 있습니다.

    public class Get : Get<GetRequestType, PortSet<testBumperServiceState, Fault>>
    {
        public Get()
        {
        }

        public Get(GetRequestType body)
            : base(body)
        {
        }

        public Get(GetRequestType body, PortSet<testBumperServiceState, Fault> responsePort)
            : base(body, responsePort)
        {
        }
    }

1-3 까지의 코드는 MSRDS에서 미리 정의를 해 놓았기 때문에 반복해서 정의할 필요가 없습니다. 이러한 공동 모듈은 Robotics.Common.proxy.dll 파일에 담아서 제공을 합니다.


4) 메시지를 처리하는 핸들러

 1부터 3까지는 프로젝트명types.cs 파일에서 정의되고 4번은 프로젝트명.cs에서 정의 됩니다. 여기서 개발자가 원하는 방향에 맞게 핸들러를 정의해주면 됩니다.


그럼 오늘도 역시 네이버 MSRDS 카페( http://cafe.naver.com/msrskorea )에 김영준 수석님께서 올려주신 자료를 따라해 보면서 범퍼 서비스에 대해 이해해 보겠습니다. 하드웨어가 없기 때문에 타이머를 이용해서 간단하게 범퍼 서비스가 작동 되는 모습만 디버그 화면으로 보도록 하겠습니다.

1. C# DSS프로젝트를 생성합니다. 이때, 자신의 MSRDS설치폴더 아래 Sample 폴더 아래 파일을 저장해 줍니다.





오케이를 누르면 아래와 같은 화면이 뜨는데 우선은 그냥 오케이 하면 됩니다.







2. RoboticsCommon.proxy.dll 을 레퍼런스에 추가해 줍니다.





우리가 이용할 범퍼 서비스가 정의되어 있는 dll 파일을 추가해 줘야 합니다.



3. 프로젝트를 생성했다면 프로젝트명types.cs 에서 쓸데 없는 주석을 제거해 주고 아래와 같이 코드를 변경해 줍니다.


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

//add code
using bumper = Microsoft.Robotics.Services.ContactSensor.Proxy;

namespace testBumperService
{
    public sealed class Contract
    {
        [DataMember]
        public const string Identifier = "http://schemas.tempuri.org/2009/04/testbumperservice.html";
    }
}



빨간 부분만 유의해서 추가해 주시면 됩니다.



4. 프로젝트명.cs 코드를 아래와 같이 수정해 줍니다.


using System;
using System.Collections.Generic;
using System.ComponentModel;
using Microsoft.Ccr.Core;

//add code
using Microsoft.Dss.Core;

using Microsoft.Dss.Core.Attributes;
using Microsoft.Dss.ServiceModel.Dssp;
using Microsoft.Dss.ServiceModel.DsspServiceBase;
using W3C.Soap;
using submgr = Microsoft.Dss.Services.SubscriptionManager;

//add code
using System.Xml;
using bumper = Microsoft.Robotics.Services.ContactSensor.Proxy;

namespace testBumperService
{
    [Contract(Contract.Identifier)]
    [DisplayName("testBumperService")]
    [Description("testBumperService service (no description provided)")]

    //add code
    [AlternateContract(bumper.Contract.Identifier)]
--> 이부분에서 항상 인터페이스의 스키마를 같은 형태로 일치 시키게 됩니다. 어떠한 로봇이든 항상 범퍼 서비스라는 것을 인식하기 위해 선언해 주는 겁니다.

    class testBumperService : DsspServiceBase
    {
        //add code
        private bumper.ContactSensor _state = new bumper.ContactSensor();
 
        //AllowMultipleInstances = true -> false
        [ServicePort("/testBumperService", AllowMultipleInstances = false)]

        //add code
        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> _TimePort = new Port<DateTime>();

        //testBumperServiceOperations _mainPort = new testBumperServiceOperations();

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

        protected override void Start()
        {

            base.Start();

            //타이머 최초 구동명령
            _TimePort.Post(DateTime.Now);
            Activate(Arbiter.Receive(true, _TimePort,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),
                    delegate(DateTime time)
                    {
                        _TimePort.Post(time);
                    }

                )
            );

        }

        [ServiceHandler(ServiceHandlerBehavior.Concurrent)]
        public virtual IEnumerator<ITask> SubscribeHandler(bumper.Subscribe subscribe)
        {
            SubscribeHelper(_submgr, subscribe.Body, subscribe.ResponsePort);
            yield break;
        }
    }
}



우선 주석을 제거하고 코드를 추가, 수정해 주시는게 편합니다. 예제 파일을 잘 따라해서 컴파일 해보면 에러없이 잘 컴파일 결과가 나옵니다^^.



5. VPL 프로그램을 실행 시켜서 한번 테스트 해보겠습니다.


서비스 목록에서 자신이 만든 프로젝트명이 보이면 성공입니다.




연결을 한 다음 다음과 같이 설정해 줍니다.






오케이를 누르면 다음의 선택이 나오는데 name 을 골라주면 됩니다.







다음 시간에는 모터 서비스를 연결해 보는 것을 연습해 보겠습니다. 예제를 따라해보니까 어느정도 감이 오는거 같습니다^^.
빨리 배워서 로봇에 적용해 보고 싶군요 ㅋㅋㅋ.


참고자료

1. http://cafe.naver.com/msrskorea
MSRDS 네이버 공식 카페

2.  예제 코드 파일