Blog | Tag | Local | Guest | Login | Write |  RSS
2008/12/09에 해당되는 글 2건
2008.12.09 :: Dot Font Generator 1

그동안 VPL만 주구장창 했군요.-_-;;;

정작 로봇은 보여드리지도 않고...;;

-_-;;




오늘은 로봇을 직접 조종할 수 있는 시뮬레이션 모드에 대해서 설명하겠습니다.

레고 마인드스톰 NXT로봇을 조종할 수 있게 하도록합니다.

음..

만들어져 있는 로봇을 시뮬레이션 하는 것은 쉽습니다.

먼저 VPL을 실행시키고 Diagram에 Simple Dashboard 와 Simulated Generic Differential Drive Activity를 추가합니다.

그 둘을 연결시킬 필요는 없습니다. 다만 SimulatedGenericDifferentialDrive Activity의 Config 정보만 수정하여주면 됩니다.


정보를 수정하기 위해  SimulatedGenericDifferentialDrive Activity를 클릭하여 주시고 화면 오른쪽에 보시면 Properities 창이 보일겁니다.

거기에서 두번째 항목인 Configuration을 보시면 선택가능한 항목들이 있는데 거기서 Use a manifest를 선택합니다.

선택하시면 아래에 Manifest를 선택할 수 있는 콤보박스가 생성됩니다.



Properities에서 import 버튼을 클릭하면 SimulatedGenericDifferentialDrive을 지원하는 서비스 목록들이 표시되는데, 거기에서 LEGO.NXT.Tribot.Simulation.manifest.xml을 선택합니다.



그러면 VPL에서 더 이상 선택할 것은 없습니다.

그리고 실행을 시켜줍니다. 그러면 윈도우 창이 두 개 뜰겁니다.

하나는 Simpledashboard가 실행된 화면이고, 하나는 시뮬레이션 실행화면입니다.

시뮬레이션 실행 화면에 보시면 LEGO NXT Tribot이 보일겁니다.




SimpleDashboard에서 시뮬레이션 로봇에 연결하고 제어해야 합니다. 그러기 위해서는 오른쪽 상단에 있는 Machine : 입력박스에 "localhost"를 입력하고 Connect합니다.



그러면 아래의 Sevice Directory 아래에 (LegoNXTMotorBase) /simulated... 라고 표시 된 항목이 추가 됩니다.


그 생성된 항목을 더블클릭하시면, 왼쪽 Differential Drive에 있는 Motor : 부분이 Motor : On 으로 변경됩니다.



그리고 그 윗 부분의 Drive 버튼을 클릭하고, 그 상태에서 위의 동그라미의 십자선 표시 그 부분이 조이스틱 역할을 하는데 그 것을 마우스로 클릭하며 움직여 보시면, 로봇이 시뮬레이션 화면 안에서 원하는 움직임 대로 움직이는 것을 볼 수 있습니다.


움직여서 장애물 옆으로 옮겨간 모습입니다.


카메라 화면 시점을 움직이고 싶으시면, 시뮬레이션 화면을 클릭하시고 마우스로 옮기면 상하좌우로 회전하고, 키보드의 화살표 키를 누르시면 앞뒤옆 등으로 움직입니다.

단순히 Activity 두 개만을 추가해서 이렇게 로봇을 시뮬레이션 상에서 제어 가능한데, 물론 LEGO NXT 말고도 다른 기본적으로 제공하는 로봇들을 제어가능합니다.




Dot Font Generator

안녕하세요. 이번시간에는 TextBlock에 표시되는 글자를 Pixel단위로 쪼개어 Dot Font로 활용하는 방법에 대해서 소개해 드리겠습니다. 방법이야 여러가지가 있겠지만 저는 RenderTargetBitmp을 사용해 텍스트의 이미지를 생성하고 해당 이미지를 MemoryStream으로 복사 한 뒤 픽셀 단위로 문자열에 해당하는 부분을 검출하는 방법을 사용했습니다. 아래는 시연동영상입니다.



Generate Text에 변환할 문자를 입력하고 적당히 Spacing 을 조절한 뒤 Generate 버튼을 누르면 변환이 이루어집니다. Result 부분에는 변환된 점의 좌표가 출력되면 Preview에는 해당 점을 직접 그렸을 경우 미리보기가 가능합니다. 소스코드는 아래와 같습니다. 이번 예제에서의 XAML은 대부분 UI구성과 관련된 내용만 포함 하고 있으므로 설명은 하지 않고 C#코드에서 실제 Dot Font를 생성하는 부분만 설명을 하도록 하겠습니다. (전체 소스코드는 첨부하도록 하겠습니다.)

아래는 C#코드입니다.

  1. public partial class Window1 : Window   
  2. {   
  3.     public Window1()   
  4.     {   
  5.         InitializeComponent();   
  6.     }   
  7.   
  8.     private void BtnGenerate_Click(object sender, RoutedEventArgs e)   
  9.     {   
  10.   
  11.         ResultTextBlock.Text = TxtText.Text;   
  12.         List<POINT> Result = GenerateDotFont(ResultTextBlock, (int)SliderSpacing.Value);   
  13.         DrawDotFont(Result);   
  14.         LstResult.ItemsSource = Result;   
  15.               
  16.     }   
  17.   
  18.     public void DrawDotFont(List<POINT> DotFont)   
  19.     {   
  20.   
  21.         DrawingVisual DrawingVisual = new DrawingVisual();   
  22.         DrawingContext DrawingContext = DrawingVisual.RenderOpen();   
  23.   
  24.         foreach (Point Dot in DotFont)   
  25.         {   
  26.             DrawingContext.DrawRectangle(Brushes.White, null,   
  27.                 new Rect(Dot.X,Dot.Y,2,2));   
  28.         }   
  29.   
  30.         DrawingContext.Close();   
  31.   
  32.         RenderTargetBitmap bmp = new RenderTargetBitmap((int)ResultTextCanvas.Width, (int)ResultTextCanvas.Height, 96, 96, PixelFormats.Pbgra32);   
  33.         bmp.Render(DrawingVisual);   
  34.         ResultTextCanvas.Background = new ImageBrush(bmp);   
  35.   
  36.     }   
  37.   
  38.   
  39.   
  40.     public List<POINT> GenerateDotFont(TextBlock ReferenceTextBlock,int Space)   
  41.     {   
  42.   
  43.         int Width = (int)ReferenceTextBlock.Width;   
  44.         int Height = (int)ReferenceTextBlock.Height;   
  45.   
  46.         FormattedText text = new FormattedText(ReferenceTextBlock.Text,   
  47.                 CultureInfo.CurrentCulture,   
  48.                 FlowDirection.LeftToRight,   
  49.                 new Typeface(ReferenceTextBlock.FontFamily, ReferenceTextBlock.FontStyle, ReferenceTextBlock.FontWeight, ReferenceTextBlock.FontStretch),   
  50.                 ReferenceTextBlock.FontSize, ReferenceTextBlock.Foreground);   
  51.   
  52.         DrawingVisual DrawingVisual = new DrawingVisual();   
  53.         DrawingContext DrawingContext = DrawingVisual.RenderOpen();   
  54.         DrawingContext.DrawText(text, new Point(0, 0));   
  55.         DrawingContext.Close();   
  56.   
  57.         RenderTargetBitmap bmp = new RenderTargetBitmap(Width, Height, 96, 96, PixelFormats.Pbgra32);   
  58.         bmp.Render(DrawingVisual);   
  59.   
  60.         BmpBitmapEncoder Encoder = new BmpBitmapEncoder();   
  61.         Encoder.Frames.Add(BitmapFrame.Create(bmp));   
  62.   
  63.         MemoryStream MemoryStream = new MemoryStream();   
  64.         Encoder.Save(MemoryStream);   
  65.   
  66.         // Header Skip   
  67.         MemoryStream.Seek(54, SeekOrigin.Begin);   
  68.   
  69.         byte[] Buff = new byte[MemoryStream.Length - 54];   
  70.         MemoryStream.Read(Buff, 0, (int)(MemoryStream.Length - 54));   
  71.   
  72.         List<POINT> Result = new List<POINT>();   
  73.         int HeightOffSet = 0;   
  74.         for (int Y = 0; Y < Height; Y+=Space)   
  75.         {   
  76.             HeightOffSet = Width * Y;   
  77.   
  78.             for (int X = 0; X < Width; X+=Space)   
  79.             {   
  80.                 if (Buff[((HeightOffSet + X) << 2 )] == 255)   
  81.                     Result.Add(new Point(X, Height - Y));   
  82.   
  83.             }   
  84.         }   
  85.   
  86.         return Result;   
  87.   
  88.     }   
  89.   
  90. }  

코드를 보면 2가지 함수를 확인 하실 수 있을 것입니다. DrawDotFont는 List<Point> Type의 Dot Data가 포함된 DotList를 사용하여 Canvas에 DotFont를 그려주는 역할을 하며 GenerateDotFont는 ReferenceTextBlock의 정보에 맞춰 DotFont를 생성하는 역할을 합니다.

우리가 자세히 살펴봐야하는 함수는 GenerateDotFont 인데요, 아래와 같이 총 5개의 과정을 통해 시작됩니다.

1. DrawingVisual과 DrawingContext를 사용해서 TextVisual을 생성합니다.
2. RenderTargetBitmap을 사용하여 DrawingVisual객체를 렌더링 합니다.
3. 렌더링한 RenderTargetBitmap객체를 BmpBitmapEncoder를 사용하여 Bmp형식으로 변환합니다.
4. MemoryStream을 사용하여 Bmp로 변환된 객체의 픽셀정보를 가져옵니다.
5. Spacing만큼 픽셀을 건너 뛰면서 해당 픽셀이 글자 부분인지를 체크합니다.

다소 접하기 어려운 Class를 활용하는 예제라서 처음 보기에는 어려워 보일 수 있는 코드지만, 한줄한줄 따라가다보면 쉽게 이해하실 수 있을것입니다. 그럼 오늘 포스팅은 여기까지 하고 기타 질문은 리플이나 메일로 보내주시면 답변드리겠습니다.
(조만간 Dot Font를 활용한 예제를 올리도록 하겠습니다.)

전체 소스코드입니다.