Naogolf简易训练

围绕Nao高尔夫竞赛准备的一些简单的配套训练任务。

Posted by LJJ on July 14, 2019

Naogolf简易训练

Target List

  • 图像定位
  • 重定位
  • 找球
  • 击球

实现代码

step1.

def locateWithImage(self, best_ball_x=400, best_ball_y=320, best_ball_radius=28):   
    self.motionProxy.angleInterpolationWithSpeed(["HeadPitch", "HeadYaw"], [20 * rad, 0 * rad], 0.1)     
    self.ballDetect.updateBallData(client="cx", fitting=True)
    centerX, centerY, radius = self.ballDetect.getBallInfoInImage()
    bias_x = centerY - best_ball_y         
    bias_y = centerX - best_ball_x       
    Kp = 0.0008           

    if abs(radius - best_ball_radius) < 15: 
        if (abs(bias_x) < 40 and abs(bias_y) < 20):
            self.tts.say("I am OK")
            return True
        else:
            self.motionProxy.moveInit()
            move_x = Kp * bias_x 
            move_x = -1.0 / 100 if (move_x < 0 and move_x > -1.0 / 100) else move_x
            move_x = 1.0 / 100 if (move_x > 0 and move_x < 1.0 / 100) else move_x
            if abs(bias_x) > 15:
                self.motionProxy.moveTo(-move_x, 0, 0)
                time.sleep(0.5)

            move_y = Kp * bias_y 
            move_y = -1.0 / 100 if (move_y < 0 and move_y > -1.0 / 100) else move_y
            move_y = 1.0 / 100 if (move_y > 0 and move_y < 1.0 / 100) else move_y
            if abs(bias_y) > 15:
                self.motionProxy.moveTo(0, -move_y, 0)
                time.sleep(0.5)

step2.

# encoding:utf-8

def moveCircle_stick(self, stickAngle, ball_d, compensateAngle1):
    '''
    绕球走半径为机器人与球的距离的圆弧,分正反手

    参数:
        stickAngle:黄杆与机器人的角度
        ball_d:机器人与球的距离
        compensateAngle1:补偿角(机器人-杆-球的角度)
    '''
    # 杆-球-机器人的夹角(分锐角和钝角)
    stick_ball_robotAngle = math.pi - compensateAngle1 * rad - abs(stickAngle)

    # 正手打
    if stickAngle >= 0:
        self.isbackhandFlag = False
        if 0 <= stick_ball_robotAngle < 0.5 * math.pi:
            moveAngle = 0.5 * math.pi - stick_ball_robotAngle
            move_d = (ball_d ** 2 + ball_d ** 2 
                        - 2 * ball_d * ball_d * math.cos(moveAngle)) ** 0.5
            self.motionProxy.moveInit()
            self.motionProxy.moveTo(0, -move_d, moveAngle)
        else:
            moveAngle = stick_ball_robotAngle - 0.5 * math.pi
            move_d = (ball_d ** 2 + ball_d ** 2 
                        - 2 * ball_d * ball_d * math.cos(moveAngle)) ** 0.5 
            self.motionProxy.moveInit()
            self.motionProxy.moveTo(0, move_d, -moveAngle)
    # 反手打
    else:
        self.isbackhandFlag = True
        stickAngle = abs(stickAngle)
        if 0 <= stick_ball_robotAngle < 0.5 * math.pi:
            moveAngle = 0.5 * math.pi - stick_ball_robotAngle
            move_d = (ball_d ** 2 + ball_d ** 2 
                        - 2 * ball_d * ball_d * math.cos(0.5 * math.pi - stick_ball_robotAngle)) ** 0.5
            self.motionProxy.moveInit()
            self.motionProxy.moveTo(0, move_d, -moveAngle)
        else:
            moveAngle = stick_ball_robotAngle - 0.5 * math.pi
            move_d = (ball_d ** 2 + ball_d ** 2 
                        - 2 * ball_d * ball_d * math.cos(stick_ball_robotAngle - 0.5 * math.pi)) ** 0.5 
            self.motionProxy.moveInit()
            self.motionProxy.moveTo(0, -move_d, moveAngle)

step3.

# encoding:utf-8
def walkToBall(self, min_ball_d=0.35, max_ball_theta=0.15):
    # 行走到球附近,若没有找到球则往前走一点
    #
    # 参数:
    #     min_ball_d:最小接近球的距离
    #     max_ball_theta:最大偏离角

    isfindBall = self.findBall()
    # 如果没有找到球则摇头找球
    if isfindBall is False:
        while True:
            isfindBall = self.moveheadToFindball()
            if isfindBall is False:
                self.motionProxy.moveInit()
                self.motionProxy.moveTo(0.5, 0, 0)
            else:
                break

    # 否则找到球,调整机器人身体,使其正对着球
    self.motionProxy.moveTo(0, 0, self.ball_info[2])
    self.motionProxy.angleInterpolationWithSpeed("HeadYaw", 0, 0.1)  # 头部回正

    moveTask_1 = self.motionProxy.post.moveTo(1.5 * self.ball_info[0], 0, 0)
    while True:
        isfindBall = self.findBall(self.pitchAngle, 0)
        if isfindBall is False:
            self.moveheadToFindball(pitchAngles=[-10], yawAngles=[-15, 15])
        ball_d = ((self.ball_info[0] ** 2 + self.ball_info[1] ** 2) ** 0.5)
        ball_theta = abs(self.ball_info[2])
        time.sleep(0.5)

        # 头不断往下低,防止看不到球
        Names = ["HeadPitch"]
        if ball_d > 0.4:
            self.pitchAngle = 0
        elif 0.3 < ball_d < 0.4:
            self.pitchAngle = (-100 * ball_d + 40)
        elif 0.02 < ball_d < 0.3:
            self.pitchAngle = 20
        self.motionProxy.angleInterpolationWithSpeed(Names, self.pitchAngle * rad, 0.1)

        # 到达最小距离内,停止
        if min_ball_d / 3 < ball_d < min_ball_d:
            self.tts.say("I am right.")
            self.motionProxy.stop(moveTask_1)
            time.sleep(0.5)
            self.motionProxy.moveInit()
            break
        # 偏差在范围内,继续走
        elif 0.02 < abs(ball_theta) < max_ball_theta:
            # 到达最小接近球的距离
            if min_ball_d / 3 < ball_d < min_ball_d:
                self.tts.say("I am right.")
                self.motionProxy.stop(moveTask_1)
                time.sleep(0.5)
                self.motionProxy.moveInit()
                break
            else:
                continue
                # 超过最大偏离角
        elif abs(ball_theta) > max_ball_theta:
            self.tts.say("I am wrong.")
            self.motionProxy.stop(moveTask_1)
            time.sleep(0.5)
            self.motionProxy.moveInit()
            self.motionProxy.moveTo(0, 0, self.ball_info[2])

            moveTask_1 = self.motionProxy.post.moveTo(1.5 * self.ball_info[0], 0, 0)

step4.

# encoding:utf-8

def forehandToHitball(self, hitSpeed):
    # 正手击球
    #
    # 参数:
    # hitSpeed:击球的力度

    # 手回正
    names = ["RShoulderPitch", "RShoulderRoll", "RElbowRoll", "RElbowYaw", "RWristYaw"]
    maxSpeedFraction = 0.1
    targetAngles = [[90 * rad, -20 * rad, 5 * rad, 90 * rad, 0 * rad],
                    [80 * rad, -40 * rad, 5 * rad, 90 * rad, 0 * rad],
                    [50 * rad, -45 * rad, 50 * rad, 90 * rad, -37 * rad],
                    [50 * rad, 5 * rad, 50 * rad, 90 * rad, 20 * rad]]  # 击球

    for targetAngle in targetAngles:
        if targetAngle == targetAngles[-1]:
            maxSpeedFraction = hitSpeed
        self.motionProxy.angleInterpolationWithSpeed(names, targetAngle, maxSpeedFraction)
        time.sleep(0.5)

def backhandToHitball(self, hitSpeed):
    
    # 反手击球
    #
    # 参数:
    #     hitSpeed:击球的力度

    names = ["RShoulderPitch", "RShoulderRoll", "RElbowRoll", "RElbowYaw", "RWristYaw"]
    maxSpeedFraction = 0.1

    targetAngles = [[90 * rad, -20 * rad, 5 * rad, 90 * rad, 0 * rad],  # 手回正
                    [80 * rad, -40 * rad, 5 * rad, 90 * rad, 0 * rad],
                    [50 * rad, -45 * rad, 50 * rad, 90 * rad, 0 * rad],
                    [50 * rad, 0 * rad, 70 * rad, 90 * rad, 40 * rad],
                    [60 * rad, 2 * rad, 60 * rad, 90 * rad, 40 * rad],
                    [60 * rad, -20 * rad, 60 * rad, 90 * rad, -20 * rad]]

    for targetAngle in targetAngles:
        if targetAngle == targetAngles[-1]:
            maxSpeedFraction = hitSpeed
        self.motionProxy.angleInterpolationWithSpeed(names, targetAngle, maxSpeedFraction)
        time.sleep(0.5)