In this tutorial we will be building a hexapod walking robot. Make sure that you have read the BubbleRob tutorial and the tutorial on importing and preparing rigid bodies before starting with this one. The V-REP CAD data, courtesy of Lyall Randell, related to this tutorial ("hexapod.dxf") is located in V-REP's installation folder's "cadFiles" folder. A finished model related to this tutorial can be found in V-REP's model browser. Click [Menu bar --> File --> Import --> Mesh...] then select the file to import. Also refer to the section on how to import/export shapes. A dialog pops open asking about mesh scaling and mesh orientation. Click Ok. Several shapes were imported and are located in the middle of the scene. The shapes also appear in the scene hierarchy on the left hand side of the main window. Depending on how the original CAD data was exported, the imported CAD data could be at a different scale, different location, or even grouped as a single shape. The assigned color of imported shapes is random. Following figure shows the imported shapes:
As you can see, the hexapod robot has 6 identical legs. So instead of preparing each leg individually, we will prepare one leg, and when it is done, just copy-and-paste it to the right locations! Select in the scene the shapes to delete (use the ctrl-click and/or the shift-click for the selection process), then press the delete-key (make sure you kept the leg pointing towards the world x-axis):
The import operation has left us with 3 shapes per leg, so we will need to subdivide those 3 shapes further, in order to have separate shapes for the leg-links and the leg-servo motors. Select the 3 shapes then click [Menu bar --> Edit --> Grouping/Merging --> Divide selected shapes]. You can see that this operation has divided the shape closest to the robot body into 3 sub-shapes, where we only expected 2 sub-shapes. To correct for this, select the left and right link elements as shown in following figure:
While the two shapes are still selected, click [Menu bar --> Edit --> Grouping/Merging --> Merge selected shapes] in order to merge them into a single shape.
In next step, we will add the joints required for our leg mechanism. One way of doing this is to add the joints into the scene, then specify their appropriate position and orientation (through the position dialog or the orientation dialog). This is however not possible, when you don't know the exact joint positions as in our case, and so we will have to extract them from the shapes that we have:
Select the 3 shapes that represent the servo motors, copy them (ctrl-c or [Menu bar --> Edit --> Copy selected objects]), then create a new scene with [Menu bar --> File --> New scene], then paste the shapes (ctrl-v or [Menu bar --> Edit --> Paste Buffer]). We are now in another scene (scene 2), and whatever we do here will not affect our original scene. Now keep the 3 servo motors selected and click [Menu bar --> Edit --> Grouping/Merging --> Merge selected shapes] to merge them as a single shape. Then enter the triangle edit mode. All triangles composing our shape are now displayed and can be manipulated.
Shift-select all triangles composing one of the servo motors' output shaft as illustrated in following figures:
Then click the Extract shape button in the shape edit mode dialog. Do the same with the two other servo motor output shafts (for the third servo motor, you will have to switch to page 3 to be able to shift-select its output shaft):
Switch back to page 1, leave the edit mode, then delete the shape representing the 3 servo motors. Now the extracted shafts become clearly visible:
We can use the extracted shapes to precisely position our joints. Click [Menu bar --> Add --> Joint --> Revolute] to insert a revolute joint into the scene. The default position is at (0;0;0) and its default orientation is vertical. While the joint is still selected, ctrl-select the shape representing the vertical output shaft, then open the position dialog , move to position tab and click the Apply to selection button.
This just positioned the joint at the exact same coordinates as the vertical output shaft! Now repeat the procedure with two additional joints and the two horizontal shafts. All joints are in position now, however, only the first added joint has the correct orientation. Select the two last added joints, then enter (-90,0,0) for the Alpha, Beta and Gamma items in the orientation dialog, on the orientation tab, then click the Apply to selection button. All joints have the right position and orientation now. Select all 3 joints, copy them to the buffer (ctrl-c), switch back to the initial scene (scene 1), then paste the buffer (ctrl-v). This is what you should have:
You can now adjust the joint sizes (check the Joint length and Joint diameter items) in the joint properties dialog (that you can open by double-clicking a joint icon in the scene hierarchy). Additionally, we want the 2 horizontal joints to be located at y-coordinate 0, and the vertical joint to be located at a z-coordinate similar to its servo motor:
Rename your joints to "hexa_joint1", "hexa_joint2" and "hexa_joint3" (from body to foot). You can do this by double-clicking the joint's names in the scene hierarchy. Now let's set the initial joint values so that when the leg is horizontally stretched, all joint values are zero: in the joint dialog, item Position, set -30 and +120 for "hexa_joint2" and "hexa_joint3". Notice how joints are in torque/force mode. In our case we want to be able to control those joints in inverse kinematics mode, but we also want the inverse kinematics results to be applied as dynamics position control values. To do this, we will set the joints in inverse kinematics mode (select "joint is in inverse kinematics mode" in the Joint mode section). In addition to that, we also activate the Hybrid operation for that joint (this tells V-REP that the inverse kinematics calculation results will be applied to the joint as dynamic target value). Click Apply to selection to apply the changes you just performed to the other two joints that are selected.
At this point, we should prepare the visual appearance of our shapes, group them if required, and prepare corresponding pure shapes for the dynamic simulation. Details on how this is done will not be explained here, since the procedure is very similar to what is done in the tutorial on importing and preparing rigid bodies. Once you finished this step, this is what you should have (visible and hidden parts):
The above scene is "tutorials\Hexapod\hexapod intermediate step.ttt". Notice following:
Next, we will be linking current elements of the mechanism. Select "hexa_link3Respondable" then "hexa_joint3", and click [Menu bar --> Edit --> Make last selected object parent]. Do the same with "hexa_joint3" and "hexa_link2Respondable", "hexa_link2Respondable" and "hexa_joint2", "hexa_joint2" and "hexa_link1Respondable", "hexa_link1Respondable" and "hexa_joint1", and finally "hexa_joint1" and "hexapod". We have assembled the first leg. Start the simulation and observe how rigid objects are constrained by the joints. Notice also that joints are not keeping a fixed position, but slowly drifting: this is because we haven't yet defined an inverse kinematics task for our kinematic chain representing the leg. This is what we will be doing next.
Add a dummy object with [Menu bar --> Add --> Dummy]. Rename it to "hexa_footTip". Now position the dummy at the tip of the leg, where the leg is contacting the floor. You can achieve this by using the object manipulation toolbar buttons, or by using the position dialog. In former case, it can be useful to adjust the position step-by-step by switching to orthogonal projection views on page 2, page 3, page 4, page 5 or page 6. Once done, the dummy's absolute position should be close to (0.204,0,0). Next, attach the dummy to "hexa_link3" (drag the dummy onto "hexa_link3" in the scene hierarchy). Then copy and paste "hexa_footTip" and rename the copy to "hexa_footTarget".
What we want at this stage, is to have "hexa_footTip" follow "hexa_footTarget", while having the attached mechanism automatically adjust for that (i.e. while having the new joint positions automatically calculated). We have to define an inverse kinematic task:
First, let's inform the two dummies that they are a tip-target pair for inverse kinematics resolution. Double-click the dummy icon of "hexa_footTip" in the scene hierarchy: this opens the dummy properties dialog. In the Dummy-dummy linking section, specify "hexa_footTarget" as Linked dummy. Notice how both dummies got linked through a red stippled line in the scene hierarchy (the two dummies are also linked in the scene through a red line, but since both dummies are coincident, the line cannot be seen). In the same dialog, Link type is already "IK, tip-target", which is the default value. This is what you should have by now:
Now open the inverse kinematics dialog, and click Add new IK group. A new item appears in the IK groups list: "IK_Group". While that item is selected, open the IK element dialog (click Edit IK elements) and indicate "hexa_footTip" in the drop-down box right to Add new IK element with tip. Then click Add new IK element with tip. Close the dialog, and attach "hexa_footTarget" to "hexapod". Our inverse kinematics task is ready for this leg! Let's test it.
First, temporarily disable dynamics by opening the general dynamics properties dialog, then unchecking Dynamics enabled. Next, start the simulation and in the scene hierarch select "hexa_footTarget". Move the "hexa_footTarget" around with the mouse: the leg should follow. Stop the simulation and enable dynamics again.
We will control the hexapod robot by generating the movement for one leg, and applying it in a delayed way for all 6 legs, where each leg will have a different delay. We implement this by having one child script generating the movement sequence for one leg, and having 6 additional child scripts applying that movement sequence in a delayed manner. Select "hexa_joint1" and click [Menu bar --> Add --> Associated child script --> Non threaded]. We just attached a child script to the "hexa_joint1" object.
Now we will duplicate the leg 5 times. Select all objects composing the leg (hidden objects as well): from "hexa_joint1" to "hexa_footTip". Also select "hexa_footTarget". Make sure that "hexa_bodyRespondable" and "hexa_body" are not selected, then copy and paste the objects. Open the orientation dialog, move to orientation tab and enter "60" for the Around Z item. Make sure the transformation will be relative to World, then click Z-rotate selection. Paste the initial leg another time, then adjust the Around Z item to 120, then click Z-rotate selection again. Repeat the procedure for the remaining 3 legs (make sure you adjust the rotation angle to 180, 240 and finally 300 degrees). This is what you should have:
Let's attach all legs to the body. Select "hexa_joint1#0" through "hexa_joint1#4", then "hexapod", and click [Menu bar --> Edit --> Make last selected object parent]. In the scene hierarch, collapse all leg trees by clicking their "-" icon. Then select "hexa_footTarget#0" through "hexa_footTarget#4", then "hexapod", and click [Menu bar --> Edit --> Make last selected object parent].
Open the inverse kinematics dialog. Notice how the inverse kinematics tasks were also copied. This is what you should have:
Close the inverse kinematics dialog. Open the object selection dialog with [Menu bar --> Tools --> Selection], or by pressing the appropriate toolbar button. Click Clear Selection, then Dummies: 0/13. All dummies in the scene have been selected. Deselect (with ctrl-click) the dummy that is not part of the hexapod robot. We now have our 12 dummies on the hexapod selected. Now open the object common properties. In the Visibility layers section, disable layer 3 and enable layer 11, then click the related Apply to selection button. This just sent all dummies to the visibility layer 11, effectively making them invisible. Have a look at the layer selection dialog if you wish to temporarily enable/disable some layers.
Next, send all joints to the visibility layer 10 by following the same procedure as above.
Then add a new dummy to the scene and rename it "hexa_base". Also send it to the visibility layer 11. Then make it child of "hexapod". "hexa_base" represents the position of our hexapod robot, that we selected to be (0;0;0).
Now let's define the hexapod model. As you might have noticed, when you click an object on the hexapod robot, only that object gets selected. But what we now want is to protect individual objects from modification, and select the whole robot instead. For each object composing the hexapod robot, except for the object "hexapod", enable the Select base of model instead item in the object common properties dialog. Clear the selection, then select "hexapod". In the same dialog, enable the Object is model base item. Now click any object on the hexapod robot: the whole robot now gets selected instead:
Now attach a non-threaded child script to "hexapod". Create another scene (scene 3), and open the "hexapod.ttm" model file. Double-click the child script icon of object "hexapod" to open the script editor. Copy the script, switch back to the original scene (scene 1), double-click the child script icon of object "hexapod" and paste the script. Repeat the same procedure for the child scripts associated with each leg. Notice how all child scripts associated with the hexapod's legs are exactly the same. A last element is still missing: we need each leg to apply the movement sequence with a different time delay. If you take a closer look at the legs' child scripts, they are each reading a delay value from their script simulation parameters with the instruction:
You can open the script simulation parameter dialog by double-clicking the icon on the right hand side of a child script. Add the exact same script simulation parameters as the hexapod in the other scene. Run the simulation. The hexapod robot should now walk.