首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

小盆友也可以玩ROS——使用Scratch2和ROS进行机器人编程学习

本文为Exbot Robotics relayZhang博士原创文章,转载请注明,谢谢...

张博士为志愿服务者,热心困境儿童教育,为小朋友讲授机器人课程

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

使用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:

[python]view plaincopyprint?

$ python scratch2python.py hiros.sb2

Stringify:

when @greenFlag clicked

repeat10

say'Hello,ROS Kinetic!'

end

[WARN] Block notincluded yet

-------------------

#!/usr/bin/env python

# -*- coding: utf-8 -*-

importtime

importconfig

importsys

importcomm

importos

importyaml

fromdroneimportDrone

fromrobotimportRobot

defexecute(robot):

try:

foriinrange(10):

print('Hello,ROS Kinetic!')

exceptKeyboardInterrupt:

raise

if__name__ =='__main__':

iflen(sys.argv) ==2:

path = os.getcwd()

open_path = path[:path.rfind('src')] +'cfg/'

filename = sys.argv[1]

else:

sys.exit("ERROR: Example:python my_generated_script.py cfgfile.yml")

# loading the ICE and ROS parameters

cfg = config.load(open_path + filename)

stream = open(open_path + filename,"r")

yml_file = yaml.load(stream)

forsectioninyml_file:

ifsection =='drone':

#starting comm

jdrc = comm.init(cfg,'drone')

# creating the object

robot = Drone(jdrc)

break

elifsection =='robot':

#starting comm

jdrc = comm.init(cfg,'robot')

# creating the object

robot = Robot(jdrc)

break

# executing the scratch program

execute(robot)

-------------------

2 控制机器人示例

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

3 scratch2python.py

[python]view plaincopyprint?

#!/usr/bin/env python

# -*- coding: utf-8 -*-

__author__ ="Raul Perula-Martinez"

__copyright__ ="JdeRobot project"

__credits__ = ["Raul Perula-Martinez"]

__license__ ="GPL v3"

__version__ ="0.0.0"

__maintainer__ ="Raul Perula-Martinez"

__email__ ="raules@gmail.com"

__status__ ="Development"

importkurt

importos

importsys

fromdifflibimportSequenceMatcher

fromparseimportparse, compile

fromtermcolorimportcprint

GENERAL = [

['end',''],

['forever','while True:'],

['if {} then','if %s:'],

['else','else:'],

['repeat {}','for i in range(%s):'],

['say {}','print(%s)'],

['set {} to {}','%s = %s'],

['wait {} secs','time.sleep(%s)'],

]

ROBOTICS = [

['move robot {}','robot.move("%s")'],

['move drone {}','robot.move("%s")'],

['move robot {} speed {}','robot.move("%s", %s)'],

['stop robot-drone','robot.stop()'],

['turn robot-drone {}','robot.turn("%s")'],

['turn robot {} speed {}','robot.turn("%s", %s)'],

['take off drone','robot.take_off()'],

['land drone','robot.land()'],

['frontal laser distance','robot.get_laser_distance()'],

]

defis_conditional(sentence):

"""

Returns if a sentence is conditional or not.

@param sentence: The sentence to check.

@return: True if it has a conditional, False otherwise.

"""

if"if"insentence:

returnTrue

returnFalse

defsimilar(a, b):

"""

Returns the ratio value comparing two sentences.

@param a: First sentence.

@param b: Second sentence.

@return: The ratio of the similarity.

"""

returnSequenceMatcher(None, a, b).ratio()

defsentence_mapping(sentence, threshold=None):

"""

Maps a sentence and returns the original and the mapped.

@param sentence: The sentence to map.

@return: The original sentence and the mapped sentence.

"""

found =False

options = []

original =None

translation =None

# first look for general blocks

foreleminGENERAL:

ifelem[][:3] == sentence.replace(' ','')[:3]:

options.append(elem)

found =True

# then look for robotics blocks

foreleminROBOTICS:

ifelem[][:3] == sentence.replace(' ','').replace('(','')[:3]:

options.append(elem)

found =True

iffound:

# select the option that better fits

l = [(m[], m[1], similar(sentence, m[]))forminoptions]

original, translation, score = max(l, key=lambdaitem: item[2])

ifthresholdandscore < threshold:

returnNone,None

# extract arguments

p = compile(original)

args = p.parse(sentence.replace(' ',''))

ifargs:

args_aux = list(args)

# look for more blocks

foridxinrange(len(args_aux)):

new_ori, new_trans = sentence_mapping(args_aux[idx])#sentence_mapping(args_aux[idx],0.8) --old

ifnew_trans !=None:

args_aux[idx] = args_aux[idx].replace(new_ori, new_trans)#replace(args_aux[idx], new_trans)

translation = translation % tuple(args_aux)

returnoriginal, translation

if__name__ =="__main__":

# get current working directory

path = os.getcwd()

open_path = path[:path.rfind('scripts')] +'data/'

save_path = path[:path.rfind('scripts')] +'src/scratch2jderobot/'

iflen(sys.argv) ==2:

# template creation

template = "\

#!/usr/bin/env python\n\

# -*- coding: utf-8 -*-\n\n\

importtime\n\

importconfig\n\

importsys\n\

importcomm\n\

importos\n\

importyaml\n\n\

fromdroneimportDrone\n\

fromrobotimportRobot\n\n\

defexecute(robot):\n\

\ttry:\n\

\t%s\

exceptKeyboardInterrupt:\n\

\t\traise\n\n\

if__name__ =='__main__':\n\

\tif len(sys.argv) ==2:\n\

\t\tpath = os.getcwd()\n\

\t\topen_path = path[:path.rfind('src')] +'cfg/'\n\

\t\tfilename = sys.argv[1]\n\n\

\telse:\n\

\t\tsys.exit(\"ERROR: Example:python my_generated_script.py cfgfile.yml\")\n\n\

\t# loading the ICE and ROS parameters\n\

\tcfg = config.load(open_path + filename)\n\

\tstream = open(open_path + filename, \"r\")\n\

\tyml_file = yaml.load(stream)\n\n\

\tfor sectioninyml_file:\n\

\t\tif section =='drone':\n\

\t\t\t#starting comm\n\

\t\t\tjdrc = comm.init(cfg,'drone')\n\n\

\t\t\t# creating the object\n\

\t\t\trobot = Drone(jdrc)\n\n\

\t\t\tbreak\n\

\t\telif section =='robot':\n\

\t\t\t#starting comm\n\

\t\t\tjdrc = comm.init(cfg,'robot')\n\n\

\t\t\t# creating the object\n\

\t\t\trobot = Robot(jdrc)\n\n\

\t\t\tbreak\n\

\t# executing the scratch program\n\

\texecute(robot)\n\n\

"

# load the scratch project

p = kurt.Project.load(open_path + sys.argv[1])

# show the blocks included

forscriptableinp.sprites + [p.stage]:

forscriptinscriptable.scripts:

# exclude definition scripts

if"define"notinscript.blocks[].stringify():

s = script

print("Stringify:")

sentences = []

forbins.blocks:

print(b.stringify())

sentences += b.stringify().split('\n')

tab_seq ="\t"

python_program = ""

forsinsentences:

# count number of tabs

num_tabs = s.replace(' ', tab_seq).count(tab_seq)

python_program += tab_seq * (num_tabs +1)

# pre-processing if there is a condition (operators and types)

ifis_conditional(s):

s = s.replace("'", "").replace("=", "==")

# mapping

original, translation = sentence_mapping(s)

# set the code

iftranslation !=None:

python_program += translation

else:

cprint("[WARN] Block not included yet"% s,'yellow')

python_program +="\n"+ tab_seq

# join the template with the code and replace the tabs

file_text = template % python_program

file_text = file_text.replace(tab_seq,' '*4)

print("\n-------------------")

cprint(file_text,'green')

print("-------------------\n")

# save the code in a python file with the same name as sb2 file

file_name = sys.argv[1].replace('.sb2','.py')

f = open(save_path + file_name,"w")

f.write(file_text)

f.close()

else:

print(

"ERROR: Number of parameters incorrect. Example:\n\tpython scratch2python.py hello_world.sb2")

  • 发表于:
  • 原文链接http://kuaibao.qq.com/s/20171221G04E6Y00?refer=cp_1026
  • 腾讯「腾讯云开发者社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 cloudcommunity@tencent.com 删除。

扫码

添加站长 进交流群

领取专属 10元无门槛券

私享最新 技术干货

扫码加入开发者社群
领券