반응형

 

 

지식 없이 완전 처음부터 하니.. 틀린정보가 많습니다..

 

https://cheongpark.tistory.com/54

 

SCARA 로봇 제작하기 Pt. 6 (제작 - 끝)

이제.. 다 조립했으니.. 보드에 선을 연결해야하는데.. 제일 헷갈린 부분이 여기다.. 최대한 찾아서 끼우긴 했지만.. 계속 잘 못 끼웠었었다.. 그러다가 결국엔 끼웠지만.. 저 사진에 보이는 것 처

cheongpark.tistory.com

여기에서 로봇을 모두 제작했었다.

그런데 한가지 문제가 있다.. 로봇을 제어할 프로그램이 필요한데.. 예제에서 제공하는 프로그램은 도무지 알 수도 없고.. 여러 버그도 있고 잘 되지 않는 문제들이 있다.. 

그래서 그냥 처음부터 프로그램을 제작하는 것을 목표로 잡았다..

 

구상

일단 GUI 프로그램으로 만들 예정인데..

나에게는 웹페이지로 GUI를 구현하는 방법, 프로그램으로 GUI를 구현하는 방법 2가지가 있었는데..

난 여기에서 프로그램으로 GUI를 만드는걸로 선택했다.

이유는 프로그램으로 GUI를 만들어 본적이.. 예전에 OpenCV로 비슷하게나마 만들어본게 끝이고.. 제대로 만들어본 적은 없고.. C++를 연습하기 위해서이다.

일단.. C++로 프로그램을 제작한다면.. MFC나.. WinRT 이런게 있는데.. 나는 나중을 생각해서 크로스 플랫폼이 지원되는 WinRT로 정했다.

 

그래서 Visual Studio에 WinRT 프로그램을 제작하기 위한 설치 파일을 설치한 후 프로젝트를 만들었다.

 

그 후 일단 구상을 했는데

대충 이런 느낌으로 제작하는 것이다. 메인 그리드 부분에선 Inverse Kinematics로 로봇의 암을 제어하고 오른쪽 설정 창에선 집게를 펼지 말지 이런거를 세팅하고, 왼쪽에선 높이로 로봇의 Z축을 제어하는 곳으로 정했다.

또한 아래쪽의 검은색 저부분은 각각의 세팅 값이다. 설정 창에서 저장버튼을 눌르면 아래에 스택이 쌓이고 각 스택을 눌르면 그 때 저장했던 값들이 다시 나오게 되는 프로그램을 제작하기로 했다.

 

현재도 제작중이기 때문에.. 저기에서 어떤 점이 바뀔지는 모르겠지만.. 이 상태로 하기로 정했다.

 

GUI Xaml 제작 및 프로그래밍

일단 여기에서 제일 중요한 부분은 Inverse Kinematics 부분이다. 물론 각도로 일일이 다 지정을 할 순 있겠지만.. 그렇게 하면.. GUI 프로그램을 만드는 의미가 사라진다..

그래서 일단 저기를 구현해야하는데.. 구현하기 전에 사전에 세팅을 했다.

 

그리드 그리기

먼저 그리드를 표시하는 것!

일단 Xaml로 저것이 표시될 구간을 정한다!

현재 나의 경우엔.. 이걸 처음하다보니.. 아는게 없었다.. 그래서 어느정도 전문가가 보기엔 불편한 것들이 많겠지만.. 일단 이대로 진행하기로 했다. 아래 코드 구조에서 Canvas가 2개가 있는데.. 하나는 그리드를 표시하는 용이고 하나는 Inverse Kinematics로 팔 부분을 표시하는 것이다.

<Border
    Width="506"
    Height="506"
    BorderBrush="#f8f8f2"
    BorderThickness="3"
    CornerRadius="15,15,15,15"
    RelativePanel.AlignVerticalCenterWithPanel="True"
    Margin="200, 0, 0, 0">
    <!-- 그리드 위에 컨트롤를 넣는 느낌으로 할려 했지만 그리드가 나중에 렌더링 되어서 Canvas.ZIndex로 직접 바꿈 -->
    <Canvas
        x:Name="DrawGrid"
        Width="500"
        Height="500"
        Canvas.ZIndex="0"
        Background="Transparent"> 
        <Canvas
            x:Name="ControlJoint"
            Width="500"
            Height="500"
            Canvas.ZIndex="1"
            Background="Transparent"> <!-- 배경을 투명하게라도 주는 이유는 안하면 ControlJoint로 마우스 위치를 얻을려고 하면 Shape 부분만 얻을 수 있어서.. 전부 얻기 위해서 하는거 -->
        </Canvas>
    </Canvas>
</Border>

주석에 달린 것 처럼.. ZIndex를 넣은 이유가.. 그리드 배경 위에 팔 부분이 나오면 좋겠지만.. 렌더링 되는 것이.. 그리드가 먼저 되다보니.. ZIndex로 직접 바꾼거다.. 그리고 움직일 부분에서 마우스로 제어할 것인데.. 거기에서 마우스로 제어하는 경우 그리드에선 전부 추적이 가능하지만.. ControlJoint에선 팔 부분만 마우스의 좌표를 알 수 있다.. 그래서 그냥 배경을 추가하는 방식으로 진행했다.

 

이제 저렇게 하면 프로그램 안에 500 * 500 의 사각 박스가 나오게 된다.

이 사각 박스 안에 격자를 그려야하는데 이걸 위해 함수를 만들었다.

일단 line의 경우 좌표에서 필요한 속성은 X1, Y1, X2, Y2가 있다.

그래서 내가 생각한 방법으론 500을 내가 필요한 만큼의 라인 갯수로 나눠서 각 지점에 직접 배치하는 방식으로 했다.

 

그렇게 해서 C++ 코드를 작성했다.

void MainPage::DrawLine(Xaml::Shapes::Line& line, Xaml::Controls::Canvas& canvas, double thickness, float2 pos_1, float2 pos_2, Xaml::Media::Brush color) {
    // 위치나 색 설정
    line.X1(pos_1.x);
    line.Y1(pos_1.y);
    line.X2(pos_2.x);
    line.Y2(pos_2.y);

    line.StrokeThickness(thickness);
    line.Stroke(color);

    canvas.Children().Append(line);

    Xaml::Controls::Canvas::SetZIndex(line, 0);
}

void MainPage::DrawGridLines(int grid_x_count, int grid_y_count) {
    double grid_width = DrawGrid().ActualWidth();
    double grid_height = DrawGrid().ActualHeight();
    double line_thickness = 1;

    // 가로 줄 세로로 여러개 그리는거
    for (double i = grid_height / grid_y_count; i < grid_height; i += grid_height / grid_y_count) {
        Xaml::Shapes::Line line = Xaml::Shapes::Line();
        DrawLine(line, DrawGrid(), line_thickness, float2(0, i), float2(grid_width, i));
    }

    // 세로 줄 가로로 여러개 그리는거
    for (double i = grid_width / grid_x_count; i < grid_width; i += grid_width / grid_x_count) {
        Xaml::Shapes::Line line = Xaml::Shapes::Line();
        DrawLine(line, DrawGrid(), line_thickness, float2(i, 0), float2(i, grid_height));
    }
}

이 코드로 DrawGridLines를 처음에 프로그램을 시작할 때 실행해서 각 x축으로 몇개 y축으로 몇개 넣을지 선택해서 하면 

 

결과적으로 이렇게 표시가 된다..!

라인을 각각 10개씩 넣어서 했다.

 

마우스 위치 알아내고 표시하기

그리고 이후에 팔을 제어하기 위해 마우스를 사용해야해서 마우스 포인터의 위치를 알아야 한다..!

근데 일단 보통은 콘솔창에서 확인을 하는데.. 콘솔창은 어떻게 띄우는지도 모르겠고.. 그냥 GUI 화면에서 확인하는게 빠를 것 같아서 GUI 화면에서 표시되도록 했다..!

 

일단 Xaml 코드에선

<StackPanel
    BorderBrush="White"
    BorderThickness="2" RelativePanel.AlignBottomWithPanel="True" RelativePanel.AlignLeftWithPanel="True">
    <StackPanel
        Orientation="Horizontal">
        <TextBlock
            Width="50"
            TextAlignment="Center"
            Text="X"
            FontSize="35"/>
        <TextBlock
            x:Name="Point_X"
            Width="100"
            TextAlignment="Right"
            Text="0"
            FontSize="35"/>
    </StackPanel>
    <StackPanel
        Orientation="Horizontal">
        <TextBlock
            Width="50"
            TextAlignment="Center"
            Text="Y"
            FontSize="35"/>
        <TextBlock
            x:Name="Point_Y"
            Width="100"
            TextAlignment="Right"
            Text="0"
            FontSize="35"/>
    </StackPanel>
</StackPanel>

이런식으로 했다. X인지 Y인지 알 수 있게 하고 그 바로 옆에 숫자를 표시하도록 했다.

그래서 이걸로 해서 실행하면 저런식으로 나온다.

 

그리고 각 X, Y 좌표를 얻어야 한다.

이 경우엔 좀 간단한데.. 보통은 Xaml 코드에서 X, Y 값을 가져올 함수를 지정할 순 있지만.. 나는 나중에 함수 이름을 쉽게 변경하기 위해 모두 C++에서 진행했다.

일단 X, Y 좌표를 가져올 캔버스는 ControlJoint라는 것이기 때문에 여기의 PointerMoved로 접근해서 함수로 넘겨주는 방식으로 했다.

void MainPage::Init() {
	ControlJoint().PointerMoved({ this, &MainPage::JointControlCanvasPointerMoved });
}

void MainPage::JointControlCanvasPointerMoved(IInspectable const& sender, Xaml::Input::PointerRoutedEventArgs const& e) {
    Input::PointerPoint point = e.GetCurrentPoint(ControlJoint());
    float2 point_pos(point.Position().X, point.Position().Y);

    Point_X().Text(to_hstring(point_pos.x));
    Point_Y().Text(to_hstring(point_pos.y));
}

이런식으로 하면 마우스 포인터의 값을 가져와서 아까 만들었던 Text로 집어넣게 된다.

Init 함수는 그냥 임의로 만든거고.. 프로그램이 시작할 때 실행되도록 하면 된다. 그렇게 해서 마우스 값을 넘겨주고 거기에서 X, Y 값을 뽑아서 Text를 지정하는 방식이다.

 

결과물!!

그래서 이것으로 일단 프로젝트 준비는 끝났다..!!

이걸로 지금까지 한 것의 결과물을 보면 아래 처럼된다..!

그렇게 해서 일단 Pt. 1은 끝났다..! 

이 모든 것이.. 3일 정도 걸려서 알아내고 만든 결과다..! 물론 GPT의 도움도 받긴 했지만.. 암튼.. 다음에선 IK를 구현하는 것이다..!

반응형

+ Recent posts