Conveyor belt / caterpillar tutorial

In this tutorial we will be building a conveyor belt (or caterpillar, in which case have a look at the very end of this tutorial) from A to Z. Following figure illustrates the simulation scene that we will design:

We will build a conveyor belt that should behave exactly as a real one, where each conveyor belt pad is individually simulated dynamically. This means that smaller objects could get trapped in-between two adjacent pads for example. This type of simulation can be quite calculation intensive and slows down the overall simulation process. There is an alternative, simplified way to model a conveyor belt which will also be explained in this tutorial and clearly marked as METHOD B (in contrast to METHOD A where individual pads are simulated).

First of all, freshly start V-REP. The conveyor belt in the figure above is basically constituted by a path object that drives several pads along its trajectory. Add a circular path with [Popup menu --> Add --> Path --> Circle type]. In order to see the path from above, switch to page 6. Use the fit-to-view toolbar button to bring the camera closer:

With the path object selected, notice how the path is defined by blue points, in-between which a Bezier interpolation is performed. You can also distinguish a red sphere, which represents the path position, which is not the position of the path, but rather a position along the path.

Before attaching pads to the path, let's prepare the correct size and shape of the path. You can import a path, or you can modify and edit an existing path, and we will opt for the second alternative. While the path is selected, enter the path edit mode by clicking the path edit mode toolbar button:

We are now in the path edit mode. We want to design a conveyor belt that is 10 cm thick, 20 cm wide and 1 m long. The individual pads making up the belt will be 5 mm thick

In the path edit mode dialog, check the Path is flat and Keep x up items. Select all path points, then open the position dialog, on the position scaling tab, enter 3 times a scaling factor of "0.19" on the right-hand side, and click Scale position. This just scaled the path appropriately. Using the mouse wheel, come closer to the path. Select the uppermost path point. Copy it with ctrl-c. Then select it again and paste the buffer just after the selected position with ctrl-v. We just created a path point coincident with the uppermost path point: we copied the path point #13, and pasted a copy of it just afterwards. The new path point is path point #14 as illustrated in these figures:

Now repeat the same procedure with the lowermost path point. Now that we have the two middle path points duplicated, we can stretch the path, i.e. move the left and right parts apart: select in the scene hierarchy path points #6 to path points #14, and on the translation tab of the position dialog, for item Along X, enter "-0.5" then click X-translate selection. Now zoom a little bit out. This is what you should have:

Now select the left-hand side path points, and shift them in a similar way by 0.5 m towards the positive x coordinate. The path is ready:

Leave the path edit mode, select the path and in the information text section of the main window notice the line "Last selected object type: Path (Bezier curve point count=270, total length=2.2985, p=+0.0000, Vn=+0.0000)". This tells us that the length of the path is 2.2985 meters. We can now figure out how many pads we want, their widths, and what the inter-pad distance should be. We go with 40 pads and a width of 5 cm, which results in an inter-pad distance of 0.75 cm

Click [Popup menu --> Add --> Primitive shape --> Cuboid]. The primitive shape dialog appears that allows you to adjust various parameters. Enter (0.05; 0.005; 0.18) for the x-, y-, and z-sizes.

METHOD A
simply click Ok. This adds a pure shape that is dynamic and respondable to the scene. Switch to page 1. Now you can see the added shape. Rename it to "pad0" (you can rename any object by double-clicking its name in the scene hierarchy). With the position dialog, set the pad's absolute z-coordinate to 0. Double-click the pad's icon in the scene hierarchy to open the shape properties dialog. Adjust its color (click the Adjust outside color item). Then, in the shape dynamics properties dialog, check the Static item in order to have the pad not fall during simulation. In the object common properties, check following items: Select base of model instead, Collidable, Measurable, Renderable, and all Detectable properties. In the Visibility layers section, enable also layer 9 (but keep layer 1 also enabled).

METHOD B
uncheck the Create dynamic and respondable shape item and click Ok. This adds a pure shape that is static to the scene. Switch to page 1. Now you can see the added shape. Rename it to "pad0" (you can rename any object by double-clicking its name in the scene hierarchy). With the position dialog, set the pad's absolute z-coordinate to 0. Double-click the pad's icon in the scene hierarchy to open the shape properties dialog. Adjust its color (click theAdjust outside coloritem). In the object common properties, check following item: Select base of model instead, Collidable, Measurable, Renderable, and all Detectable properties. In METHOD B, the conveyor belt pads don't have a dynamic function!

Next, we would like to attach the pad to the path, so that it automatically follows the path's trajectory, if the path's intrinsic position is modified with sim.setPathPosition. For this task we will need a helper object: a dummy. Click [Popup menu --> Add --> Dummy]. Rename the dummy to "padLink0". Adjust the dummy's orientation to (0;-90;0) via the orientation dialog, on the orientation tab. Attach the pad to the dummy by selecting the pad, then the dummy, then clicking [Popup menu --> Edit --> Make last selected object parent]. Next, attach the dummy to the path in a similar way (parenting can also be achieved by drag-and-drop in the scene hierarchy). Double-click the dummy icon in the scene hierarchy to open the dummy properties dialog. Check the Follow parent path (only direct parent) item: notice how the dummy and the pad just jumped to the path's red sphere's location. While the dummy is still selected, set the copy increment item to "0.0575". This indicates that if the dummy is copied, then its offset on the path will automatically be incremented by 0.0575 meters, i.e. the width of the pad plus the inter-pad distance. In the object common properties dialog, hide the dummy in layer 11 (deactivate layer 3 and activate layer 11).

Now we will add the remaining 39 pads. Select the dummy and the pad, and copy the selection with ctrl-c. Then paste the buffer exactly 39 times by pressing 39 times ctrl-v. Clear the selection with the esc-key, then select "padLink1" to "padLink39" in the scene hierarchy (make sure you don't select the pads but just the dummies!), then select the path, then click [Popup menu --> Edit --> Make last selected object parent]. This is what you should have:

In next step, we will add a simplified housing for the conveyor belt. Add a pure cylinder with dimensions (0.12; 0.12; 0.2) to the scene. Set its z-position to 0, its x-position to 0.5, then adjust its color. Copy and paste it, and move the copy to x-coordinate -0.5 meters. Add a pure cuboid with dimensions (1.0; 0.09; 0.18). Set its z-position to 0, and adjust its color. Select the two cylinders and the cuboid that you just added, then click [Popup menu --> Edit --> Grouping/Merging --> Group selected shapes]. Rename the resulting shape to "conveyorBelt". In the shape dynamics properties dialog, make "conveyorBelt" static, and in the object common properties, check Collidable, Measurable, Renderable, and all Detectable properties. Press also the Visibility layer button 9. Then attach the path to "conveyorBelt".

METHOD B
add a pure cuboid with dimensions (1.0; 0.1; 0.18). Set its z-position to 0. Rename the resulting shape to "conveyorForwarder". In the shape dialog, make "conveyorForwarder" static, and in the object common properties dialog send the object to the Visibility layer 9 (disable button 1 and enable button 9). Then attach "conveyorForwarder" to "conveyorBelt". "ConveyorForwarder" is the object that will move other objects lying on it along with a little trick (see further below).

Now rotate the conveyor body by 90 degrees around the absolute x-axis, and set its coordinates to (0.0; 0.0; 0.5). Select the path, and in the path properties uncheck Show path line, Show orientation of points and Show current position on path. Select "conveyorBelt" and in the object common properties dialog, check the Object is model base items. Click Edit model properties and in the Model content acknowledgments/Info section, add some text that you wish displayed every time the conveyor model is loaded. Finally collapse the hierarchy tree starting at "conveyorBelt". Our model is almost ready:

Notice that clicking any object on the conveyor belt model, the whole model gets selected. If you wish to select individual objects, you can still do this in the scene hierarchy, or by holding down the shift and ctrl keys (both at the same time!) when clicking an object.

The intrinsic position of the path (thus, the movement of the path) can also be modified through the API function sim.setPathPosition. Have a look at the other conveyor belt models in the model browser for an example on how to do this.

METHOD A
select the "conveyorBelt" object and click [Menu bar --> Add --> Associated child script --> Non threaded]. This just attached a non-threaded child script to the model base. Double-click on the child script icon in the scene hierarchy to open the child script. Replace the script with following code:
function sysCall_init()
    pathHandle=sim.getObjectHandle("Path")
    sim.setPathTargetNominalVelocity(pathHandle,0) -- for backward compatibility
end

function sysCall_cleanup()
 
end 

function sysCall_sensing()

end 

function sysCall_actuation()
    beltVelocity=0.1 -- in meters/seconds
    local dt=sim.getSimulationTimeStep()
    local pos=sim.getPathPosition(pathHandle)
    pos=pos+beltVelocity*dt
    sim.setPathPosition(pathHandle,pos) -- update the path's intrinsic position
end
What above code effectively does is following: in each simulation pass, the intrinsic position of the path is modified in order to generate the intrinsic motion of the conveyor belt.

METHOD B
select the "conveyorBelt" object and click [Menu bar --> Add --> Associated child script --> Non threaded]. This just attached a non-threaded child script to the model base. Double-click on the child script icon in the scene hierarchy to open the child script. Replace the script with following code:
function sysCall_init()
    pathHandle=sim.getObjectHandle("Path")
    forwarder=sim.getObjectHandle('conveyorForwarder')
    sim.setPathTargetNominalVelocity(pathHandle,0) -- for backward compatibility
end

function sysCall_cleanup()
 
end 

function sysCall_sensing()

end 

function sysCall_actuation()
    beltVelocity=0.1 -- in meters/seconds
    local dt=sim.getSimulationTimeStep()
    local pos=sim.getPathPosition(pathHandle)
    pos=pos+beltVelocity*dt
    sim.setPathPosition(pathHandle,pos) -- update the path's intrinsic position

    -- Here we "fake" the transportation pads with a single
    -- static cuboid that we dynamically reset at each
    -- simulation pass (while not forgetting to set its initial
    -- velocity vector) :

    local relativeLinearVelocity={-beltVelocity,0,0}
    -- Reset the dynamic cuboid from the simulation
    -- (it will be removed and added again):
    sim.resetDynamicObject(forwarder)
    -- Compute the absolute velocity vector:
    local m=sim.getObjectMatrix(forwarder,-1)
    m[4]=0 -- Make sure the translation component is discarded
    m[8]=0 -- Make sure the translation component is discarded
    m[12]=0 -- Make sure the translation component is discarded
    local absoluteLinearVelocity=sim.multiplyVector(m,relativeLinearVelocity)
    -- Now set the initial velocity of the dynamic cuboid:
    sim.setObjectFloatParameter(forwarder,3000,absoluteLinearVelocity[1])
    sim.setObjectFloatParameter(forwarder,3001,absoluteLinearVelocity[2])
    sim.setObjectFloatParameter(forwarder,3002,absoluteLinearVelocity[3])
end
What above code effectively does is following: in each simulation pass, the intrinsic position of the path is modified in order to generate the intrinsic motion of the conveyor belt. At the same time, in each simulation pass, the "conveyorForwarder" object is "dynamically reset" (removed and then directly added again from/to the dynamic simulation) and an initial velocity set. The initial velocity is what will make other objects lying on it move! This is much less calculation intensive than to simulate each conveyor belt pad individually.

To conclude this tutorial, we will save the model that we just created, so that it will appear in V-REP's model browser. Select the model, then click [Menu bar --> File --> Save model as...]. A dialog appears that allows adjusting the model thumbnail image. Once you are satisfied with the thumbnail image, click Ok and navigate to V-REP's "models/equipment" folder and save the model.


Making a caterpillar

in V-REP, caterpillars are simulated by using several dynamic cylinders along the caterpillar, to give the impression the caterpillar is moving the vehicle, when in fact, the cylinders are! This means that the caterpillar pads are just "eye candy", and dynamically not enabled (they should be static and non-respondable). The method of creating caterpillars is actually very similar to making a conveyor belt with METHOD B. Following figure illustrates the caterpillar concept in V-REP: