Python初学者ROS开发求助:TypeError: __init__()缺失必填参数'target'问题排查
解决ROS Python开发中的
TypeError: __init__() missing 1 required positional argument: 'target'问题 嘿,刚接触Python和ROS的话遇到这种参数错误太正常了,我来帮你理清楚问题出在哪以及怎么解决:
错误原因分析
你报错的直接原因很明确:在if __name__ == '__main__':代码块里创建TurtleCatch实例时,写的是x = TurtleCatch(),但你的TurtleCatch类的__init__方法明确要求必须传入一个target参数——看类定义第一行def __init__(self, target):,这里的target是必填的位置参数,你没传就会触发这个TypeError。
但更深层的问题是代码逻辑有点混乱:你想在TurtleCatch的初始化方法里去设置target的订阅者和属性,但此时你根本还没创建任何target对象,相当于要给一个不存在的东西赋值,这肯定行不通。
修复方案
我们需要先创建一个用来管理目标对象坐标的类(或者至少是一个能存储pose的对象),然后再把它传给TurtleCatch实例。同时还要修正你代码里方法参数不匹配的问题(比如linear_vel方法定义要target,但你调用时传的是target.pose)。
修改后的完整代码
import rospy from geometry_msgs.msg import Twist, Pose from math import sqrt, atan2 # 先定义一个Target类来管理目标的pose和订阅 class Target: def __init__(self): self.pose = Pose() # 订阅目标的pose话题 self.pose_subscriber = rospy.Subscriber('/mytarget/pose', Pose, self.update_pose) self.rate = rospy.Rate(10) def update_pose(self, data): self.pose = data self.pose.x = round(self.pose.x, 4) self.pose.y = round(self.pose.y, 4) class TurtleCatch: def __init__(self, target): rospy.init_node('turtlecatch_initialiser', anonymous=True) # 修正:机器人移动需要发布到速度话题,而非位姿话题 self.velocity_publisher = rospy.Publisher('/robot1/cmd_vel', Twist, queue_size=10) self.pose_subscriber = rospy.Subscriber('/robot1/pose', Pose, self.update_pose) self.target = target # 把传入的target对象存为实例属性 self.pose = Pose() self.rate = rospy.Rate(10) def update_pose(self, data): self.pose = data self.pose.x = round(self.pose.x, 4) self.pose.y = round(self.pose.y, 4) def euclidean_distance(self): # 直接用实例的target属性计算距离,不用再传参数 return sqrt(pow((self.target.pose.x - self.pose.x), 2) + pow((self.target.pose.y - self.pose.y), 2)) def linear_vel(self, constant=1.5): return constant * self.euclidean_distance() def steering_angle(self): return atan2(self.target.pose.y - self.pose.y, self.target.pose.x - self.pose.x) def angular_vel(self, constant=6): return constant * (self.steering_angle() - self.pose.theta) def move2target(self): distance_tolerance = 0.01 vel_msg = Twist() while self.euclidean_distance() >= float(distance_tolerance): # 修正速度赋值的参数错误 vel_msg.linear.x = self.linear_vel() vel_msg.linear.y = 0 vel_msg.linear.z = 0 vel_msg.angular.x = 0 vel_msg.angular.y = 0 vel_msg.angular.z = self.angular_vel() self.velocity_publisher.publish(vel_msg) self.rate.sleep() # 到达目标后停止移动 vel_msg.linear.x = 0 vel_msg.angular.z = 0 self.velocity_publisher.publish(vel_msg) rospy.spin() if __name__ == '__main__': try: # 先创建Target实例 target_obj = Target() # 再把target_obj传给TurtleCatch的构造函数 x = TurtleCatch(target_obj) # 调用move2target不需要再传参数,因为实例已经持有target了 x.move2target() except rospy.ROSInterruptException: pass
关键改动说明
- 新增
Target类:专门负责订阅目标的/mytarget/pose话题,更新并存储目标坐标,让代码职责更清晰,符合面向对象设计思路。 - 修正
TurtleCatch实例化流程:先创建target_obj实例,再将其传入TurtleCatch的构造函数,满足__init__方法对target参数的必填要求。 - 简化方法参数逻辑:将原本需要传入
target的方法,改为直接调用实例的self.target属性,避免了参数传递时的类型/层级错误(比如你之前混淆target对象和target.pose属性的问题)。 - 修正速度发布话题:你原本错误地向
/robot1/pose(位姿订阅话题)发布速度指令,改成了ROS标准的机器人速度控制话题/robot1/cmd_vel,这是ROS开发里的常见误区。
这样修改后,你的代码就能正常创建订阅者、获取目标坐标,然后驱动捕捉者移动到目标位置了。
内容的提问来源于stack exchange,提问作者Andrei Gorun
相关产品推荐
相关产品推荐

