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

举报
zhangrelay 发表于 2021/07/15 06:01:14 2021/07/15
【摘要】 使用Scratch3和ROS进行机器人编程学习(适用于中小学机器人编程Scratch和ROS) Scratch是一款由麻省理工学院(MIT)设计开发的少儿编程工具,Python是近年来非常流行的机器人和人工智能编程语言,ROS是机器人操作系统。 参考JdeRobot的一篇详细介绍,就可以实现上述的功能,需要安装Scratch2、ROS Kinetic、Gazebo 7、J...

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

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

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

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

codelab-adapter-docs.codelab.club  +  github.com/wwj718  +  

上海久牵志愿者服务社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 None, None
  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")

 

 

 

 

 

----

 

文章来源: zhangrelay.blog.csdn.net,作者:zhangrelay,版权归原作者所有,如需转载,请联系作者。

原文链接:zhangrelay.blog.csdn.net/article/details/78857311

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。