Make a spider robot in SolidWorks and simulate it

This demo is about the simulation of a crawling spider robot with six legs, where we control the motion of the legs with 18 actuators.

In deail, one performs the following steps:

  • Use SolidWorks to make a 3D CAD model of the crawling robot,
  • export it as a .pyfile using the Chrono::SolidWorks add-in; ex. use the name spider_robot.py
  • create a Python program, ex. use the name demo_spider.py, using the functions of Chrono::PyEngine to load and simulate spider_robot.py.

For your convenience, the CAD model, the converted spider_robot.py model, and the demo_spider.py program are all available in the following archive:

spider_robot.zip.

The following is the complete listing of demo_spider.py (it must stay in the same directory where you exported your CAD model with the name spider_robot.py)

Note how we used mybody = mysystem.SearchBody('...'); and mymarker = mybody.SearchMarker('...'); to retrieve object pointers from their names in the 3D CAD model. Also note that a part that shows as M-410iB-300 -1/ArmBase<1> in the GUI of SolidWorks, becomes M-410iB-300 -1/ArmBase-1 for the Python side; i.e. the <N> suffix becomes -N.

Finally, note how we used ChFunction objects to build some basic loop motions for the actuators, in prescribed rotation mode.

1 def main():
2  pass
3 
4 if __name__ == '__main__':
5  main()
6 
7 
8 import os
9 import math
10 import ChronoEngine_python_core as chrono
11 import ChronoEngine_python_postprocess as postprocess
12 import ChronoEngine_python_irrlicht as chronoirr
13 
14 print ("Load a model exported by SolidWorks");
15 
16 
17 
18 # ---------------------------------------------------------------------
19 #
20 # Create the simulation system and add items
21 #
22 
23 mysystem = chrono.ChSystemNSC()
24 
25 parts = chrono.ImportSolidWorksSystem('./spider_robot');
26 
27 for ib in parts:
28  mysystem.Add(ib);
29 
30 # Retrieve objects from their name as saved from the SolidWorks interface
31 # (look the spider_robot.py file to guess them, or look their name in SW)
32 
33 bbody = mysystem.SearchBody('Part3^SPIDER_ROBOT-1');
34 bbody.SetBodyFixed(False);
35 b1base = mysystem.SearchBody('M-410iB-300 -1/ArmBase-1');
36 b1turret = mysystem.SearchBody('M-410iB-300 -1/M-410iB-300-02-1');
37 b1bicept = mysystem.SearchBody('M-410iB-300 -1/M-410iB-300-03-1');
38 b1forearm = mysystem.SearchBody('M-410iB-300 -1/M-410iB-300-06-1');
39 m1_1B = b1base. SearchMarker('marker_M1_B');
40 m1_1A = b1turret. SearchMarker('marker_M1_A');
41 m1_2B = b1turret. SearchMarker('marker_M2_B');
42 m1_2A = b1bicept. SearchMarker('marker_M2_A');
43 m1_3B = b1bicept. SearchMarker('marker_M3_B');
44 m1_3A = b1forearm.SearchMarker('marker_M3_A');
45 b2base = mysystem.SearchBody('M-410iB-300 -2/ArmBase-1');
46 b2turret = mysystem.SearchBody('M-410iB-300 -2/M-410iB-300-02-1');
47 b2bicept = mysystem.SearchBody('M-410iB-300 -2/M-410iB-300-03-1');
48 b2forearm = mysystem.SearchBody('M-410iB-300 -2/M-410iB-300-06-1');
49 m2_1B = b2base. SearchMarker('marker_M1_B');
50 m2_1A = b2turret. SearchMarker('marker_M1_A');
51 m2_2B = b2turret. SearchMarker('marker_M2_B');
52 m2_2A = b2bicept. SearchMarker('marker_M2_A');
53 m2_3B = b2bicept. SearchMarker('marker_M3_B');
54 m2_3A = b2forearm.SearchMarker('marker_M3_A');
55 b3base = mysystem.SearchBody('M-410iB-300 -3/ArmBase-1');
56 b3turret = mysystem.SearchBody('M-410iB-300 -3/M-410iB-300-02-1');
57 b3bicept = mysystem.SearchBody('M-410iB-300 -3/M-410iB-300-03-1');
58 b3forearm = mysystem.SearchBody('M-410iB-300 -3/M-410iB-300-06-1');
59 m3_1B = b3base. SearchMarker('marker_M1_B');
60 m3_1A = b3turret. SearchMarker('marker_M1_A');
61 m3_2B = b3turret. SearchMarker('marker_M2_B');
62 m3_2A = b3bicept. SearchMarker('marker_M2_A');
63 m3_3B = b3bicept. SearchMarker('marker_M3_B');
64 m3_3A = b3forearm.SearchMarker('marker_M3_A');
65 b7base = mysystem.SearchBody('M-410iB-300 -7/ArmBase-1');
66 b7turret = mysystem.SearchBody('M-410iB-300 -7/M-410iB-300-02-1');
67 b7bicept = mysystem.SearchBody('M-410iB-300 -7/M-410iB-300-03-1');
68 b7forearm = mysystem.SearchBody('M-410iB-300 -7/M-410iB-300-06-1');
69 m7_1B = b7base. SearchMarker('marker_M1_B');
70 m7_1A = b7turret. SearchMarker('marker_M1_A');
71 m7_2B = b7turret. SearchMarker('marker_M2_B');
72 m7_2A = b7bicept. SearchMarker('marker_M2_A');
73 m7_3B = b7bicept. SearchMarker('marker_M3_B');
74 m7_3A = b7forearm.SearchMarker('marker_M3_A');
75 b8base = mysystem.SearchBody('M-410iB-300 -8/ArmBase-1');
76 b8turret = mysystem.SearchBody('M-410iB-300 -8/M-410iB-300-02-1');
77 b8bicept = mysystem.SearchBody('M-410iB-300 -8/M-410iB-300-03-1');
78 b8forearm = mysystem.SearchBody('M-410iB-300 -8/M-410iB-300-06-1');
79 m8_1B = b8base. SearchMarker('marker_M1_B');
80 m8_1A = b8turret. SearchMarker('marker_M1_A');
81 m8_2B = b8turret. SearchMarker('marker_M2_B');
82 m8_2A = b8bicept. SearchMarker('marker_M2_A');
83 m8_3B = b8bicept. SearchMarker('marker_M3_B');
84 m8_3A = b8forearm.SearchMarker('marker_M3_A');
85 b9base = mysystem.SearchBody('M-410iB-300 -9/ArmBase-1');
86 b9turret = mysystem.SearchBody('M-410iB-300 -9/M-410iB-300-02-1');
87 b9bicept = mysystem.SearchBody('M-410iB-300 -9/M-410iB-300-03-1');
88 b9forearm = mysystem.SearchBody('M-410iB-300 -9/M-410iB-300-06-1');
89 m9_1B = b9base. SearchMarker('marker_M1_B');
90 m9_1A = b9turret. SearchMarker('marker_M1_A');
91 m9_2B = b9turret. SearchMarker('marker_M2_B');
92 m9_2A = b9bicept. SearchMarker('marker_M2_A');
93 m9_3B = b9bicept. SearchMarker('marker_M3_B');
94 m9_3A = b9forearm.SearchMarker('marker_M3_A');
95 
96 
97 
98 period = 2;
99 mfunc_sineS = chrono.ChFunction_Sine(0, 1.0/period, 0.2); # phase, frequency, amplitude
100 mfunc_swingSa = chrono.ChFunction_Repeat();
101 mfunc_swingSa.Set_fa(mfunc_sineS);
102 mfunc_swingSa.Set_window_length(period);
103 mfunc_swingSa.Set_window_start(0);
104 mfunc_swingSb = chrono.ChFunction_Repeat();
105 mfunc_swingSb.Set_fa(mfunc_sineS);
106 mfunc_swingSb.Set_window_length(period);
107 mfunc_swingSb.Set_window_start(period/2.0);
108 mfunc_sineD = chrono.ChFunction_Sine(0, 1.0/period, -0.2); # phase, frequency, amplitude
109 mfunc_swingDb = chrono.ChFunction_Repeat();
110 mfunc_swingDb.Set_fa(mfunc_sineD);
111 mfunc_swingDb.Set_window_length(period);
112 mfunc_swingDb.Set_window_start(period/2.0);
113 mfunc_swingDa = chrono.ChFunction_Repeat();
114 mfunc_swingDa.Set_fa(mfunc_sineD);
115 mfunc_swingDa.Set_window_length(period);
116 mfunc_swingDa.Set_window_start(0);
117 
118 
119 mfunc_sigma = chrono.ChFunction_Sigma();
120 mfunc_sigma.Set_amp(-0.2);
121 mfunc_sigma.Set_end(0.5);
122 mfunc_const = chrono.ChFunction_Const();
123 mfunc_sigmb = chrono.ChFunction_Sigma();
124 mfunc_sigmb.Set_amp(0.2);
125 mfunc_sigmb.Set_end(0.5);
126 mfunc_seq = chrono.ChFunction_Sequence();
127 mfunc_seq.InsertFunct(mfunc_sigma, 0.5, 1, True); # fx, duration, weight, C0 continuity
128 mfunc_seq.InsertFunct(mfunc_const, 1.0, 1, True); # fx, duration, weight, C0 continuity
129 mfunc_seq.InsertFunct(mfunc_sigmb, 0.5, 1, True); # fx, duration, weight, C0 continuity
130 mfunc_updownA = chrono.ChFunction_Repeat();
131 mfunc_updownA.Set_fa(mfunc_seq);
132 mfunc_updownA.Set_window_length(period);
133 mfunc_updownB = chrono.ChFunction_Repeat();
134 mfunc_updownB.Set_fa(mfunc_seq);
135 mfunc_updownB.Set_window_length(period);
136 mfunc_updownB.Set_window_phase(period/2.0);
137 
138 # Add actuators to Leg n.1
139 
140 motor1_1 = chrono.ChLinkEngine();
141 motor1_1.Initialize(m1_1A, m1_1B);
142 motor1_1.Set_eng_mode(chrono.ChLinkEngine.ENG_MODE_ROTATION);
143 motor1_1.Set_rot_funct(mfunc_swingSa);
144 mysystem.Add(motor1_1);
145 
146 motor1_2 = chrono.ChLinkEngine();
147 motor1_2.Initialize(m1_2A, m1_2B);
148 motor1_2.Set_eng_mode(chrono.ChLinkEngine.ENG_MODE_ROTATION);
149 motor1_2.Set_rot_funct(mfunc_updownA);
150 mysystem.Add(motor1_2);
151 
152 motor1_3 = chrono.ChLinkEngine();
153 motor1_3.Initialize(m1_3A, m1_3B);
154 motor1_3.Set_eng_mode(chrono.ChLinkEngine.ENG_MODE_ROTATION);
155 motor1_3.Set_rot_funct(mfunc_const);
156 mysystem.Add(motor1_3);
157 
158 # Add actuators to Leg n.2
159 
160 motor2_1 = chrono.ChLinkEngine();
161 motor2_1.Initialize(m2_1A, m2_1B);
162 motor2_1.Set_eng_mode(chrono.ChLinkEngine.ENG_MODE_ROTATION);
163 motor2_1.Set_rot_funct(mfunc_swingSb);
164 mysystem.Add(motor2_1);
165 
166 motor2_2 = chrono.ChLinkEngine();
167 motor2_2.Initialize(m2_2A, m2_2B);
168 motor2_2.Set_eng_mode(chrono.ChLinkEngine.ENG_MODE_ROTATION);
169 motor2_2.Set_rot_funct(mfunc_updownB);
170 mysystem.Add(motor2_2);
171 
172 motor2_3 = chrono.ChLinkEngine();
173 motor2_3.Initialize(m2_3A, m2_3B);
174 motor2_3.Set_eng_mode(chrono.ChLinkEngine.ENG_MODE_ROTATION);
175 motor2_3.Set_rot_funct(mfunc_const);
176 mysystem.Add(motor2_3);
177 
178 # Add actuators to Leg n.3
179 
180 motor3_1 = chrono.ChLinkEngine();
181 motor3_1.Initialize(m3_1A, m3_1B);
182 motor3_1.Set_eng_mode(chrono.ChLinkEngine.ENG_MODE_ROTATION);
183 motor3_1.Set_rot_funct(mfunc_swingSa);
184 mysystem.Add(motor3_1);
185 
186 motor3_2 = chrono.ChLinkEngine();
187 motor3_2.Initialize(m3_2A, m3_2B);
188 motor3_2.Set_eng_mode(chrono.ChLinkEngine.ENG_MODE_ROTATION);
189 motor3_2.Set_rot_funct(mfunc_updownA);
190 mysystem.Add(motor3_2);
191 
192 motor3_3 = chrono.ChLinkEngine();
193 motor3_3.Initialize(m3_3A, m3_3B);
194 motor3_3.Set_eng_mode(chrono.ChLinkEngine.ENG_MODE_ROTATION);
195 motor3_3.Set_rot_funct(mfunc_const);
196 mysystem.Add(motor3_3);
197 
198 # Add actuators to Leg n.9
199 
200 motor9_1 = chrono.ChLinkEngine();
201 motor9_1.Initialize(m9_1A, m9_1B);
202 motor9_1.Set_eng_mode(chrono.ChLinkEngine.ENG_MODE_ROTATION);
203 motor9_1.Set_rot_funct(mfunc_swingDb);
204 mysystem.Add(motor9_1);
205 
206 motor9_2 = chrono.ChLinkEngine();
207 motor9_2.Initialize(m9_2A, m9_2B);
208 motor9_2.Set_eng_mode(chrono.ChLinkEngine.ENG_MODE_ROTATION);
209 motor9_2.Set_rot_funct(mfunc_updownB);
210 mysystem.Add(motor9_2);
211 
212 motor9_3 = chrono.ChLinkEngine();
213 motor9_3.Initialize(m9_3A, m9_3B);
214 motor9_3.Set_eng_mode(chrono.ChLinkEngine.ENG_MODE_ROTATION);
215 motor9_3.Set_rot_funct(mfunc_const);
216 mysystem.Add(motor9_3);
217 
218 # Add actuators to Leg n.8
219 
220 motor8_1 = chrono.ChLinkEngine();
221 motor8_1.Initialize(m8_1A, m8_1B);
222 motor8_1.Set_eng_mode(chrono.ChLinkEngine.ENG_MODE_ROTATION);
223 motor8_1.Set_rot_funct(mfunc_swingDa);
224 mysystem.Add(motor8_1);
225 
226 motor8_2 = chrono.ChLinkEngine();
227 motor8_2.Initialize(m8_2A, m8_2B);
228 motor8_2.Set_eng_mode(chrono.ChLinkEngine.ENG_MODE_ROTATION);
229 motor8_2.Set_rot_funct(mfunc_updownA);
230 mysystem.Add(motor8_2);
231 
232 motor8_3 = chrono.ChLinkEngine();
233 motor8_3.Initialize(m8_3A, m8_3B);
234 motor8_3.Set_eng_mode(chrono.ChLinkEngine.ENG_MODE_ROTATION);
235 motor8_3.Set_rot_funct(mfunc_const);
236 mysystem.Add(motor8_3);
237 
238 # Add actuators to Leg n.7
239 
240 motor7_1 = chrono.ChLinkEngine();
241 motor7_1.Initialize(m7_1A, m7_1B);
242 motor7_1.Set_eng_mode(chrono.ChLinkEngine.ENG_MODE_ROTATION);
243 motor7_1.Set_rot_funct(mfunc_swingDb);
244 mysystem.Add(motor7_1);
245 
246 motor7_2 = chrono.ChLinkEngine();
247 motor7_2.Initialize(m7_2A, m7_2B);
248 motor7_2.Set_eng_mode(chrono.ChLinkEngine.ENG_MODE_ROTATION);
249 motor7_2.Set_rot_funct(mfunc_updownB);
250 mysystem.Add(motor7_2);
251 
252 motor7_3 = chrono.ChLinkEngine();
253 motor7_3.Initialize(m7_3A, m7_3B);
254 motor7_3.Set_eng_mode(chrono.ChLinkEngine.ENG_MODE_ROTATION);
255 motor7_3.Set_rot_funct(mfunc_const);
256 mysystem.Add(motor7_3);
257 
258 #
259 # Create a floor
260 
261 mfloor = chrono.ChBody();
262 mfloor.SetBodyFixed(True);
263 mfloor.GetCollisionModel().ClearModel();
264 mfloor.GetCollisionModel().AddBox(10,0.5,10, chrono.ChVectorD(0,0.3,0));
265 mfloor.GetCollisionModel().BuildModel();
266 mfloor.SetCollide(True);
267 mysystem.Add(mfloor);
268 
269 mfloorshape = chrono.ChBoxShape();
270 mfloorshape.GetBoxGeometry().Size = chrono.ChVectorD(10,0.5,10);
271 mfloorshape.GetBoxGeometry().Pos = chrono.ChVectorD(0,0.3,0);
272 mfloor.AddAsset(mfloorshape);
273 
274 mfloorcolor = chrono.ChColorAsset(0.2,0.2,0.2);
275 mfloor.AddAsset(mfloorcolor);
276 
277 # ---------------------------------------------------------------------
278 #
279 # Create an Irrlicht application to visualize the system
280 #
281 
282 myapplication = chronoirr.ChIrrApp(mysystem, 'Test', chronoirr.dimension2du(1280,720))
283 
284 myapplication.AddTypicalSky('./data/skybox/')
285 myapplication.AddTypicalCamera(chronoirr.vector3df(2.8,2.6,2.8),chronoirr.vector3df(0.0,2.6,0.0))
286 myapplication.AddTypicalLights()
287 myapplication.AddLightWithShadow(chronoirr.vector3df(10,20,10),chronoirr.vector3df(0,2.6,0), 10 ,10,40, 60, 512);
288 
289  # ==IMPORTANT!== Use this function for adding a ChIrrNodeAsset to all items
290  # in the system. These ChIrrNodeAsset assets are 'proxies' to the Irrlicht meshes.
291  # If you need a finer control on which item really needs a visualization proxy in
292  # Irrlicht, just use application.AssetBind(myitem); on a per-item basis.
293 
294 myapplication.AssetBindAll();
295 
296  # ==IMPORTANT!== Use this function for 'converting' into Irrlicht meshes the assets
297  # that you added to the bodies into 3D shapes, they can be visualized by Irrlicht!
298 
299 myapplication.AssetUpdateAll();
300 
301  # ==IMPORTANT!== Use this function for enabling cast soft shadows
302 
303 myapplication.AddShadowAll();
304 
305 # ---------------------------------------------------------------------
306 #
307 # Run the simulation
308 #
309 
310 mysystem.SetMaxItersSolverSpeed(600);
311 mysystem.SetSolverWarmStarting(True);
312 mysystem.SetSolverType(chrono.ChSolver.Type_BARZILAIBORWEIN);
313 myapplication.SetTimestep(0.002):
314 
315 
316 while(myapplication.GetDevice().run()):
317  myapplication.BeginScene()
318  myapplication.DrawAll()
319  myapplication.DoStep()
320  myapplication.EndScene()