主脚本(main script)

主脚本(main script)

主脚本包含一个回调函数的集合,这些函数由系统适当地调用。如果给定的系统回调函数没有定义,调用将被忽略。除了初始化函数外,其他所有函数都是可选的,默认的主脚本通常分为4个主要的系统回调函数:

  • 初始化函数sysCall_init:这是个必选函数,它会在仿真开始时被执行一次。其中的代码负责模拟运行前的准备部分。
  • 驱动函数sysCall_actuation:这个函数将在每次模拟过程中执行。代码用来处理模拟器的所有驱动功能(逆运动学、动力学等)。其中有三个命令值得注意: sim.launchThreadedChildScripts,sim.resumeThreads和sim.handleChildScripts。前两个会启动/恢复线性子脚本,而第三个会调用非线性子脚本的sysCall_actuation函数。没有这些指令,子脚本不会执行它们的驱动函数,而特定的模型功能或行为将无法按预期运行。
  • 传感函数sysCall_sensing:这个函数将在每次模拟过程中执行。代码用来处理模拟器的所有传感功能(传感器、碰撞检测等)。要关注以下两个命令:sim.resumeThreads和sim.handleChildScripts。前者恢复线性子脚本,而后者会调用非线性子脚本的 sysCall_sensing函数。没有这些指令,子脚本不会执行它们的传感函数,而特定的模型功能或行为将无法按预期运行。
  • 恢复功能sysCall_cleanup:这个函数会在仿真结束前执行一次。用来存储物体的初始配置,清除传感器状态和碰撞状态等。

下面是一些典型的主脚本:

function sysCall_init()
    -- Initialization part:
    sim.handleSimulationStart()
    sim.openModule(sim.handle_all)
    sim.handleGraph(sim.handle_all_except_explicit,0)
end

function sysCall_actuation()
    -- Actuation part:
    sim.resumeThreads(sim.scriptthreadresume_default)
    sim.resumeThreads(sim.scriptthreadresume_actuation_first)
    sim.launchThreadedChildScripts()
    sim.handleChildScripts(sim.syscb_actuation)
    sim.resumeThreads(sim.scriptthreadresume_actuation_last)
    sim.handleCustomizationScripts(sim.syscb_actuation)
    sim.handleAddOnScripts(sim.syscb_actuation)
    sim.handleSandboxScript(sim.syscb_actuation)
    sim.handleModule(sim.handle_all,false)
    sim.handleIkGroup(sim.handle_all_except_explicit)
    sim.handleDynamics(sim.getSimulationTimeStep())
end

function sysCall_sensing()
    -- Sensing part:
    sim.handleSensingStart()
    sim.handleCollision(sim.handle_all_except_explicit)
    sim.handleDistance(sim.handle_all_except_explicit)
    sim.handleProximitySensor(sim.handle_all_except_explicit)
    sim.handleVisionSensor(sim.handle_all_except_explicit)
    sim.resumeThreads(sim.scriptthreadresume_sensing_first)
    sim.handleChildScripts(sim.syscb_sensing)
    sim.resumeThreads(sim.scriptthreadresume_sensing_last)
    sim.handleCustomizationScripts(sim.syscb_sensing)
    sim.handleAddOnScripts(sim.syscb_sensing)
    sim.handleSandboxScript(sim.syscb_sensing)
    sim.handleModule(sim.handle_all,true)
    sim.resumeThreads(sim.scriptthreadresume_allnotyetresumed)
    sim.handleGraph(sim.handle_all_except_explicit,sim.getSimulationTime()+sim.getSimulationTimeStep())
end

function sysCall_cleanup()
    -- Clean-up part:
    sim.resetCollision(sim.handle_all_except_explicit)
    sim.resetDistance(sim.handle_all_except_explicit)
    sim.resetProximitySensor(sim.handle_all_except_explicit)
    sim.resetVisionSensor(sim.handle_all_except_explicit)
    sim.closeModule(sim.handle_all)
end

function sysCall_suspend()
    sim.handleChildScripts(sim.syscb_suspend)
    sim.handleCustomizationScripts(sim.syscb_suspend)
    sim.handleAddOnScripts(sim.syscb_suspend)
    sim.handleSandboxScript(sim.syscb_suspend)
end

function sysCall_suspended()
    sim.handleChildScripts(sim.syscb_suspended)
    sim.handleCustomizationScripts(sim.syscb_suspended)
    sim.handleAddOnScripts(sim.syscb_suspended)
    sim.handleSandboxScript(sim.syscb_suspended)
end

function sysCall_resume()
    sim.handleChildScripts(sim.syscb_resume)
    sim.handleCustomizationScripts(sim.syscb_resume)
    sim.handleAddOnScripts(sim.syscb_resume)
    sim.handleSandboxScript(sim.syscb_resume)
end

主脚本还可以使用更多的系统回调函数来响应各种事件:

function sysCall_init() -- not optional!!
    -- Put some initialization code here
end

function sysCall_actuation()
    -- Put some actuation code here
end

function sysCall_sensing()
    -- Put some sensing code here
end

function sysCall_cleanup()
    -- Put some restoration code here
end

function sysCall_beforeCopy(inData)
    for key,value in pairs(inData.objectHandles) do
        print("Object with handle "..key.." will be copied")
    end
end

function sysCall_afterCopy(inData)
    for key,value in pairs(inData.objectHandles) do
        print("Object with handle "..key.." was copied")
    end
end

function sysCall_afterCreate(inData)
    for key,value in pairs(inData.objectHandles) do
        print("Object with handle "..value.." was created")
    end
end

function sysCall_beforeDelete(inData)
    for key,value in pairs(inData.objectHandles) do
        print("Object with handle "..key.." will be deleted")
    end
    -- inData.allObjects indicates if all objects in the scene will be deleted
end

function sysCall_afterDelete(inData)
    for key,value in pairs(inData.objectHandles) do
        print("Object with handle "..key.." was deleted")
    end
    -- inData.allObjects indicates if all objects in the scene were deleted
end

function sysCall_suspend()
    -- Simulation is about to be suspended
end

function sysCall_suspended()
    -- Simulation is suspended
end

function sysCall_resume()
    -- Simulation is about to be resumed
end

主脚本最好不要修改。理由如下:CoppeliaSim的优势之一是,任何模型(机器人,执行器,传感器等)都可以复制到一个场景,并立即操作。当修改主脚本后,将会有模型不再按预期执行的风险(比如,当主脚本缺少指令sim.handleChildScripts,那么所有复制到场景中的模型都不会再执行)。另一个理由是使用默认的主脚本使旧的场景能比较容易地调整为新的功能(比如,一个新的CoppeliaSim版本引入了一个命令sim.doMagic(),那么就的场景将会自动更新,使该命令也自动调用在他们的主脚本)。

然而,如果出于某种原因,你确实需要修改场景的主脚本,你可以双击场景层次结构顶部世界图标旁边的浅红色脚本图标。

在这里插入图片描述

从你打开主脚本的那一刻起,它就会被标记为自定义的,并且不会被自动更新。

大多数主脚本中的命令会以相似的方式执行。比如在执 distance calculation functionality时,会有如下部分:

  • sim.handleDistancehttps:(sim.handle_all_except_explicit):这个指令的功能是计算所有已注册的,并且在距离计算对话框中列出的所有距离对象的最小距离(一个距离对象的处理距离计算将会计算它的最小距离,设置距离变量,在场景中显示最小距离间隔)。所有的距离对象都被这个命令处理(即计算),除了那些被标记为explicit handling(显式处理)的对象。

任何新的距离对象都会被上面的命令自动地处理(只要它没被标记为显式处理)。相同的机制也被用到 collision detection(碰撞检测),proximity sensor(接近度传感器)and vision sensorsimulations(视觉传感器仿真), inverse kinematics(逆动力学)等。这是一种强大的机制,允许运行简单的模拟而不需要编写一行代码。

大多数子脚本的系统回调函数都从主脚本通过sim.handleChildScripts函数调用,在场景层次和附加到单个场景对象的子脚本上以级联的方式操作。

如果看默认主函数,就会注意到驱动函数驱动或者修改场景内容(比如sim.handleIkGroup,sim.handleDynamics等),而传感函数会感知和探测场景内容(比如sim.handleCollision,sim.handleDistance,sim.handleProximitySensor等)。下面演示了在模拟一个配备了接近度传感器的移动机器人时,在默认的主脚本中会发生什么:

在这里插入图片描述

子脚本将总是读取(使用sim.readProximitySensor)从以前的感知(发生在前一个模拟过程结束时,在主脚本中,使用sim.handleProximitySensor)接近传感器的状态,然后对障碍物做出反应。

如果你需要显式地控制一个传感器,请确保在传感部分总是这样做,否则就可能会出现如下图所示地显示错误的情况:

在这里插入图片描述

正如主脚本具有驱动和感知功能一样,非线程子脚本也具有驱动和感知功能。另一方面,线程化的子脚本可以在主脚本处于驱动或感知函数中时被强制运行,请参考API函数sim.setThreadResumeLocation。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值