User Tools

Site Tools


wiimote_button_action

How to Program Wii Remote to Control DARwIn-OP

Author: Fausto Vega Email: vegaf1@unlv.nevada.edu
Author: Yu Hang He Email: hey6@unlv.nevada.edu
Reviewed by: Jean Vaz Email: chagasva@unlv.nevada.edu

Date: Last modified on <04/20/19>
Keywords: Dynamixels , C/Cpp Programming, Wii Remote, Humanoid robot, DARwIn-OP

The objective of the tutorial is to control DARwIn-OP with a Wii controller. Solving this partially or completely is important because it allows one to access data from the internal sensors in the Wii remote and use the inputs on the Wii remote to control DARwIn-OP. This tutorial shows you the procedure and the program to access the data from the Wii remote, use inputs from Wii remote to control DARwIn-OP, and provides a demonstration of the final result.

Motivation and Audience

This tutorial's motivation is to teach the audience how to detect inputs on the Wii remote and use those inputs to control DARwIn-OP. The Wii remote is connected to a laptop using Bluetooth. A client program on the laptop will receive inputs from the Wii remote, then send the signals via a TCP network model to a server program on DARwIn-OP to control its action. Readers of this tutorial assumes the reader has the following background and interests:

* Know how to program using Cpp language
* Familiar with Linux terminal
* Familiar with programming structure of DARwIn-OP
* This tutorial may also attract readers who are interested in using Wii remote as a controller for any program

The rest of this tutorial is presented as follows:

Other Tutorials and References

For a more in depth explanation of network programming (TCP client server program) refer to the following tutorial:

For a quick guide to using network programming on DARwIn-OP refer to the following tutorial

For a guide to accessing acceleration data on Wii remote and use it to control Dynamixel motor refer to the following tutorial:

The procedures for downloading the Wii remote driver, connecting Wii remote to a computer through Bluetooth, and source code for accessing Wii remote data and use it to control Dynamixels are presented in the last tutorial. It is highly recommended that the reader read and complete the last tutorial before proceeding since the information will not be repeated in this tutorial.

Programming

This section will highlight some important part of the code in the programs. The full programs are available in the Source Code section.

| xwiiacc/main.cpp
//Line 82
static void wii_event(const struct xwii_event *event, int sockfd)
{
    int n, reply[1];
    //array that stores the states of key and acceleration data
    int arg[8] = {0};
 
    //in event struct, v is an union that stores data payload
 
    //key struct continas the enumerated key number and key state
    //store key number in code and state as a bool pressed (0 false, 1 true)
    unsigned int code = event->v.key.code;
    bool pressed = event->v.key.state;
 
    //Use switch case to cycle through wiimote events
    switch(event->type)
    {
    case XWII_EVENT_KEY:
 
        //if the respective key are pressed, the state is set to 1, otherwise 0
        if(pressed)
        {
        if (code == XWII_KEY_LEFT)
            arg[2] = 1;
        else
            arg[2] = 0;
        if (code == XWII_KEY_RIGHT)
            arg[3] = 1;
        else
            arg[3] = 0;
        if (code == XWII_KEY_UP)
            arg[4] = 1;
        else
            arg[4] = 0;
        if (code == XWII_KEY_DOWN)
            arg[5] = 1;
        else
            arg[5] = 0;
        }
        else
        {
            for(int i = 2; i < 6; i++)
                arg[i] = 0;
 
        }
 
        //key A and B act as switches for performing actions, the sleep() was used to pause the program while action is performed
        if (code == XWII_KEY_A)
            if(pressed)
            {
                arg[6] = -arg[6];
                sleep(1);
            }
        if (code == XWII_KEY_B)
            if(pressed)
            {
                arg[7] = -arg[7];
                sleep(1);
            }
        break;
    case XWII_EVENT_ACCEL:
 
        //abs struct contains absolute motion event payload, x stores roll, while y stores pitch
        if(arg[7] == 1)
        {
            arg[0] = event->v.abs[0].x*val2deg;
            arg[1] = event->v.abs[0].y*val2deg;
        }
        else
        {
            arg[0] = 0;
            arg[1] = 0;
        }
        break;
    }
 
    //send motion data to server using socket
    n = write(sockfd, arg, sizeof(arg));
    if (n < 0)
         error("ERROR writing to socket");
    bzero(reply,sizeof(reply));
 
    n = read(sockfd,reply,sizeof(reply));
    if (n < 0)
         error("ERROR reading from socket");
}
| network_programming/server.cpp
//Line 135
    //store the initial position of dynamixel
    cm730.ReadWord(JointData::ID_L_SHOULDER_PITCH, MX28::P_PRESENT_POSITION_L, &pitchpos, 0);
    cm730.ReadWord(JointData::ID_L_SHOULDER_ROLL, MX28::P_PRESENT_POSITION_L, &rollpos, 0);
 
    while (1) {
 
        //read TCP data from client and store it in disp[] array
        n = read(newsockfd,disp,sizeof(disp));
        if (n < 0) error("ERROR reading from socket");
 
        //new position for shoulder roll and pitch dynamixel is the sum of initial position and angle inputs from Wii remote
        r_pos = rollpos+11.378*disp[0];
        p_pos = pitchpos+11.378*disp[1];
 
        if (disp[7] ==1)
        {
 
            Action::GetInstance()->m_Joint.SetEnableBody(false, false);
            MotionManager::GetInstance()->SetEnable(false);
 
            //dynamixel limits
            if (rollpos>=2460 || rollpos<=1200)
                printf("Limit has been reached");
            else
                cm730.WriteWord(JointData::ID_L_SHOULDER_ROLL, MX28::P_GOAL_POSITION_L, r_pos, 0); //move shoulder roll
 
            //dynamixel limits
            if (pitchpos<0 || pitchpos>3038)
                printf("Limit has been reached");
            else
                cm730.WriteWord(JointData::ID_L_SHOULDER_PITCH, MX28::P_GOAL_POSITION_L, p_pos, 0); //move shoulder pitch
 
        }
 
        //disp[6] stores states of button A on Wii remote
        //integer stand and sit stores the state of DARwIn-OP
        if (disp[6] == 1)
        {
            if(stand == 0)
            {
                if(Action::GetInstance()->IsRunning() == 0)
                {
                    Action::GetInstance()->m_Joint.SetEnableBody(true, true);
                    MotionManager::GetInstance()->SetEnable(true);
                    Action::GetInstance()->Start(9);
                    stand = 1;
                    sit = 0;
                }
            }
        }
        else if (disp[6] == -1)
        {
            if (sit == 0)
            {
                if(Action::GetInstance()->IsRunning() == 0)
                {
                    Action::GetInstance()->m_Joint.SetEnableBody(true, true);
                    MotionManager::GetInstance()->SetEnable(true);
                    Action::GetInstance()->Start(15);
                    sit = 1;
                    stand = 0;
                }
            }
        }
 
        n = write(newsockfd,"0",1);
        if (n < 0) error("ERROR writing to socket");
    }

Source Code

Below is the source code for the client and server used in the program. Download the xwiiacc.zip folder on a laptop and the darwin_wii_action.zip folder on the DARwIn-OP. The Wii remote will be used as input device to control DARwIn-OP

Compiling the Client

If the xwiimote driver is successfully installed on the linux system, the library file libxwiimote.so should be installed in

   /usr/local/lib     

The program can be compiled direclty, however, the library file and header will need to be manually included in C compiler. Using terminal, navigate to the xwiiacc folder. While inside xwiiacc, execute the following command to compile the program:

   gcc main.cpp -o xwiiacc -L/~/usr/local/lib/ -lxwiimote    

The output program file is called xwiiacc.

Instructions

This section gives step-by-step instructions on how to run the program.

Step 1: Run sudo su on Darwin OP (password is 111111) and navigate to the code folder with the following command;

   cd Desktop/darwin_wii_action/Linux/project/network_programming/    

Then make the code :

   make

Step 2

Once the program is built, make sure that both the client (laptop) and the server (Darwin OP) are connected to the same network. In this case it is “DASLWarehouse 2”

Step 3

Run the server program by accessing the command prompt, navigating to the network programming folder (Step 1) and running the following command.

   ./server 5000    

In this command, 5000 is the port number used for communication between the server and client.

Step 4

Before running the client program, make sure the wii remote is laying still on a flat surface with the controls facing up.

To run the client program on the laptop, access the command prompt and navigate to the folder where the xwiiacc program was compiled in the previous section. Enter the following commands to establish connection with the server:

   sudo ./xwiiacc 192.168.50.75 5000 1     

Enter the password for ubuntu system to execute the program.

Step 5

Once both server and client program is running, Press the B button on Wii remote to control the Dynamixel motor on DARwIn-OP. The Left shoulder pitch motor is controlled with the pitch motion of wii remote while the left shoulder roll motor is controlled with the roll motion. Slowly tilt and roll the wii remote for fine controls. Press the B button again to stop the control of Dynamixel. Press the A button to command DARwIn-OP to move to Stand position. Press the A button again to command DARwIn-OP to move to Sit position.

Step 6

To exit out of the program, press control C on the command prompt

Demonstration

In this demonstration, I successfully compiled and execute the program described above

Final Words

This tutorial objective was to access the wii remote data and use it to control DARwIn-OP. The process of connecting a wiimote was explained as well as a client server model to send the data from the wii remote. Once the concepts were conveyed the reader could access data in the wii remote and use it for their project.

Speculating future work derived from this tutorial, includes implementing a nunchuck to the wii and accessing its data. In the big picture, the problem of Wii remote control teleoperation can be solved with this tutorial.

wiimote_button_action.txt · Last modified: 2019/04/20 11:48 by jeanvaz