论文复现Pushing and Grasping Policies(3)

一、测试

Test 1

原句:Compact scenario where the target object is occluded with structured clutter, The termianl output is saved to a text file so that can be later used for evaluation.翻译:目标对象被结构化的杂乱遮挡的紧凑场景,终端输出被保存到文本文件中,以便稍后用于评估。

在~/CoppeliaSim_Edu_V4_7_0_rev4_Ubuntu20_04下打开一个终端,输入 ./coppeliaSim.sh,成功启动CoppeliaSim。在~/pushing_and_grasping目录下conda activate push_grasp激活环境。然后执行如下命令。

#这里将test1.txt放在~/pushing_and_grasping目录下
python main.py --stage push_grasp --num_obj 10 --experience_replay --explore_rate_decay --is_testing --test_preset_cases --test_preset_file 'simulation/test-cases/test-10-obj-06.txt' --load_snapshot --snapshot_file 'JointPushGraspModelNoMaskInput_b.pth' --save_visualizations --grasp_goal_conditioned --goal_conditioned --goal_obj_idx 1 > ~/pushing_and_grasping/test1.txt

 运行后机械臂会推动的物体(在不容易抓取绿色目标物体的时候),运行图如下。

运行后有5个警告如下。

#警告信息有5个

关于 nn.init.kaiming_normal 的警告:
/home/lenovo/pushing_and_grasping/models.py:200: UserWarning: nn.init.kaiming_normal is now deprecated in favor of nn.init.kaiming_normal_.
nn.init.kaiming_normal(m[1].weight.data)
解释:nn.init.kaiming_normal 已经弃用,建议使用 nn.init.kaiming_normal_

关于 size_average 和 reduce 的警告:
/home/lenovo/anaconda3/envs/push_grasp/lib/python3.8/site-packages/torch/nn/_reduction.py:42: UserWarning: size_average and reduce args will be deprecated, please use reduction='none' instead.
warnings.warn(warning.format(ret))
解释:size_average 和 reduce 参数将被弃用,建议使用 reduction='none'。

关于 grid_sample 和 affine_grid 的警告:
/home/lenovo/anaconda3/envs/push_grasp/lib/python3.8/site-packages/torch/nn/functional.py:4065: UserWarning: Default grid_sample and affine_grid behavior has changed to align_corners=False since 1.3.0. Please specify align_corners=True if the old behavior is desired. See the documentation of grid_sample for details.
warnings.warn(
解释:grid_sample 和 affine_grid 的默认行为已更改为 align_corners=False。如果需要旧行为,需将 align_corners 参数设置为 True。

关于 volatile 的警告:
/home/lenovo/pushing_and_grasping/models.py:233: UserWarning: volatile was removed and now has no effect. Use `with torch.no_grad():` instead.
rotate_color = F.grid_sample(Variable(input_color_data, volatile=True).cuda(), flow_grid_before, mode='nearest')
解释:volatile 参数已被移除,建议使用 with torch.no_grad(): 来代替。

关于 nn.Upsample 的警告:
/home/lenovo/anaconda3/envs/push_grasp/lib/python3.8/site-packages/torch/nn/functional.py:3631: UserWarning: Default upsampling behavior when mode=bilinear is changed to align_corners=False since 0.4.0. Please specify align_corners=True if the old behavior is desired. See the documentation of nn.Upsample for details.
warnings.warn(
解释:当 mode=bilinear 时,nn.Upsample 的默认行为已更改为 align_corners=False。如果需要旧行为,需将 align_corners 参数设置为 True。

运行后的报错是CUDA 内存不足。

Test 2

原句:Unstructured case of testing keep the goal object set below to 1 since the goal object has to be the green object, c is the number of objects that can be placed in the environment, max 20. Thhere are more test files in the directory with a different goal object shape that can be used. The termianl output is saved to a text file so that can be later used for evaluation.翻译:在非结构化测试的情况下,将目标对象设置为1以下,因为目标对象必须是绿色对象,c是可以放置在环境中的对象数,最大为20。目录中还有更多可以使用的具有不同目标对象形状的测试文件。终端输出保存到文本文件中,以便以后用于评估。

这行命令修改原命令中--num_obj c的c为20 ,命令代码如下。

#这里将test2.txt放在~/pushing_and_grasping目录下
python main.py --stage push_grasp --num_obj 20 --experience_replay --explore_rate_decay --is_testing --test_preset_cases --test_preset_file 'simulation/test-cases/Test0.txt' --load_snapshot --snapshot_file 'JointPushGraspModelNoMaskInput_b.pth' --save_visualizations --grasp_goal_conditioned --goal_conditioned --goal_obj_idx 1 > ~/pushing_and_grasping/test2.txt

 运行后第一次直接抓到绿色物体,第二次先推动还没抓,运行图如下。

运行后有5个警告,和Test 1的警告内容一样。 

运行后的报错多了一个,如下。

关于 double_scalars 的警告:
/home/lenovo/pushing_and_grasping/utils.py:361: RuntimeWarning: invalid value encountered in double_scalars
occupy_ratio = margin_value / np.sum(margin_mask)
解释:在计算 occupy_ratio 时遇到无效值,可能是因为 margin_mask 的求和结果为零,导致除零错误。

分析测试的两行命令,这两个命令在大多数参数上是相同的,但在对象数量和测试预设文件上有所不同。第一个测试将在仿真环境中使用 10 个对象,并加载 test-10-obj-06.txt 文件中的预设配置,而第二个测试将在仿真环境中使用 20 个对象,并加载 Test0.txt 文件中的预设配置。这些不同的设置会影响仿真环境中的物体布局和数量,从而测试模型在不同复杂度场景下的表现。

#这里将test1.txt放在~/pushing_and_grasping目录下
python main.py --stage push_grasp --num_obj 10 --experience_replay --explore_rate_decay --is_testing --test_preset_cases --test_preset_file 'simulation/test-cases/test-10-obj-06.txt' --load_snapshot --snapshot_file 'JointPushGraspModelNoMaskInput_b.pth' --save_visualizations --grasp_goal_conditioned --goal_conditioned --goal_obj_idx 1 > ~/pushing_and_grasping/test1.txt

#这里将test2.txt放在~/pushing_and_grasping目录下
python main.py --stage push_grasp --num_obj 20 --experience_replay --explore_rate_decay --is_testing --test_preset_cases --test_preset_file 'simulation/test-cases/Test0.txt' --load_snapshot --snapshot_file 'JointPushGraspModelNoMaskInput_b.pth' --save_visualizations --grasp_goal_conditioned --goal_conditioned --goal_obj_idx 1 > ~/pushing_and_grasping/test2.txt

具体的参数解释如下。

相同点:

    --stage push_grasp:指定任务阶段为推-抓(push-grasp)
    --experience_replay:使用经验回放
    --explore_rate_decay:启用探索率衰减
    --is_testing:表明是在进行测试
    --test_preset_cases:使用预设的测试案例
    --load_snapshot:从快照文件加载模型
    --snapshot_file 'JointPushGraspModelNoMaskInput_b.pth':指定要加载的快照文件
    --save_visualizations:保存测试的可视化结果
    --grasp_goal_conditioned:启用抓取目标条件
    --goal_conditioned:启用目标条件
    --goal_obj_idx 1:指定目标对象的索引为 1

不同点:

    --num_obj:
        第一个命令:--num_obj 10,表示在仿真环境中放置 10 个对象。
        第二个命令:--num_obj 20,表示在仿真环境中放置 20 个对象。

    --test_preset_file:
        第一个命令:--test_preset_file 'simulation/test-cases/test-10-obj-06.txt',指定使用 test-10-obj-06.txt 作为预设测试文件。
        第二个命令:--test_preset_file 'simulation/test-cases/Test0.txt',指定使用 Test0.txt 作为预设测试文件。

    输出重定向文件:
        第一个命令:> ~/pushing_and_grasping/test1.txt,将输出重定向到 test1.txt 文件。
        第二个命令:> ~/pushing_and_grasping/test2.txt,将输出重定向到 test2.txt 文件。

二、评估

没有训练出来结果,但还是想运行下评估的命令,看到项目本身有测试的文件夹,于是,将主目录下的 evaluate.py 文件放在 ~/pushing_and_grasping/simulation/test-cases 目录下。在这个目录下执行python evaluate.py。报错显示如下,也就是说没有evaluate/.txt文件,修改如下。

#执行命令 
python evaluate.py
#报错信息
Traceback (most recent call last):
  File "evaluate.py", line 4, in 
    with open("evaluate/.txt") as f:
FileNotFoundError: [Errno 2] No such file or directory: 'evaluate/.txt'
#原来evaluate.py文件的第4行
with open("evaluate/.txt") as f:
    lines = f.readlines()

#修改文件,填写测试输出文件的路径
file_path = "/home/lenovo/pushing_and_grasping/simulation/test-cases/Test1.txt"
with open(file_path) as f:
    lines = f.readlines()

然后,再运行python evaluate.py,新的报错如下。

#报错内容,说在程序中进行了除以零的操作
Traceback (most recent call last):
  File "evaluate.py", line 73, in 
    final_completion = (sum(completion)/len(completion))*100
ZeroDivisionError: division by zero

在evaluate.py文件中的第73行如下,这表示 len(completion) 的值为零,也就是说completion 列表为空。在进行除法运算时,不能除以零,因此程序报错。

final_completion = (sum(completion)/len(completion))*100

因此,修改evaluate.py文件如下。

import numpy as np

# 填写测试输出文件的路径
file_path = "/home/lenovo/pushing_and_grasping/simulation/test-cases/Test1.txt"
with open(file_path) as f:
    lines = f.readlines()

# 打印文件内容用于调试
print("Test1.txt 文件内容:")
for line in lines:
    print(line.strip())

graspPush = []
list_of_outcomes = []
pushes = []
graspsPushes = []
for line in lines:
    if 'Grasp successful:' in line:
        graspPush.append(line)
    if 'Push successful:' in line:
        graspPush.append(line)

# 打印抓取和推动操作的行用于调试
print("抓取和推动操作的行:")
for line in graspPush:
    print(line.strip())

for line in graspPush:
    words = line.split()
    list_of_outcomes.append(words)
    if words[0] == "Grasp" and words[-1] == "True":
        graspsPushes.append(1)
    if words[0] == "Grasp" and words[-1] == "False":
        graspsPushes.append(2)
    if words[0] == "Push" and words[-1] == "True":
        graspsPushes.append(3)
    if words[0] == "Push" and words[-1] == "False":
        graspsPushes.append(4)

# 打印解析后的抓取和推动状态
print("解析后的抓取和推动状态:", graspsPushes)

max_attempts = 5
completion = []
GraspsuccessCountTotal = []
grasp_success_rate = []
efeciencyList = []
motion_numberTotal = []
GraspFailCount = 0
PushCount = 0
counter = 0
GraspsuccessCount = 0
GraspFailCountTotal = 0
start_flag = True
total_grasp = 0
old_PushCount = float('NaN')
PushCountOld = 0
for state in graspsPushes:
    counter += 1

    if state == 2:  # grasp false
        start_flag = False
        GraspFailCountTotal += 1
        GraspFailCount += 1
        total_grasp += 1
        GraspsuccessCountTotal.append(0)

    if state == 1:  # grasp true
        start_flag = True
        GraspsuccessCount += 1
        total_grasp += 1

        if GraspFailCount < max_attempts:
            completion.append(1)
            GraspsuccessCountTotal.append(1)
            motion_numberTotal.append(PushCount - PushCountOld)
            PushCountOld = PushCount
        else:
            completion.append(0)
            GraspsuccessCountTotal.append(0)
        GraspFailCount = 0

    if state == 3 or state == 4:  # push true or false
        start_flag = False
        PushCount += 1

# 确保completion列表不为空
if len(completion) > 0:
    final_completion = (sum(completion)/len(completion))*100
    SE_final_completion = np.std(completion, ddof=1) / np.sqrt(np.size(completion))
    print("final_completion %", final_completion)
    print("SE completion", SE_final_completion * 100)
else:
    print("Error: completion list is empty.")
    final_completion = None
    SE_final_completion = None

print()

# 确保GraspsuccessCount和GraspFailCountTotal不是零
if (GraspsuccessCount + GraspFailCountTotal) > 0:
    final_GraspSuccessRate = (GraspsuccessCount/(GraspsuccessCount+GraspFailCountTotal))*100
    SE_GraspsuccessCountTotal = np.std(GraspsuccessCountTotal, ddof=1) / np.sqrt(np.size(GraspsuccessCountTotal))
    print("final_GraspSuccessRate %", final_GraspSuccessRate)
    print("SE final_GraspSuccessRate", SE_GraspsuccessCountTotal * 100)
else:
    print("Error: GraspsuccessCount and GraspFailCountTotal sum to zero.")
    final_GraspSuccessRate = None
    SE_GraspsuccessCountTotal = None

print()

# 确保GraspsuccessCount不是零
if GraspsuccessCount > 0:
    motion_number = (len(graspsPushes)-(total_grasp))/GraspsuccessCount
    SE_motion_numberTotal = np.std(motion_numberTotal, ddof=1) / np.sqrt(np.size(motion_numberTotal))
    print("motion_number", motion_number)
    print("SE_motion_numberTotal", SE_motion_numberTotal)
else:
    print("Error: GraspsuccessCount is zero.")
    motion_number = None
    SE_motion_numberTotal = None

print()

运行以后终端显示的最下面一部分如下,说在测试过程中,抓取和推动操作都没有成功。具体是。

    "completion list is empty": 表示在测试过程中,没有任何抓取或推动操作被成功执行或记录。这可能意味着机器人没有尝试抓取或推动,或者尝试失败了。

    "GraspsuccessCount and GraspFailCountTotal sum to zero": 表示抓取成功计数和抓取失败计数总和为零。这意味着测试中没有成功或失败的抓取操作被记录。

    "GraspsuccessCount is zero": 抓取成功计数为零,意味着在测试中没有一次成功的抓取操作。

#终端执行evaluate.py文件后的返回内容
 -5.141063928604125977e-01 -5.489115789532661438e-02 2.598390541970729828e-02 1.572011947631835938e+00 -9.765665531158447266e-01 3.324743127450346947e-03
抓取和推动操作的行:
解析后的抓取和推动状态: []
Error: completion list is empty.

Error: GraspsuccessCount and GraspFailCountTotal sum to zero.

Error: GraspsuccessCount is zero.

所以,没有训练结果是无法评估的,项目内simulation/test-cases文件夹下的Test1.txt不能直接用于评估。正确的test1文件中应该有类似于 Grasp successful: TruePush successful: True 这样的行。如果文件中没有这些行,脚本就不会向 completionGraspsuccessCountTotalgraspsPushes 列表中添加任何元素。打开Test1.txt确实没有,都是数字。

然后,想到刚才进行了测试,虽然结果不完全,于是在~/pushing_and_grasping目录下执行python evaluate.py命令,前提是修改evaluate.py文件的第四行。

#修改后的evaluate.py文件第四行和第五行如下,test1.txt执行一遍,test2.txt执行一遍
with open("test1.txt") as f:
    lines = f.readlines()

当为test1.txt时, 终端运行结果依然是ZeroDivisionError: division by zero

当为test2.txt时,终端运行结果如下,说有几项指标(如 completion 和 GraspSuccessRate)的值为 nan(Not a Number),这通常意味着在计算这些指标时发生了某种问题。

#evaluate.py文件的第四行是test2.txt,运行后的终端结果
/usr/lib/python3/dist-packages/numpy/core/_methods.py:216: RuntimeWarning: Degrees of freedom <= 0 for slice
  ret = _var(a, axis=axis, dtype=dtype, out=out, ddof=ddof,
/usr/lib/python3/dist-packages/numpy/core/_methods.py:209: RuntimeWarning: invalid value encountered in double_scalars
  ret = ret.dtype.type(ret / rcount)
final_completion % 100.0
SE completion nan

final_GraspSuccessRate % 100.0
SE final_GraspSuccessRate nan

motion_number 1.0
SE_motion_numberTotal nan

具体解释如下。

Degrees of freedom <= 0 for slice: 表示在计算标准差时,自由度小于或等于 0。自由度是样本数量减去 1,若样本数量太少或者为 0,就会导致自由度为负数或零,从而触发警告。

invalid value encountered in double_scalars:表示在执行浮点数运算时遇到了无效值(如 0 除以 0 或除以负数)。这种情况通常出现在数据缺失或有错误的数据处理过程中。

final_completion % 100.0 和 final_GraspSuccessRate % 100.0 的值为 nan:nan 表示这些值在计算过程中遇到了问题,通常是由于无效的操作或缺失数据导致的。

SE completion nan 和 SE final_GraspSuccessRate nan:这些标准误的值为 nan,也是由于上述原因导致的计算错误。

motion_number 1.0 和 SE_motion_numberTotal nan:这表明运动次数被计算为 1,但标准误的计算同样出现了问题。

所以,总结来说就是数据量不足(当然不足,毕竟只训练成功一次),如果数据量足够还是报错那么也可能其他问题,数据处理问题:确保在 evaluate.py 中没有任何数据处理错误。例如,检查是否有任何数据文件缺失或损坏。代码逻辑错误:查看 evaluate.py 中的代码逻辑,尤其是与数据处理和统计计算相关的部分,确保没有错误。预设文件内容问题:检查预设文件(如 Test0.txt 和 test-10-obj-06.txt)的内容是否正确,确保它们包含了所需的所有数据。

Fine,那么这篇论文的复现暂时到此为止了,之后换成其他设备再进行一遍,看看能否运行成功。

 

你可能感兴趣的:(linux,机器人)