用于机器人的 Python : How to generate an app for localization of a Pepper robot

标签 python github nao-robot pepper

这些天我尝试使用 Github 项目 Jumpstarter( https://github.com/aldebaran/robot-jumpstarter ) 中的 pythonapp 模板生成一个应用程序来进行 Pepper 的本地化。我的基本想法是在生成的应用程序“Lokalisierung”(德语本地化)中结合 LandmarkDetector 模块。 mainlandmarkdetection

您可以在这里阅读“LandmarkDetector.py”、“main.py”和“MainLandmarkDetection.py”的完整代码:

“LandmarkDetector.py”:

#! /usr/bin/env python
# -*- encoding: UTF-8 -*-

"""Example: Demonstrates a way to localize the robot with ALLandMarkDetection"""

import qi
import time
import sys
import argparse
import math
import almath


class LandmarkDetector(object):
"""
We first instantiate a proxy to the ALLandMarkDetection module
Note that this module should be loaded on the robot's naoqi.
The module output its results in ALMemory in a variable
called "LandmarkDetected".
We then read this ALMemory value and check whether we get
interesting things.
After that we get the related position of the landmark compared to robot.
"""
def __init__(self, app):
    """
    Initialisation of qi framework and event detection.
    """
    super(LandmarkDetector, self).__init__()

    app.start()
    session = app.session
    # Get the service ALMemory.
    self.memory = session.service("ALMemory")
    # Connect the event callback.

    # Get the services ALMotion & ALRobotPosture.

    self.motion_service = session.service("ALMotion")
    self.posture_service = session.service("ALRobotPosture")

    self.subscriber = self.memory.subscriber("LandmarkDetected")
    print "self.subscriber = self.memory.subscriber(LandmarkDetected)"
    self.subscriber.signal.connect(self.on_landmark_detected)
    print "self.subscriber.signal.connect(self.on_landmark_detected)"
    # Get the services ALTextToSpeech, ALLandMarkDetection and ALMotion.
    self.tts = session.service("ALTextToSpeech")
    self.landmark_detection = session.service("ALLandMarkDetection")
  #  print "self.landmark_detection" is repr(self.landmark_detection)
    self.motion_service = session.service("ALMotion")
    self.landmark_detection.subscribe("LandmarkDetector", 500, 0.0 )
    print "self.landmark_detection.subscribe(LandmarkDetector, 500, 0.0 )"
    self.got_landmark = False
    # Set here the size of the landmark in meters.
    self.landmarkTheoreticalSize = 0.06 #in meters 0  #.05 or 0.06?
    # Set here the current camera ("CameraTop" or "CameraBottom").
    self.currentCamera = "CameraTop"

def on_landmark_detected(self, markData):
    """
    Callback for event LandmarkDetected.
    """
    while markData == [] :  # empty value when the landmark disappears
        self.got_landmark = False
        self.motion_service.moveTo(0, 0, 0.1 * math.pi)

    if not self.got_landmark:  # only speak the first time a landmark appears
        self.got_landmark = True

#stop.motion_service.moveTo

        print "Ich sehe eine Landmarke! "
        self.tts.say("Ich sehe eine Landmarke! ")

        # Retrieve landmark center position in radians.
        wzCamera = markData[1][0][0][1]
        wyCamera = markData[1][0][0][2]

        # Retrieve landmark angular size in radians.
        angularSize = markData[1][0][0][3]

        # Compute distance to landmark.
        distanceFromCameraToLandmark = self.landmarkTheoreticalSize / ( 2 * math.tan( angularSize / 2))

        # Get current camera position in NAO space.
        transform = self.motion_service.getTransform(self.currentCamera, 2, True)
        transformList = almath.vectorFloat(transform)
        robotToCamera = almath.Transform(transformList)

        # Compute the rotation to point towards the landmark.
        cameraToLandmarkRotationTransform = almath.Transform_from3DRotation(0, wyCamera, wzCamera)

        # Compute the translation to reach the landmark.
        cameraToLandmarkTranslationTransform = almath.Transform(distanceFromCameraToLandmark, 0, 0)

        # Combine all transformations to get the landmark position in NAO space.
        robotToLandmark = robotToCamera * cameraToLandmarkRotationTransform *cameraToLandmarkTranslationTransform

#    robotTurnAroundAngle = almath.rotationFromAngleDirection(0, 1, 1, 1)
#        print "robotTurnAroundAngle = ", robotTurnAroundAngle

        print "x " + str(robotToLandmark.r1_c4) + " (in meters)"
        print "y " + str(robotToLandmark.r2_c4) + " (in meters)"
        print "z " + str(robotToLandmark.r3_c4) + " (in meters)"

def run(self):
    """
    Loop on, wait for events until manual interruption.
    """

    # Wake up robot
    self.motion_service.wakeUp()

    # Send robot to Pose Init
    self.posture_service.goToPosture("StandInit", 0.5)

    # Example showing how to get a simplified robot position in world.
    useSensorValues = False
    result = self.motion_service.getRobotPosition(useSensorValues)
    print "Robot Position", result

    # Example showing how to use this information to know the robot's diplacement.
    useSensorValues = False
    #   initRobotPosition = almath.Pose2D(self.motion_service.getRobotPosition(useSensorValues))

    # Make the robot move
    for i in range(1, 12, 1):
        self.motion_service.moveTo(0, 0, 0.1 * math.pi)
        print "self.motion_service.moveTo(0, 0, (0.1)*math.pi)"

    print "Starting LandmarkDetector"
    try:
        while True:
            time.sleep(1)
    except KeyboardInterrupt:
        print "Interrupted by user, stopping LandmarkDetector"
        self.landmark_detection.unsubscribe("LandmarkDetector")
        #stop
        sys.exit(0)


if __name__ == "__main__":


    parser = argparse.ArgumentParser()
    parser.add_argument("--ip", type=str, default="10.0.0.10",
                    help="Robot IP address. On robot or Local Naoqi: use 
'10.0.0.10'.")
    parser.add_argument("--port", type=int, default=9559,
                    help="Naoqi port number")

    args = parser.parse_args()
    try:
        # Initialize qi framework.
        connection_url = "tcp://" + args.ip + ":" + str(args.port)
        app = qi.Application(["LandmarkDetector", "--qi-url=" + connection_url])
    except RuntimeError:
        print ("Can't connect to Naoqi at ip \"" + args.ip + "\" on port " + str(args.port) +".\n"
               "Please check your script arguments. Run with -h option for help.")
        sys.exit(1)
    landmark_detector = LandmarkDetector(app)
    landmark_detector.run()

“main.py”:

""" A sample showing how to make a Python script as an app. """

version = "0.0.8"

copyright = "Copyright 2015, Aldebaran Robotics" author = 'YOURNAME' email = 'YOUREMAIL@aldebaran.com'

import stk.runner
import stk.events
import stk.services
import stk.logging

class Activity(object):

"A sample standalone app, that demonstrates simple Python usage" APP_ID = "com.aldebaran.lokalisierung"

def __init__(self, qiapp):
    self.qiapp = qiapp
    self.events = stk.events.EventHelper(qiapp.session)
    self.s = stk.services.ServiceCache(qiapp.session)
    self.logger = stk.logging.get_logger(qiapp.session, self.APP_ID)

def on_touched(self, *args):
    "Callback for tablet touched."
    if args:
        self.events.disconnect("ALTabletService.onTouchDown")
        self.logger.info("Tablet touched: " + str(args))
        self.s.ALTextToSpeech.say("Yay!")
        self.stop()

def on_start(self):
    "Ask to be touched, waits, and exits."
    # Two ways of waiting for events
    # 1) block until it's called

    self.s.ALTextToSpeech.say("Touch my forehead.")
    self.logger.warning("Listening for touch...")
    while not self.events.wait_for("FrontTactilTouched"):
        pass

    # 2) explicitly connect a callback
    if self.s.ALTabletService:
        self.events.connect("ALTabletService.onTouchDown", self.on_touched)
        self.s.ALTextToSpeech.say("okay, now touch my tablet.")
        # (this allows to simltaneously speak and watch an event)
    else:
        self.s.ALTextToSpeech.say("touch my tablet ... oh. " + \
            "I don't haave one.")
        self.stop()

def stop(self):
    "Standard way of stopping the application."
    self.qiapp.stop()

def on_stop(self):
    "Cleanup"
    self.logger.info("Application finished.")
    self.events.clear()

if __name__ == "__main__":


    stk.runner.run_activity(Activity)

“MainLandmarkDetection.py”:

#! /usr/bin/env python
# -*- encoding: UTF-8 -*-

"""A sample showing how to make a Python script as an app to localize the robot with ALLandMarkDetection"""

version = "0.0.8"

copyright = "Copyright 2015, Aldebaran Robotics"

author = 'YOURNAME'

email = 'YOUREMAIL@aldebaran.com'

import stk.runner
import stk.events
import stk.services
import stk.logging
import time
import sys
import math
import almath

class Activity(object):

"A sample standalone app, that demonstrates simple Python usage" APP_ID = "com.aldebaran.lokalisierung"

def __init__(self, qiapp):

    self.qiapp = qiapp
    self.events = stk.events.EventHelper(qiapp.session)
    self.s = stk.services.ServiceCache(qiapp.session)
    self.logger = stk.logging.get_logger(qiapp.session, self.APP_ID)
    self.qiapp.start()
    session = qiapp.session
    # Get the service ALMemory.
    self.memory = session.service("ALMemory")
    # Connect the event callback.

    # Get the services ALMotion & ALRobotPosture.

    self.motion_service = session.service("ALMotion")
    self.posture_service = session.service("ALRobotPosture")

    self.subscriber = self.memory.subscriber("LandmarkDetected")
    print "self.subscriber = self.memory.subscriber(LandmarkDetected)"
    self.subscriber.signal.connect(self.on_landmark_detected)
    print "self.subscriber.signal.connect(self.on_landmark_detected)"
    # Get the services ALTextToSpeech, ALLandMarkDetection and ALMotion.
    self.tts = session.service("ALTextToSpeech")
    self.landmark_detection = session.service("ALLandMarkDetection")
    #  print "self.landmark_detection" is repr(self.landmark_detection)
    self.motion_service = session.service("ALMotion")
    self.landmark_detection.subscribe("Activity", 500, 0.0)
    print "self.landmark_detection.subscribe(Activity, 500, 0.0 )"
    self.got_landmark = False
    # Set here the size of the landmark in meters.
    self.landmarkTheoreticalSize = 0.06  # in meters 0  #.05 or 0.06?
    # Set here the current camera ("CameraTop" or "CameraBottom").
    self.currentCamera = "CameraTop"

def on_landmark_detected(self, markData):
    """
    Callback for event LandmarkDetected.
    """
    while markData == []:  # empty value when the landmark disappears
        self.got_landmark = False
    #           self.motion_service.moveTo(0, 0, 0.1 * math.pi)

    if not self.got_landmark:  # only speak the first time a landmark appears
        self.got_landmark = True

        # stop.motion_service.moveTo

        print "Ich sehe eine Landmarke! "
        #          self.tts.say("Ich sehe eine Landmarke! ")

        # Retrieve landmark center position in radians.
        wzCamera = markData[1][0][0][1]
        wyCamera = markData[1][0][0][2]

        # Retrieve landmark angular size in radians.
        angularSize = markData[1][0][0][3]

        # Compute distance to landmark.
        distanceFromCameraToLandmark = self.landmarkTheoreticalSize / (2 * math.tan(angularSize / 2))

        # Get current camera position in NAO space.
        transform = self.motion_service.getTransform(self.currentCamera, 2, True)
        transformList = almath.vectorFloat(transform)
        robotToCamera = almath.Transform(transformList)

        # Compute the rotation to point towards the landmark.
        cameraToLandmarkRotationTransform = almath.Transform_from3DRotation(0, wyCamera, wzCamera)

        # Compute the translation to reach the landmark.
        cameraToLandmarkTranslationTransform = almath.Transform(distanceFromCameraToLandmark, 0, 0)

        # Combine all transformations to get the landmark position in NAO space.
        robotToLandmark = robotToCamera * cameraToLandmarkRotationTransform * cameraToLandmarkTranslationTransform

        #    robotTurnAroundAngle = almath.rotationFromAngleDirection(0, 1, 1, 1)
        #        print "robotTurnAroundAngle = ", robotTurnAroundAngle

        print "x " + str(robotToLandmark.r1_c4) + " (in meters)"
        print "y " + str(robotToLandmark.r2_c4) + " (in meters)"
        print "z " + str(robotToLandmark.r3_c4) + " (in meters)"

def run(self):
    """
    Loop on, wait for events until manual interruption.
    """

    # Wake up robot
    self.motion_service.wakeUp()

    # Send robot to Pose Init
    self.posture_service.goToPosture("StandInit", 0.5)

    # Example showing how to get a simplified robot position in world.
    useSensorValues = False
    result = self.motion_service.getRobotPosition(useSensorValues)
    print "Robot Position", result

    # Example showing how to use this information to know the robot's diplacement.
    useSensorValues = False
    #   initRobotPosition = almath.Pose2D(self.motion_service.getRobotPosition(useSensorValues))

    # Make the robot move
    for i in range(1, 20, 1):
        self.motion_service.moveTo(0, 0, 0.1 * math.pi)
        print "self.motion_service.moveTo(0, 0, (0.1)*math.pi)"

    print "Starting Activity"
    try:
        while True:
            time.sleep(1)
    except KeyboardInterrupt:
        print "Interrupted by user, stopping Activity"
        self.landmark_detection.unsubscribe("Activity")
        # stop
        sys.exit(0)

    def stop(self):
        "Standard way of stopping the application."
        self.qiapp.stop()

    def on_stop(self):
        "Cleanup"
        self.logger.info("Application finished.")
        self.events.clear()

if __name__ == "__main__":



    stk.runner.run_activity(Activity)

    landmark_detector = Activity()

    landmark_detector.run()

这就是它在 cmd.exe 中的工作方式:

bugs_for_mainlandmarkdetection02 bugs_for_mainlandmarkdetection03 由于图像中的错误,我对程序末尾第 157 行中的“landmark_detector = Activity()”参数有疑问,我应该传递该错误。在阅读 Stackoverflow Python: TypeError: __init__() takes exactly 2 arguments (1 given) 此处类似问题的答案后,我还是一头雾水。我认为它应该是赋予“qiapp”的值,但是什么值?

最诚挚的问候, 弗雷德里克

最佳答案

实际上,当你打电话时

stk.runner.run_activity(Activity)

...它将使用正确的参数为您实例化该事件对象,您不需要在 MainLandmarkDetector.py 中使用地标检测器 = Activity() 等

如果这个对象有一个名为 on_start 的方法,那么一旦一切准备就绪,该方法就会被调用(因此您可能只需将 run() 方法重命名为 on_start()

另请注意,您可以不调用 sys.stop(),而只调用 self.stop() 或 self.qiapp.stop() (这在让 on_stop 中的清理代码被调用方面更干净一些) ,如果您需要取消订阅等)

参见here有关 stk.runner 的一些文档。

另请注意,而不是这样做

self.motion_service = session.service("ALMotion")
(...)
transform = self.motion_service.getTransform(self.currentCamera, 2, True)

你可以直接这样做

transform = self.s.ALMotion.getTransform(self.currentCamera, 2, True)

...(在我看来)这使得更容易准确地看到正在做什么(并减少变量的数量)。

关于用于机器人的 Python : How to generate an app for localization of a Pepper robot,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51177486/

相关文章:

python - Django 的双下划线

windows - 将 Github 远程添加到 GitKraken

github - 如何避免使用 API 延迟 github 拉取请求合并

java - JAVA中使用键盘控制机器人

Python 脚本连接到 NAO 机器人

javascript - Django:如何保存mxGraph,以便当用户刷新图表时保持不变? (异步)

python - 如何使用spark session 导入python文件?

c++ - 当项目依赖于用旧 c++ 编译的 .so 库时,用 c++11 编译

python - 即使退出状态非零,也使用 check_output 获取输出

Jenkins - 获取远程仓库 'origin' 时出错