用于机器人技术的 Python第 5 单元 类和面向对象程序设计- 摘要预计完成时间:2 小时在本单元中,您将学习如何正确地组织代码,以防止在事情变得复杂时(通常在使用机器人时)出现代码混乱的情况。Python 中使用的组织方法/原则称为面向对象编程,它基于Python 类的概念。- 摘要结束5.1 面向对象程序设计在我们迄今为止编写的所有程序中,我们都是围绕方法来设计程序的,这些方法可以操作存储在变量中的数据。这就是所谓的面向过程的编程方式。还有另一种编程方式!这种编程方式基于数据和方法的结合,并将它们封装在称为对象(也称为类)的东西中。这种编程方式被称为面向对象编程,或 OOP。在大多数情况下,您仍然会在简单的项目中使用过程式编程,但在编写更大、更复杂的程序时,这种方法就会变得很麻烦。在这种情况下,使用 OOP 会好得多,因为你的代码会更有条理,也更容易理解、调试、维护和升级。因此,正
第 5 单元 类和面向对象程序设计
- 摘要
预计完成时间:2 小时
在本单元中,您将学习如何正确地组织代码,以防止在事情变得复杂时(通常在使用机器人时)出现代码混乱的情况。Python 中使用的组织方法/原则称为面向对象编程,它基于Python 类的概念。
- 摘要结束
5.1 面向对象程序设计
在我们迄今为止编写的所有程序中,我们都是围绕方法来设计程序的,这些方法可以操作存储在变量中的数据。这就是所谓的面向过程的编程方式。
还有另一种编程方式!这种编程方式基于数据和方法的结合,并将它们封装在称为对象(也称为类)的东西中。这种编程方式被称为面向对象编程,或 OOP。
在大多数情况下,您仍然会在简单的项目中使用过程式编程,但在编写更大、更复杂的程序时,这种方法就会变得很麻烦。在这种情况下,使用 OOP 会好得多,因为你的代码会更有条理,也更容易理解、调试、维护和升级。
因此,正如我之前所说,OOP 基于 "对象 "的概念。这些对象通常由两方面定义:
属性:这是与对象相关的数据,以字段的形式定义。
方法:这些是与对象相关的程序或方法。
对象最重要的特点是,与之关联的方法可以访问和修改与之关联的对象的数据字段。
5.2 什么是 Python 类?
所以,一切听起来都超酷、超有趣,但我还没读过一个关于 Python 类的字。Python 类到底是什么?让我们来看看!
Python 类基本上就是创建对象的代码模板。
例如,下面的Jedi类描述了如何创建 Jedi 类型的对象,因此你可以使用该类型的对象,按照类定义的方式存储和操作数据。
例如,如果我的代码创建了Jedi 类,那么我就可以通过以下操作创建该类型的对象:
在 [ ] 中:
my_object = Jedi("Qui-Gong-Jin")这意味着对象my_object是一个Jedi 类型的变量。
请记住,我们在前几章中已经使用过。例如
在 [ ] 中:
rc = RobotControl()
在前面的代码中,我们创建了一个名为 rc类型的 RobotControl.
与 Jedi类和 RobotControl类的区别在于,前者需要一个参数来创建对象(需要Jedi 的名称),而后者则不需要任何参数来创建 obejct。
注:当我们创建一个X 类的变量时,我们就说已经创建了一个X 类的实例。在上面的代码中,我们创建了一个类Jedi 的实例。
5.3 如何在 Python 中定义类
下面是一个定义 Python 类的简单示例,该类名为 Jedi:
Python 文件: jedi_class.py
在 [ ] 中:
class Jedi:
def __init__(self, name):
self.jedi_name = name
def say_hi(self):
print('Hello, my name is ', self.jedi_name)
j1 = Jedi('ObiWan')
j1.say_hi()
j2 = Jedi('Anakin')
j2.say_hi()
结束 Python 文件: jedi_class.py
上述代码由两部分组成:
在这里我们定义了
在这里,我们使用该定义来创建和使用类型为
Jedi(j1和j2)
5.3.1 类的定义
让我们快速分析一下上面的类。我们首先看到的是标签类和名称 Jedi.
在 [ ] 中:
class Jedi:
也就是说,让我们定义一个名为 Jedi.然后,该行下面包含缩进的所有内容都属于该类的代码。
让我们来看看一个类可能包含的不同部分。
5.3.2 类的方法
然后,我们继续标记 def.正如你在上一章中所知道的,这意味着接下来是一个方法的定义。不过,在本例中,方法只是为类定义的 Jedi因为,正如你所看到的,它在类中有一个缩进。
如您所见,在代码中,该类有两个方法:
在 [ ] 中:
def __init__(self,name):
在 [ ] 中:
def say_hi(self):
请注意,每个方法都包含 self关键字作为参数。该关键字表示这些方法属于该类。包含 self关键字是类中每个方法的必选项。
5.3.3 方法只属于类是什么意思?
这意味着只能通过类的实例来调用该方法。也就是说,你不能在程序中通过 say_hi()方法:
在 [ ] 中:
say_hi()
要调用该方法,首先需要创建一个*Jedi* 类的实例,然后调用该方法。就像这样
在 [ ] 中:
j = Jedi()
j.say_hi()
下面你就会明白其中的原因。
5.3.4 类构造函数
在上面定义的两个方法中,有一个方法非常特别,被称为类的构造函数。该方法如下:
在 [ ] 中:
def __init__(self, name):
self.jedi_name = name
对于您创建的任何类 Jedi类、 RobotControl类或其他任何你可能发明的类),名为 __init__的方法称为类的构造函数。
构造函数有什么特别之处?每次创建类的新实例时,(Python 系统)都会自动调用构造函数。
例如,当我们创建了 Jedi类的实例时,调用了 __init__(self, name)方法被调用。如前几章所述,参数 name是提供给构造函数的。因此,构造函数使用该参数将其存储在变量 self.jedi_name.
类的构造函数是一个非常重要的方法,因为它用于根据提供的参数,用适当的值初始化类的实例。例如,在上面的代码中
在 [ ] 中:
j1 = Jedi('ObiWan')我们将创建一个 Jedi实例,并为其提供参数 ObiWan.参数 __init__方法(类的构造函数 Jedi类的方法(类的构造函数 Jedi类的构造函数)用来初始化 self.jedi_name变量。这就是我们在构造函数中做的唯一一件事,但我们还可以添加其他任何需要的东西,以使 Jedi实例正确配置所需的其他内容。
5.3.5 类的变量
类内部通常有变量,用于为每个实例存储适当的值。通过这些变量,可以将同一个类的每个实例区分开来。例如,在上面的代码中,类 Jedi类中有一个名为 self.jedi_name.该变量必须包含该类每个实例的绝地名称。
这就是为什么在后面的代码中,我们会有:
在 [ ] 中:
j1 = Jedi('ObiWan')
j2 = Jedi('Anakin')
我们为同一个类创建了两个不同的实例。但每个实例都与不同的Jedi 名称相关联。的值为 self.jedi_name为 j1的值是 ObiWan的值是 self.jedi_name为 j2的值是 Anakin.
看到了吗?你可以为一个类创建任意多的实例,但每个实例的类参数值都是不同的。
重要提示:要创建一个类的变量,必须以前缀 self.开头,然后是变量名。记住要在类的任何位置添加 self.前缀。
类的变量就像该类的*全局变量*!这意味着什么?这意味着变量可以在属于该类的任何方法中使用,就像我们在第四单元中使用 global关键字。
重要 2:这是使用类的要点之一。你不必使用全局变量,因为这些变量可以在代码的任何部分被访问,从而造成混乱。通过将变量封装在类中,只有类中的方法才能访问这些变量,因此,你可以减少弄乱的机会。
重要事项 3: 从现在起,您不能在程序中使用 globalglobal 关键字。这是非常不好的做法!相反,您应该组织您的 Python 程序,使用不需要 global 变量的类(相反,它们使用类的变量)。
5.3.6 为类添加方法
除了类的构造函数外,您还可以定义任何其他方法,使您的类变得有用。例如,在 Jedi类中,有一个名为 say_hi()的方法,它可以使类打印一条 hello 消息。
在 [ ] 中:
def say_hi(self):
print('Hello, my name is', self.jedi_name)
这是类的另一个方法。在本例中,它只包含一个简单的打印,其中考虑到了变量的值 self.jedi_name.
重要:正如您在方法 say_hi()中,该方法可以访问类的变量 self.jedi_name变量,而无需使用 global关键字,因为 self.jedi_name是类的一个变量,因此类的任何方法都可以访问它。
注意:类的方法可以修改类的任何变量!它们可以读取甚至修改这些值。
5.3.7 调用类方法
如上所述,要调用属于类的方法,首先需要创建一个类的实例。这样就可以创建不同的类实例,在调用其成员方法时产生不同的结果。
例如,在上面的代码中,我们有如下代码:
在 [ ] 中:
j1 = Jedi('ObiWan')
j1.say_hi()
j2 = Jedi('Anakin')
j2.say_hi()
这意味着我们正在为同一个类创建两个不同的实例*Jedi* 。每个实例都与不同的Jedi 有关。因此,为每个实例调用 say_hi()方法会产生不同的结果。
如果运行上面的代码,应该会得到这样的输出结果:
在 [ ] 中:
Hello, my name is ObiWan
Hello, my name is Anakin
第一句 Hello ...句是调用 say_hi()j1方法的输出。 Jedi类。第二句是调用该类第二个实例 (j2) 的方法的输出结果。 Jedi类。
这就是类的魅力所在:根据类变量的内部值,同一个方法可以得到不同的结果!
- 练习 5.1 -
创建一个 Python 程序,让机器人进行 2 次方格运动。第二个方块的大小是第一个方块的两倍。

为控制机器人而需要传递给方法的所有参数(motion, clockwise, speed, time ,可能还有其他参数)都必须声明为类的属性。
您需要
导入
RobotControl类。使用
move_straight_time()和turn()方法。创建类的构造函数
为你的类创建必要的方法,以便执行正方形。
创建 2 个不同的类实例,每个方块运动一个。
- 练习 5.1 - 结束
- 练习 5.1 的解法

请尽量自己做,除非遇到困难或需要灵感。如果你能为每一个练习而奋斗,你会学到更多。
test_class.py
在 [ ] 中:
from robot_control_class import RobotControl
class MoveRobot:
def __init__(self, motion, clockwise, speed, time):
self.robotcontrol = RobotControl(robot_name="summit")
self.motion = motion
self.clockwise = clockwise
self.speed = speed
self.time = time
self.time_turn = 7.0 # This is an estimate time in which the robot will rotate 90 degrees
def do_square(self):
i = 0
while (i < 4):
self.move_straight()
self.turn()
i+=1
def move_straight(self):
self.robotcontrol.move_straight_time(self.motion, self.speed, self.time)
def turn(self):
self.robotcontrol.turn(self.clockwise, self.speed, self.time_turn)
mr1 = MoveRobot('forward', 'clockwise', 0.3, 4)
mr1.do_square()
mr2 = MoveRobot('forward', 'clockwise', 0.3, 8)
mr2.do_square()
- 练习 5.1 的最终解答 -
5.4 班级RobotControl 如何运作
现在,您已经掌握了编写自己的 Python 程序的所有知识,是时候检查您在整个课程中使用的 RobotControl类!
这是该类的代码:
机器人控制类.py
在 [ ] 中:
#!/usr/bin/env python
import rospy
from geometry_msgs.msg import Twist
from sensor_msgs.msg import LaserScan
import time
class RobotControl():
def __init__(self, robot_name="turtlebot"):
rospy.init_node('robot_control_node', anonymous=True)
if robot_name == "summit":
rospy.loginfo("Robot Summit...")
cmd_vel_topic = "/summit_xl_control/cmd_vel"
# We check sensors are working
self._check_summit_laser_ready()
else:
rospy.loginfo("Robot Turtlebot...")
cmd_vel_topic='/cmd_vel'
self._check_laser_ready()
# We start the publisher
self.vel_publisher = rospy.Publisher(cmd_vel_topic, Twist, queue_size=1)
self.cmd = Twist()
self.laser_subscriber = rospy.Subscriber(
'/kobuki/laser/scan', LaserScan, self.laser_callback)
self.summit_laser_subscriber = rospy.Subscriber(
'/hokuyo_base/scan', LaserScan, self.summit_laser_callback)
self.ctrl_c = False
self.rate = rospy.Rate(1)
rospy.on_shutdown(self.shutdownhook)
def _check_summit_laser_ready(self):
self.summit_laser_msg = None
rospy.loginfo("Checking Summit Laser...")
while self.summit_laser_msg is None and not rospy.is_shutdown():
try:
self.summit_laser_msg = rospy.wait_for_message("/hokuyo_base/scan", LaserScan, timeout=1.0)
rospy.logdebug("Current /hokuyo_base/scan READY=>" + str(self.summit_laser_msg))
except:
rospy.logerr("Current /hokuyo_base/scan not ready yet, retrying for getting scan")
rospy.loginfo("Checking Summit Laser...DONE")
return self.summit_laser_msg
def _check_laser_ready(self):
self.laser_msg = None
rospy.loginfo("Checking Laser...")
while self.laser_msg is None and not rospy.is_shutdown():
try:
self.laser_msg = rospy.wait_for_message("/kobuki/laser/scan", LaserScan, timeout=1.0)
rospy.logdebug("Current /kobuki/laser/scan READY=>" + str(self.laser_msg))
except:
rospy.logerr("Current /kobuki/laser/scan not ready yet, retrying for getting scan")
rospy.loginfo("Checking Laser...DONE")
return self.laser_msg
def publish_once_in_cmd_vel(self):
"""
This is because publishing in topics sometimes fails the first time you publish.
In continuous publishing systems, this is no big deal, but in systems that publish only
once, it IS very important.
"""
while not self.ctrl_c:
connections = self.vel_publisher.get_num_connections()
if connections > 0:
self.vel_publisher.publish(self.cmd)
#rospy.loginfo("Cmd Published")
break
else:
self.rate.sleep()
def shutdownhook(self):
# works better than the rospy.is_shutdown()
self.ctrl_c = True
def laser_callback(self, msg):
self.laser_msg = msg
def summit_laser_callback(self, msg):
self.summit_laser_msg = msg
def get_laser(self, pos):
time.sleep(1)
return self.laser_msg.ranges[pos]
def get_laser_summit(self, pos):
time.sleep(1)
return self.summit_laser_msg.ranges[pos]
def get_front_laser(self):
time.sleep(1)
return self.laser_msg.ranges[360]
def get_laser_full(self):
time.sleep(1)
return self.laser_msg.ranges
def stop_robot(self):
#rospy.loginfo("shutdown time! Stop the robot")
self.cmd.linear.x = 0.0
self.cmd.angular.z = 0.0
self.publish_once_in_cmd_vel()
def move_straight(self):
# Initilize velocities
self.cmd.linear.x = 0.5
self.cmd.linear.y = 0
self.cmd.linear.z = 0
self.cmd.angular.x = 0
self.cmd.angular.y = 0
self.cmd.angular.z = 0
# Publish the velocity
self.publish_once_in_cmd_vel()
def move_straight_time(self, motion, speed, time):
# Initilize velocities
self.cmd.linear.y = 0
self.cmd.linear.z = 0
self.cmd.angular.x = 0
self.cmd.angular.y = 0
self.cmd.angular.z = 0
if motion == "forward":
self.cmd.linear.x = speed
elif motion == "backward":
self.cmd.linear.x = - speed
i = 0
# loop to publish the velocity estimate, current_distance = velocity * (t1 - t0)
while (i <= time):
# Publish the velocity
self.vel_publisher.publish(self.cmd)
i += 1
self.rate.sleep()
# set velocity to zero to stop the robot
self.stop_robot()
s = "Moved robot " + motion + " for " + str(time) + " seconds at " str(speed) + " m/s"
return s
def turn(self, clockwise, speed, time):
# Initilize velocities
self.cmd.linear.x = 0
self.cmd.linear.y = 0
self.cmd.linear.z = 0
self.cmd.angular.x = 0
self.cmd.angular.y = 0
if clockwise == "clockwise":
self.cmd.angular.z = -speed
else:
self.cmd.angular.z = speed
i = 0
# loop to publish the velocity estimate, current_distance = velocity * (t1 - t0)
while (i <= time):
# Publish the velocity
self.vel_publisher.publish(self.cmd)
i += 1
self.rate.sleep()
# set velocity to zero to stop the robot
self.stop_robot()
s = "Turned robot " + clockwise + " for " + str(time) + " seconds at " str(speed) + " radians/second"
return s
if __name__ == '__main__':
robotcontrol_object = RobotControl()
try:
robotcontrol_object.move_straight()
except rospy.ROSInterruptException:
pass
机器人控制类.py
5.4.1 代码说明
首先,请允许我指出,在本课程中,已经介绍了一些 ROS 概念。这可能会让你现在有些困惑,至少在你参加之前是这样。总之,在这一点上,你应该能够完全理解本课的不同部分及其主要结构。
首先,我们在这里找到了所有的进口商品:
在 [ ] 中:
import rospy
from geometry_msgs.msg import Twist
from sensor_msgs.msg import LaserScan
import time
正如我们在第二单元已经学过的,导入允许我们在程序中包含在其他 Python 模块中创建的代码。在本例中,我们将导入一些与 ROS 相关的模块,以及在之前的课程中已经使用过的时间模块。
接下来,我们可以看看该类的定义。
在 [ ] 中:
class RobotControl():
这里没有什么新东西。我们正在定义一个名为 RobotControl的类,它不接受任何参数。让我们继续!
现在我们可以看到 __init__方法,它也被称为构造函数,大家已经知道了。
在 [ ] 中:
def __init__(self, robot_name="turtlebot"):
rospy.init_node('robot_control_node', anonymous=True)
if robot_name == "summit":
rospy.loginfo("Robot Summit...")
cmd_vel_topic = "/summit_xl_control/cmd_vel"
# We check sensors working
self._check_summit_laser_ready()
else:
rospy.loginfo("Robot Turtlebot...")
cmd_vel_topic='/cmd_vel'
self._check_laser_ready()
# We start the publisher
self.vel_publisher = rospy.Publisher(cmd_vel_topic, Twist, queue_size=1)
self.cmd = Twist()
self.laser_subscriber = rospy.Subscriber(
'/kobuki/laser/scan', LaserScan, self.laser_callback)
self.summit_laser_subscriber = rospy.Subscriber(
'/hokuyo_base/scan', LaserScan, self.summit_laser_callback)
self.ctrl_c = False
self.rate = rospy.Rate(1)
rospy.on_shutdown(self.shutdownhook)
这里有一些传感器检查方法,可以避免查看没有任何数据的传感器:
在 [ ] 中:
def _check_summit_laser_ready(self):
self.summit_laser_msg = None
rospy.loginfo("Checking Summit Laser...")
while self.summit_laser_msg is None and not rospy.is_shutdown():
try:
self.summit_laser_msg = rospy.wait_for_message("/hokuyo_base/scan", LaserScan, timeout=1.0)
rospy.logdebug("Current /hokuyo_base/scan READY=>" + str(self.summit_laser_msg))
except:
rospy.logerr("Current /hokuyo_base/scan not ready yet, retrying for getting scan")
rospy.loginfo("Checking Summit Laser...DONE")
return self.summit_laser_msg
def _check_laser_ready(self):
self.laser_msg = None
rospy.loginfo("Checking Laser...")
while self.laser_msg is None and not rospy.is_shutdown():
try:
self.laser_msg = rospy.wait_for_message("/kobuki/laser/scan", LaserScan, timeout=1.0)
rospy.logdebug("Current /kobuki/laser/scan READY=>" + str(self.laser_msg))
except:
rospy.logerr("Current /kobuki/laser/scan not ready yet, retrying for getting scan")
rospy.loginfo("Checking Laser...DONE")
return self.laser_msg
在类的构造函数中,我们要对许多不同的 ROS 元素进行初始化和定义,因此我们暂时不考虑这部分内容。请记住,我们在这里进行的所有设置都是为了能够与模拟机器人进行通信。
你知道接下来会发生什么吗?知道!那就是类的方法。在这门课中,我们有很多方法。不过,其中的大多数方法你可能已经耳熟能详了,因为在本课程中你一直在使用它们。
例如,您可以看到所有的激光方法,这些方法可以让您从机器人那里获得激光读数:
在 [ ] 中:
def get_laser(self, pos):
time.sleep(1)
return self.laser_msg.ranges[pos]
def get_laser_summit(self, pos):
time.sleep(1)
return self.summit_laser_msg.ranges[pos]
def get_front_laser(self):
time.sleep(1)
return self.laser_msg.ranges[360]
def get_laser_full(self):
time.sleep(1)
return self.laser_msg.ranges
或者说,你们使用了哪些不同的方法来移动机器人:
在 [ ] 中:
def stop_robot(self):
#rospy.loginfo("shutdown time! Stop the robot")
self.cmd.linear.x = 0.0
self.cmd.angular.z = 0.0
self.publish_once_in_cmd_vel()
def move_straight(self):
# Initilize velocities
self.cmd.linear.x = 0.5
self.cmd.linear.y = 0
self.cmd.linear.z = 0
self.cmd.angular.x = 0
self.cmd.angular.y = 0
self.cmd.angular.z = 0
# Publish the velocity
self.publish_once_in_cmd_vel()
def move_straight_time(self, motion, speed, time):
# Initilize velocities
self.cmd.linear.y = 0
self.cmd.linear.z = 0
self.cmd.angular.x = 0
self.cmd.angular.y = 0
self.cmd.angular.z = 0
if motion == "forward":
self.cmd.linear.x = speed
elif motion == "backward":
self.cmd.linear.x = - speed
i = 0
# loop to publish the velocity estimate, current_distance = velocity * (t1 - t0)
while (i <= time):
# Publish the velocity
self.vel_publisher.publish(self.cmd)
i += 1
self.rate.sleep()
# set velocity to zero to stop the robot
self.stop_robot()
s = "Moved robot " + motion + " for " + str(time) + " seconds at " str(speed) + " m/s"
return s
def turn(self, clockwise, speed, time):
# Initilize velocities
self.cmd.linear.x = 0
self.cmd.linear.y = 0
self.cmd.linear.z = 0
self.cmd.angular.x = 0
self.cmd.angular.y = 0
if clockwise == "clockwise":
self.cmd.angular.z = -speed
else:
self.cmd.angular.z = speed
i = 0
# loop to publish the velocity estimate, current_distance = velocity * (t1 - t0)
while (i <= time):
# Publish the velocity
self.vel_publisher.publish(self.cmd)
i += 1
self.rate.sleep()
# set velocity to zero to stop the robot
self.stop_robot()
s = "Turned robot " + clockwise + " for " + str(time) + " seconds at " str(speed) + " radians/second"
return s
同样,你能在这里看到的大部分代码都与 ROS 有关,所以我们就不细说了。但您可以从中了解到一个大概,那就是 Python 类 RobotControl有许多不同的方法,可以与机器人进行交互,从它那里获取数据(激光读数)或向它发送数据(移动它)。
最后,您可以看到 main方法:
在 [ ] 中:
if __name__ == '__main__':
robotcontrol_object = RobotControl()
try:
robotcontrol_object.move_straight()
except rospy.ROSInterruptException:
pass
对于我们的课程来说,这段代码并不是很重要,因为我们不会用到它。但让我们试着快速解释一下。在整个课程中,您一直在导入这个 RobotControl类并使用它的各种方法。但是......如果你想直接执行这个文件呢?比方说,使用下面的命令:
在 [ ] 中:
python robot_control_class.py
在这种情况下, main方法将被执行。忽略 ROSInterruptException部分,这个方法内部的内容非常简单(也很熟悉)。
在 [ ] 中:
robotcontrol_object = RobotControl()
robotcontrol_object.move_straight()
正如您所看到的,您在这里所做的只是在 RobotControl()类的实例。 robotcontrol_object变量中创建一个类的实例。然后调用 move_straight()的方法。
因此,以 Jedi类,就会产生类似的结果:
Python 文件: jedi_class.py (已更新)
在 [ ] 中:
class Jedi:
def __init__(self, name):
self.jedi_name = name
def say_hi(self):
print('Hello, my name is ', self.jedi_name)
if __name__ == '__main__':
j1 = Jedi('ObiWan')
j1.say_hi()
j2 = Jedi('Anakin')
j2.say_hi()
Python 文件: jedi_class.py (已更新)
请记住,如果您有兴趣了解更多关于 ROS 的知识,以及所有这些方法在幕后到底在做什么,您可以从我们的课程获得所有这些知识,您还将有机会实践从 Python 中学到的所有知识。
5.5 结论
本课程到此结束。通过本课程的学习,您已经掌握了 Python 的基础知识,但关于这门优秀的语言,您还有很多东西需要学习。
我们的建议是,您现在就开始利用您的 Python 知识学习《ROS 基础知识 5 天课程》,每当您在我们为您提供的 ROS 程序中发现一段本课程中没有解释的代码时,就去互联网上查找它的含义。既然你已经掌握了 Python 语言的基础知识,就能很快理解它。

最后建议:如果你现在去学习 ROS 基础课程,你会发现你必须做很多为 ROS 编写 Python 代码的练习。你有两种选择:使用过程方法编写代码,或者使用 Python 类。我们建议你尽量使用类来完成练习,因为这是专业 ROS 程序员的方法。
继续推动你的 Python 学习!
5.6 测验提醒
如果由于某种原因测验没有显示,请告诉我们,我们会解决这个问题。
您想在 6 个月内从事机器人技术工作吗?机会就在这里。
了解更多信息:
现在,该进入本课程结业项目的下一部分了!
该学院的每门课程都包含一个项目,必须通过应用课程所学知识来解决。
该项目将在一个不同的环境中完成,即ROS 开发工作室(ROSDS)。ROSDS是一个更接近于为公司机器人编程的环境。不过,它不像本学院那样具有指导性。
ROSDS已包含在您的订阅中,并集成在The Construct 中。因此,您无需付出额外的努力。不过,您需要付出一些额外的学习努力!不过,这也是您来到这里的原因!
要启动该项目,首先需要获取一份包含项目说明的ROS Project(ROSject)。请执行以下操作:
将项目 rosject 复制到您的ROSJECT区域(请参阅下面的说明)。
获得ROSJECT后,请进入The Construct面板上的 "我的 Rosjects"区域。

单击在此课程 Rosject 上运行,打开 ROSJECT。

然后按照 Rosject 的指示完成项目的第二部分和第三部分。
现在,您可以通过点击下面提供的链接来复制项目 Rosject。这将自动复制该项目。

发表评论