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