Communication Problems in NAO Robot Relay Race

Keywords: socket REST Python

I. Preface

NAO robots have been in contact for more than a year, during which many programs have been developed.

First, NAO robot face recognition and path planning in complex indoor environment are done.

Later, he participated in the NAO Robot Golf Tournament and developed a complete framework for the NAO Robot Golf Tournament, and provided the source code to the organizers.

On this basis, it also helps organizers to develop a NAO robot relay program framework. The first version is the robot's message transmission through Socket communication, which is also mentioned in this chapter. The second version is the robot's information extraction through machine vision.

Now let's talk about socket communication.

TCP server:
1 Create sockets, bind sockets to local IP and ports
# socket.socket(socket.AF_INET,socket.SOCK_STREAM) , s.bind()
2 Start listening on connection # s.listen()
3 Enter the loop and continue to accept client connection requests #s.accept()___________.
4 Then receive the incoming data and send it to the other party # s. recv (), s. sendall ()
5 Close the socket # s.close()

TCP client:
1 Create sockets to connect to remote addresses
# socket.socket(socket.AF_INET,socket.SOCK_STREAM) , s.connect()
Send and receive data after connection# s.sendall(), s.recv()
Close the socket # s.close()

For NAO robots, there is nothing more than a server and a client. The code is as follows:
client.py

#-*- coding: utf-8 -*-
###########################################################
#   > Description: Remote Control - Client
#                       Send instructions to the server to view the server receipt message.
###########################################################
#! /usr/bin/env python

import argparse
from naoqi import ALProxy
import socket
import time

LISTEN_PORT = 8001 # Server listening port

# command 
COMMAND_DISCONNECT = 'DISCONNECT'
COMMAND_HEADYAW = 'HEADYAW'     # Around the head
COMMAND_HEADPITCH = 'HEADPITCH' # Head up and down

# flag
CONNECT = False

def main(robot_IP, robot_PORT=9559):
    # ----------> Connect to socket server listening port
    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    sock.connect((robot_IP, LISTEN_PORT))
    time.sleep(2)

    CONNECT = True
    while CONNECT == True: 
        # Input instruction
        command = raw_input("Command code:")
        # socket sends instructions
        sock.send(command)
        if command == COMMAND_HEADYAW or command == COMMAND_HEADPITCH:
            value = raw_input("Value:")
            sock.send(value)

        # socket accepts the return message
        buf = sock.recv(1024)
        print buf
        if command == COMMAND_DISCONNECT: 
            CONNECT = False
    sock.close() # Disconnect socket from server

if __name__ == "__main__":
    parser = argparse.ArgumentParser()
    parser.add_argument("--ip", type=str, default="192.168.1.100", help="Robot ip address")
    parser.add_argument("--port", type=int, default=9559, help="Robot port number")
    args = parser.parse_args()
    # Executing main function
    main(args.ip, args.port)

server.py

#! /usr/bin/env python
#-*- coding: utf-8 -*-
###########################################################
#   > Description: Remote Control - Server Side
#                       Accept the instructions from the client and perform the corresponding functions.
###########################################################
import argparse
from naoqi import ALProxy
import socket
import sys      # sys.exit() exits main function
import almath   # Almath. TO_RAD
import thread   # Multithreading
import time     # Delay function time.sleep(1)

LISTEN_PORT = 8001 # Server listening port

# Command Definition
COMMAND_WAKEUP = 'WAKEUP'
COMMAND_REST = 'REST'

COMMAND_FORWARD = 'FORWARD'
COMMAND_BACK = 'BACK'
COMMAND_LEFT = 'LEFT'
COMMAND_RIGHT = 'RIGHT'
COMMAND_STOP = 'STOP'

COMMAND_TURNLEFT = 'TURNLEFT'
COMMAND_TURNRIGHT = 'TURNRIGHT'

COMMAND_DISCONNECT = 'DISCONNECT'
COMMAND_SENSOR = 'SENSOR'

COMMAND_HEADYAW = 'HEADYAW'     # Around the head
COMMAND_HEADPITCH = 'HEADPITCH' # Head up and down

# flag
CONNECT = False         # Client Connection Flag 
SENSOR  = False         # Sensors monitor Flag, and threads send data regularly for True.

# Global variables for use by other functions
ROBOT_IP = '192.168.1.100'
ROBOT_PORT = 9559
connection = None
battery = None
memory = None

def main(robot_IP, robot_PORT=9559):

    global ROBOT_IP
    global ROBOT_PORT
    ROBOT_IP = robot_IP
    ROBOT_PORT = robot_PORT

    # ----------> Connect to robot <----------
    tts = ALProxy("ALTextToSpeech", robot_IP, robot_PORT)
    motion = ALProxy("ALMotion", robot_IP, robot_PORT)
    posture = ALProxy("ALRobotPosture", robot_IP, robot_PORT)
    global memory
    memory = ALProxy("ALMemory", robot_IP, robot_PORT)
    leds = ALProxy("ALLeds", robot_IP, robot_PORT)
    global battery
    battery = ALProxy("ALBattery", ROBOT_IP, ROBOT_PORT)
    autonomous = ALProxy("ALAutonomousLife", robot_IP, robot_PORT)
    autonomous.setState("disabled") # turn ALAutonomousLife off

    # Open the socket server listening port
    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    sock.bind((robot_IP, LISTEN_PORT))
    sock.listen(10)

    try:
        while True: # Waiting for client connection, single thread listening for single client
            global connection
            connection,address = sock.accept()
            CONNECT = True
            while CONNECT == True:
                try:
                    #connection.settimeout(10)
                    # Server accepts instructions
                    buf = connection.recv(1024)
                    print "get:[", buf, "]"
                    # Perform different operations according to the received commands
                    if buf == COMMAND_WAKEUP:
                        if motion.robotIsWakeUp() == False: 
                            motion.post.wakeUp()
                        connection.send("Robot Motion: [ Wakeup ]\r")
                    elif buf == COMMAND_REST:
                        if motion.robotIsWakeUp() == True: 
                            motion.post.rest()
                        connection.send("Robot Motion: [ Rest ]\r")
                    elif buf == COMMAND_FORWARD:
                        if motion.robotIsWakeUp() == False: 
                            motion.post.wakeUp()
                            connection.send("Robot Motion: [ Wakeup ]\r")
                            motion.post.moveInit()
                            connection.send("Robot Motion: [ MoveInit ]\r")
                        #motion.post.moveTo(0.3, 0, 0)
                        motion.move(0.1,0,0) # Continuous walking at a fixed rate
                        connection.send("Robot Motion: [ Forward ]\r")
                    elif buf == COMMAND_BACK:
                        if motion.robotIsWakeUp() == False: 
                            motion.post.wakeUp()
                            connection.send("Robot Motion: [ Wakeup ]\r")
                            motion.post.moveInit()
                            connection.send("Robot Motion: [ MoveInit ]\r")
                        #motion.post.moveTo(-0.1, 0, 0)
                        motion.move(-0.1,0,0)
                        connection.send("Robot Motion: [ Back ]\r")
                    elif buf == COMMAND_LEFT:
                        if motion.robotIsWakeUp() == False: 
                            motion.post.wakeUp()
                            connection.send("Robot Motion: [ Wakeup ]\r")
                            motion.post.moveInit()
                            connection.send("Robot Motion: [ MoveInit ]\r")
                        #motion.post.moveTo(0, 0.1, 0)
                        motion.move(0,0.1,0)
                        connection.send("Robot Motion: [ Left ]\r")
                    elif buf == COMMAND_RIGHT:
                        if motion.robotIsWakeUp() == False: 
                            motion.post.wakeUp()
                            connection.send("Robot Motion: [ Wakeup ]\r")
                            motion.post.moveInit()
                            connection.send("Robot Motion: [ MoveInit ]\r")
                        #motion.post.moveTo(0, -0.1, 0)
                        motion.move(0,-0.1,0)
                        connection.send("Robot Motion: [ Right ]\r")
                    elif buf == COMMAND_STOP:
                        motion.stopMove()
                        connection.send("Robot Motion: [ stop move ]\r")
                    elif buf == COMMAND_TURNRIGHT:
                        if motion.robotIsWakeUp() == False: 
                            motion.post.wakeUp()
                            connection.send("Robot Motion: [ Wakeup ]\r")
                            motion.post.moveInit()
                            connection.send("Robot Motion: [ MoveInit ]\r")
                        motion.move(0, 0, -0.3)
                        connection.send("Robot Motion: [ turn right ]\r")
                    elif buf == COMMAND_TURNLEFT:
                        if motion.robotIsWakeUp() == False: 
                            motion.post.wakeUp()
                            connection.send("Robot Motion: [ Wakeup ]\r")
                            motion.post.moveInit()
                            connection.send("Robot Motion: [ MoveInit ]\r")
                        motion.move(0, 0, 0.3)
                        connection.send("Robot Motion: [ turn left ]\r")
                    elif buf == COMMAND_DISCONNECT:
                        CONNECT = False
                        connection.send("disconnect from robot server.\r")
                    elif buf == COMMAND_HEADYAW:
                        # Head turning left and right (Yaw axis)
                        buf2 = connection.recv(1024)    # Read Yaw values    
                        print "yaw:", buf2
                        angles = (int(buf2) - 50)  
                        motion.setStiffnesses("Head", 1.0)
                        motion.setAngles("HeadYaw", angles * almath.TO_RAD, 0.2) # Converting angles angle at 10% speed
                        connection.send("Robot Motion: [ head raw ]\r")
                    elif buf == COMMAND_HEADPITCH:
                        # Head up and down rotation (Pitch axis)
                        buf2 = connection.recv(1024)    # Read Pitch values  
                        print "pitch:", buf2
                        angles = (int(buf2) - 50) * 2
                        motion.setStiffnesses("Head", 1.0)
                        motion.setAngles("HeadPitch", angles * almath.TO_RAD, 0.2) # Converting angles angle at 10% speed
                        connection.send("Robot Motion: [ head pitch ]\r")
                    elif buf == COMMAND_SENSOR:
                        global SENSOR
                        if SENSOR == False:
                            # Open new threads and send sensor data regularly
                            SENSOR = True
                            thread.start_new_thread(sensor, (1,)) # 2nd arg must be a tuple
                        else:
                            # When COMMAND_SENSOR is sent the second time, the thread is closed
                            SENSOR = False  # Set the identification bit and exit the thread itself after detection.
                        connection.send("Robot Motion: [ send sensor value ]\r")
                    else:
                        connection.send(buf + ": command not found\r")
                except socket.timeout:
                    print 'time out'
            connection.close()  # Close the current socket connection and enter the next cycle
    except KeyboardInterrupt: # CTRL+C, close the server-side program;
        print ""
        print "Interrupted by user, shutting down"
        sys.exit(0)

def sensor(interval):
    ''' each interval Send sensor data once in seconds
    '''
    while SENSOR == True:
        connection.send("BATTERY" + "#" + str(battery.getBatteryCharge()) + "\r")
        connection.send("SONAR1" + "#" + str(memory.getData("Device/SubDeviceList/US/Left/Sensor/Value")) + "\r")
        connection.send("SONAR2" + "#" + str(memory.getData("Device/SubDeviceList/US/Right/Sensor/Value")) + "\r")
#       print "BATTERY" + "#" + str(battery.getBatteryCharge())
        time.sleep(interval)
    # SENSOR == False
    thread.exit_thread()       

if __name__ == "__main__":
    parser = argparse.ArgumentParser()
    parser.add_argument("--ip", type=str, default="192.168.1.100", help="Robot ip address")
    parser.add_argument("--port", type=int, default=9559, help="Robot port number")
    args = parser.parse_args()
    # Executing main function
    main(args.ip, args.port)

The first robot will send an instruction to the second robot as soon as it reaches the end point. It's still easy to run a relay. Focus on running!

Posted by geny on Fri, 31 May 2019 12:15:58 -0700