A-A+

使用Scratch2和ROS进行机器人编程学习

2017年12月21日 ROS 评论 1 条 阅读 433 次

使用Scratch2和ROS进行机器人编程学习(适用于中小学机器人编程Scratch和ROS)

Scratch是一款由麻省理工学院(MIT)设计开发的少儿编程工具Python是近年来非常流行的机器人和人工智能编程语言ROS是机器人操作系统

参考JdeRobot的一篇详细介绍,就可以实现上述的功能,需要安装Scratch2、ROS Kinetic、Gazebo 7、JdeRobot、Python2.7等。

通过将Scratch2图形化编程语言转为Python,然后通过ROS消息机制控制Gazebo或实际机器人。

上海久牵志愿者服务社2017中国困境儿童关注日

~~信息化智能化时代下平等受教育的权利~~

1 先看如下一个简单的示例

1.1 新建hiros.bz2,如下:

1.2 通过下面命令将其转为Python:

  1. $ python scratch2python.py hiros.sb2
  2. Stringify:
  3. when @greenFlag clicked
  4. repeat 10
  5.     say 'Hello,ROS Kinetic!'
  6. end
  7. [WARN] Block <when @greenFlag clicked> not included yet
  8. -------------------
  9. #!/usr/bin/env python
  10. # -*- coding: utf-8 -*-
  11. import time
  12. import config
  13. import sys
  14. import comm
  15. import os
  16. import yaml
  17. from drone import Drone
  18. from robot import Robot
  19. def execute(robot):
  20.     try:
  21.         for i in range(10):
  22.             print('Hello,ROS Kinetic!')
  23.     except KeyboardInterrupt:
  24.         raise
  25. if __name__ == '__main__':
  26.     if len(sys.argv) == 2:
  27.         path = os.getcwd()
  28.         open_path = path[:path.rfind('src')] + 'cfg/'
  29.         filename = sys.argv[1]
  30.     else:
  31.         sys.exit("ERROR: Example:python my_generated_script.py cfgfile.yml")
  32.     # loading the ICE and ROS parameters
  33.     cfg = config.load(open_path + filename)
  34.     stream = open(open_path + filename, "r")
  35.     yml_file = yaml.load(stream)
  36.     for section in yml_file:
  37.         if section == 'drone':
  38.             #starting comm
  39.             jdrc = comm.init(cfg,'drone')
  40.             # creating the object
  41.             robot = Drone(jdrc)
  42.             break
  43.         elif section == 'robot':
  44.             #starting comm
  45.             jdrc = comm.init(cfg,'robot')
  46.             # creating the object
  47.             robot = Robot(jdrc)
  48.             break
  49.     # executing the scratch program
  50.     execute(robot)
  51. -------------------

2 控制机器人示例

是不是比较有趣,在不需购买任何设备的情况下,就可以用Scratch2进行ROS机器人编程。小学用Scratch2学习简单编程,中学用Python学习简单编程,大学用Python和C++学习复杂机器人编程,无缝衔接。

3 scratch2python.py

  1. #!/usr/bin/env python
  2. # -*- coding: utf-8 -*-
  3. __author__ = "Raul Perula-Martinez"
  4. __copyright__ = "JdeRobot project"
  5. __credits__ = ["Raul Perula-Martinez"]
  6. __license__ = "GPL v3"
  7. __version__ = "0.0.0"
  8. __maintainer__ = "Raul Perula-Martinez"
  9. __email__ = "raules@gmail.com"
  10. __status__ = "Development"
  11. import kurt
  12. import os
  13. import sys
  14. from difflib import SequenceMatcher
  15. from parse import parse, compile
  16. from termcolor import cprint
  17. GENERAL = [
  18.     ['end'''],
  19.     ['forever''while True:'],
  20.     ['if {} then''if %s:'],
  21.     ['else''else:'],
  22.     ['repeat {}''for i in range(%s):'],
  23.     ['say {}''print(%s)'],
  24.     ['set {} to {}''%s = %s'],
  25.     ['wait {} secs''time.sleep(%s)'],
  26. ]
  27. ROBOTICS = [
  28.     ['move robot {}''robot.move("%s")'],
  29.     ['move drone {}''robot.move("%s")'],
  30.     ['move robot {} speed {}''robot.move("%s", %s)'],
  31.     ['stop robot-drone''robot.stop()'],
  32.     ['turn robot-drone {}''robot.turn("%s")'],
  33.     ['turn robot {} speed {}''robot.turn("%s", %s)'],
  34.     ['take off drone''robot.take_off()'],
  35.     ['land drone''robot.land()'],
  36.     ['frontal laser distance''robot.get_laser_distance()'],
  37. ]
  38. def is_conditional(sentence):
  39.     """
  40.     Returns if a sentence is conditional or not.
  41.     @param sentence: The sentence to check.
  42.     @return: True if it has a conditional, False otherwise.
  43.     """
  44.     if "if" in sentence:
  45.         return True
  46.     return False
  47. def similar(a, b):
  48.     """
  49.     Returns the ratio value comparing two sentences.
  50.     @param a: First sentence.
  51.     @param b: Second sentence.
  52.     @return: The ratio of the similarity.
  53.     """
  54.     return SequenceMatcher(None, a, b).ratio()
  55. def sentence_mapping(sentence, threshold=None):
  56.     """
  57.     Maps a sentence and returns the original and the mapped.
  58.     @param sentence: The sentence to map.
  59.     @return: The original sentence and the mapped sentence.
  60.     """
  61.     found = False
  62.     options = []
  63.     original = None
  64.     translation = None
  65.     # first look for general blocks
  66.     for elem in GENERAL:
  67.         if elem[0][:3] == sentence.replace('    ''')[:3]:
  68.             options.append(elem)
  69.             found = True
  70.     # then look for robotics blocks
  71.     for elem in ROBOTICS:
  72.         if elem[0][:3] == sentence.replace('    ''').replace('(''')[:3]:
  73.             options.append(elem)
  74.             found = True
  75.     if found:
  76.         # select the option that better fits
  77.         l = [(m[0], m[1], similar(sentence, m[0])) for m in options]
  78.         original, translation, score = max(l, key=lambda item: item[2])
  79.         if threshold and score < threshold:
  80.             return NoneNone
  81.         # extract arguments
  82.         p = compile(original)
  83.         args = p.parse(sentence.replace('    '''))
  84.         if args:
  85.             args_aux = list(args)
  86.             # look for more blocks
  87.             for idx in range(len(args_aux)):
  88.                 new_ori, new_trans = sentence_mapping(args_aux[idx]) #sentence_mapping(args_aux[idx],0.8) --old
  89.                 if new_trans != None:
  90.                     args_aux[idx] = args_aux[idx].replace(new_ori, new_trans) #replace(args_aux[idx], new_trans)
  91.             translation = translation % tuple(args_aux)
  92.     return original, translation
  93. if __name__ == "__main__":
  94.     # get current working directory
  95.     path = os.getcwd()
  96.     open_path = path[:path.rfind('scripts')] + 'data/'
  97.     save_path = path[:path.rfind('scripts')] + 'src/scratch2jderobot/'
  98.     if len(sys.argv) == 2:
  99.         # template creation
  100.         template = "\
  101. #!/usr/bin/env python\n\
  102. # -*- coding: utf-8 -*-\n\n\
  103. import time\n\
  104. import config\n\
  105. import sys\n\
  106. import comm\n\
  107. import os\n\
  108. import yaml\n\n\
  109. from drone import Drone\n\
  110. from robot import Robot\n\n\
  111. def execute(robot):\n\
  112. \ttry:\n\
  113. \t%s\
  114. except KeyboardInterrupt:\n\
  115. \t\traise\n\n\
  116. if __name__ == '__main__':\n\
  117. \tif len(sys.argv) == 2:\n\
  118. \t\tpath = os.getcwd()\n\
  119. \t\topen_path = path[:path.rfind('src')] + 'cfg/'\n\
  120. \t\tfilename = sys.argv[1]\n\n\
  121. \telse:\n\
  122. \t\tsys.exit(\"ERROR: Example:python my_generated_script.py cfgfile.yml\")\n\n\
  123. \t# loading the ICE and ROS parameters\n\
  124. \tcfg = config.load(open_path + filename)\n\
  125. \tstream = open(open_path + filename, \"r\")\n\
  126. \tyml_file = yaml.load(stream)\n\n\
  127. \tfor section in yml_file:\n\
  128. \t\tif section == 'drone':\n\
  129. \t\t\t#starting comm\n\
  130. \t\t\tjdrc = comm.init(cfg,'drone')\n\n\
  131. \t\t\t# creating the object\n\
  132. \t\t\trobot = Drone(jdrc)\n\n\
  133. \t\t\tbreak\n\
  134. \t\telif section == 'robot':\n\
  135. \t\t\t#starting comm\n\
  136. \t\t\tjdrc = comm.init(cfg,'robot')\n\n\
  137. \t\t\t# creating the object\n\
  138. \t\t\trobot = Robot(jdrc)\n\n\
  139. \t\t\tbreak\n\
  140. \t# executing the scratch program\n\
  141. \texecute(robot)\n\n\
  142. "
  143.         # load the scratch project
  144.         p = kurt.Project.load(open_path + sys.argv[1])
  145.         # show the blocks included
  146.         for scriptable in p.sprites + [p.stage]:
  147.             for script in scriptable.scripts:
  148.                 # exclude definition scripts
  149.                 if "define" not in script.blocks[0].stringify():
  150.                     s = script
  151.         print("Stringify:")
  152.         sentences = []
  153.         for b in s.blocks:
  154.             print(b.stringify())
  155.             sentences += b.stringify().split('\n')
  156.         tab_seq = "\t"
  157.         python_program = ""
  158.         for s in sentences:
  159.             # count number of tabs
  160.             num_tabs = s.replace('    ', tab_seq).count(tab_seq)
  161.             python_program += tab_seq * (num_tabs + 1)
  162.             # pre-processing if there is a condition (operators and types)
  163.             if is_conditional(s):
  164.                 s = s.replace("'", "").replace("=", "==")
  165.             # mapping
  166.             original, translation = sentence_mapping(s)
  167.             # set the code
  168.             if translation != None:
  169.                 python_program += translation
  170.             else:
  171.                 cprint("[WARN] Block <%s> not included yet" % s, 'yellow')
  172.             python_program += "\n" + tab_seq
  173.         # join the template with the code and replace the tabs
  174.         file_text = template % python_program
  175.         file_text = file_text.replace(tab_seq, ' ' * 4)
  176.         print("\n-------------------")
  177.         cprint(file_text, 'green')
  178.         print("-------------------\n")
  179.         # save the code in a python file with the same name as sb2 file
  180.         file_name = sys.argv[1].replace('.sb2','.py')
  181.         f = open(save_path + file_name, "w")
  182.         f.write(file_text)
  183.         f.close()
  184.     else:
  185.         print(
  186.             "ERROR: Number of parameters incorrect. Example:\n\tpython scratch2python.py hello_world.sb2")
标签:

1 条留言  访客:1 条  博主:0 条

  1. 跨境电商之家

    这种文章一定要顶,谢谢了

给我留言

Copyright © ExBot易科机器人实验室 保留所有权利.   Theme   Robin modified by poyoten

用户登录

分享到: