Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Illustrative ex for viz #11

Open
wants to merge 36 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 8 commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
06398c4
Added a 3 link pendulum problem, with massless links. and
tarzzz Jun 18, 2013
11a0059
Added README
tarzzz Jun 18, 2013
d5f2d44
Update three_link_pendulum.py
tarzzz Jun 18, 2013
a61e602
Modified script for two dimensional joints
tarzzz Jun 19, 2013
e69d5cf
Merge branch '3-link-pendulum' of https://github.com/tarzzz/pydy_exam…
tarzzz Jun 19, 2013
89db91f
Added an illustrative example to demonstrate the workflow of
tarzzz Jun 19, 2013
b10d0e5
Updated to include code according to PEP8 style guide
tarzzz Jun 23, 2013
b1a923c
[WIP] Added some base classes for the illustrative example
Jul 9, 2013
aa6a338
[WIP] Some error in the numerical integration of the problem.
Jul 10, 2013
17f8f0b
WIP
Jul 12, 2013
5a79f75
[WIP] Python part nearly complete, some problems with json serialization
Jul 12, 2013
134bf88
WIP
Jul 12, 2013
f769203
[WIP] Completed Python side, although in a dirty way, with some hacks
Jul 13, 2013
31e7b65
WIP Added some javascript code
Jul 14, 2013
7c348e9
WIP Enabled visualizations of the shapes.
Jul 15, 2013
9c10bf6
Added server creating module
Jul 15, 2013
bcbca28
Added indents to JSON Output
Jul 15, 2013
f0aa71b
Added scene.display method in the run script
Jul 15, 2013
3c82531
Added README
Jul 15, 2013
8441d29
WIP
Jul 15, 2013
ae2a57b
Added static orientations to the shape
Jul 15, 2013
e60fe75
Fixed translation bug
Jul 18, 2013
f950c97
WIP Animation bug. I have kept output.json for ease in testing
Jul 19, 2013
cb5ba46
Working example now. Modified both python and Javascript code.
Jul 22, 2013
8314218
Changed time.
moorepants Aug 6, 2013
d11bd84
Modified according to new code for pydy_viz
Aug 12, 2013
5ef35c4
WIP
Aug 18, 2013
733f2ca
Removed white spaces
Aug 18, 2013
85b715e
Modified illustrative_example source
Sep 9, 2013
9fcf6bb
Merge branch 'illustrative-ex-for-viz' of github.com:tarzzz/pydy_exam…
moorepants Sep 9, 2013
4ea2488
Attempt to fix up the animation with correct link lengths and spheres…
moorepants Sep 9, 2013
0fec414
Removed comma.
moorepants Sep 9, 2013
18ad2b2
Removed extraneous line.
moorepants Sep 10, 2013
cde87c8
Modified README
Sep 22, 2013
53bddd4
Modified README
Sep 22, 2013
896a29f
Merge branch 'clean_conical' of https://github.com/PythonDynamics/pyd…
Sep 22, 2013
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
99 changes: 99 additions & 0 deletions illustrative_example_for_viz/essential.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
#This file contains all the essential methods for the
#illustrative example
#It only contains the basic implementations of pydy-viz
#also it doesnot check for TypeErrors etc.

class MeshShape(object):
def __init__(self,name,point_list,color='grey',origin=[0,0,0]):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

spaces after commas

self._name = name
self._points = point_list
self._color = color
self._origin = origin

@property
def name(self):
return self._name

@name.setter
def name(self,new_name):
self._name = new_name

@property
def points(self):
return self._points

@points.setter
def points(self,new_point_list):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think it's a bad idea that this field exists, but I think the more likely use case would be that someone makes an OBJ file in blender and wants to create a MeshShape from that file. So maybe there should be a constructor that takes an OBJ file and generates a point list from that, or that there's a separate shape that is an OBJShape or something. That would not be a high priority at all. Just running my mouth (my fingers?).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes it will should be, we should have both options, this setter, and the import_from_obj() method .

self._points = new_point_list

@property
def color(self):
return self._color

@color.setter
def color(self,new_color):
self._color = new_color

@property
def origin(self):
return self._origin

@color.setter
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

color.setter? what does that have to do with the origin

def origin(self,new_origin):
self._origin = new_origin
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will need to document the format/type for this attribute well.



class VisualizationFrame(object):
def __init__(self,name,rigidbody,shape=None):
#It is only to be used for rigidbody here, as per the
#specific requirements of the illustrative example
self._name = name
self._reference_frame = rigidbody.get_frame()
self._point = rigidbody.get_masscenter()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't remember if we were going to rename this to origin. I think we were.

self._shape = shape
self._transformation_matrix = \
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

np.eye(4)

[[1, 0, 0, 0], \
[0, 1, 0, 0], \
[0, 0, 1, 0], \
[0, 0, 0, 1]]

def homogeneous_transformation(self,rframe):
rotation_matrix = self._reference_frame.dcm(rframe)
for i in range(0,3):
for j in range(0,3):
self._transformation_matrix[i][j] = rotation_matrix
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do you mean: self._transformation_matrix[i][j] = rotation_matrix[i][j]?

You can avoid the loops with clever indexing:
self._transformation_matrix[0:3, 0:3] = rotation_matrix

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why call the attribute _transformation_matrix instead of _homogeneous_transform?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

that clever indexing perk , Thats why I just love python .. :-)

return self._transformation_matrix

def add_simulation_data(self,file_name=None):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure why this is here either. See comment below about numerics.

#TODO
pass

def generate_json():
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Look at built-in JSONEncoder class. Just an aside.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think that generate_json belongs in the VizFrame class. The json file will contain numerics and you don't get numerics until you deal with simulate and scene. Seems like the scene should generate all of the json stuff. What will this actually do in this class?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

when we provide a add_simulation_data to Vframe class instance, we provide a filename, where numerical data is stored ..
We can give that filename to the JSON..
It would be containing the stuff limited to that VFRame ..
for example ..
on calling vframe.generate_json() ...
we get something like ...

[vframe1: {name: ..., shape: ... , shape_related_numerics: ..., simulation_data: /filename.json , tranform_matrix:[ [],[],[]] ..]

and when we call
Scene.gen_json ..
it recursively calls on all vframes which are children of Scene, and take all those json objects,and compile them into one ..

[Scene1:{width:800,heigth:800, ...
vframes: { vfame1:data_got_from_vframe1.gen_json, vframe2:data_got_from_vframe2.gen_json ... }}]

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider making this method hidden; only the Scene's generate_json() needn't be hidden.

Also I don't think generate_json() is descriptive. Like, right now, I have no idea why I would want to call it. I think it should be something like Scene.print() or Scene.write_input() or something. Then stuff like VFrame's can have a _serialization() method or something. I would encourage us from moving away from the "verb" name generate_json(), and view the JSON serializatin of a VFrame, etc. as just one of its attributes, but that we need to do some processing to form.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we are also having confusion about where the symbolic side mechanics changes to numerics. I don't see why VizFrame should have any numerical values. So if there are no numeric values then generating a json file will only have metadata at the VizFrame level.

This is what I'm imagining:

# the viz frame has symbolics and the main purpose is to provide a symbolic transformation matrix
viz_frame = VisualizationFrame(shape, shape_reference_frame, shape_point)
# the we add these to the scene so we have all the info for all shapes in the scen
scene = Scene(newtonian_reference_frame, origin_point, viz_frames=(viz_frame,))
# now when we simulate the system we can tell it there is an animation scene associated with this
data = scene.simulate(kane, and_any_other_stuff_thats_needed)
# the simulation data is numerical time series for everything that we need for the three.js
jsonified_data = scene.jsonify(data)
# it uses the data in the json description to pass to the js code and three.js
scene.show()

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah okay. In my head, I thought that the symbolic equations would end up in some javascript code somewhere, and the constants and state values (data) would be available in the javascript code also. Then, the JSON file contains constants, and symbolic equations, but not time series data. But the way you describe this, Jason, is that the JSON actually contains time series data.

This mostly makes sense to me. Two questions:

  1. Does and_any_other_stuff_thats_needed include things like actual (e.g., "1.5") masses of all bodies, etc?
  2. Does calling jsonify(data) change the state of the scene object? In this case it seems like instead of jsonify we mean add_simulation_data. I would think that jsonify would just create a JSON file, and would not store in scene the necessary info to actually simulate. Sorry about any confusion on my end.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

and_any_other_stuff_thats_needed also includes masses and other numerical data(gravity etc.)

#TODO
pass

class Scene():
def __init__(self,name,reference_frame,origin,height=800,width=800):
self._name = name
self._reference_frame=reference_frame
self._origin = origin #contains point
self._child_vframes = []
self._height = height
self._width = width

@property
def vframes(self):
return self._child_vframes
@vframes.setter
def vframes(self,vframes):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In my opinion, this property shouldn't have a setter. Instead there should be a method add_visualization_frame. I think ideally there would also be a method remove_visualization_frame, but that makes it all a little bit more complex, and may not be necessary.

I also discourage the use of the vframe abbreviation in the actual code (though it's fine in our casual discussions), unless we rename VisualizationFrame to VFrame. I personally prefer the long names.

for vframe in vframes:
self._child_vframes.append(vframe)


def generate_json(self):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The package / module should be set up so that classes MUST implement this method; this could be done using the ABC module, and something like a parent object "Object" or something. Haven't thought about this too much. But say someone wants to extend your work; they shouldn't be able to create a new subclass of Shape, for example, without defining this method.

#TODO
pass




31 changes: 31 additions & 0 deletions illustrative_example_for_viz/illustrative_example.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
#Export method calls and namespace
# from three_link_pendulum example ..

from three_link_pendulum import *
from essential import *
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It isn't the best practice to use the * in imports because you don't know what you imported. If you make these explicit imports:

from essential import something, another_thing

then the code is more coherent.


#setting some shapes for the pendulums ..

shape1 = MeshShape('shape1',[[1,1,1], [0,1,1], [2,1,1]], \
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

make these variable names descriptive shape1 -> arm or cylinder or link_shape.

color='red',origin=[0,0,0])

shape2 = MeshShape('shape2',[[1,1,1], [0,1,1], [2,1,1]], \
color='blue',origin=[0,0,0])

shape3 = MeshShape('shape3',[[1,1,1], [0,1,1], [2,1,1]], \
color='green',origin=[0,0,0])

#Setting up some vframes ...

frame1 = VisualizationFrame('frame1', link1, shape=shape1)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why is there no point defintion here? Don't you need a vector to locate the VizFrame in the Scene?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The point is taken automatically from link1, which is a rigidbody.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, so why do all the links show up in the same position in the visualization? Shouldn't they be spaced out and look like a chain of cylinders? Also, add spheres for the three particles.

print frame1.homogeneous_transformation(I)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thinking about it more, it might be okay if we just call this transformation or something; that's what this is commonly called I think in most related software packages (or Transform).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We will call it transformation() meanwhile ..


frame2 = VisualizationFrame('frame2', link2, shape=shape2)
frame3 = VisualizationFrame('frame3', link3, shape=shape3)

scene = Scene('scene1',I,O)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The scene might be able to define its base frame and the O on its own; and just let the user access them if necessary. Haven't thought too much about this though.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you'll have to pass in a frame and point. Not sure where these would come from other wise? You can get the frame from the KanesMethod object if that was around anywhere, but the point isn't anywhere.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So the point is something that is necessarily part of the dynamics derivation? I was thinking the Scene could just create it, but I suppose if the rigidbodys' dynamics depend on that point, it needs to be given to the Scene.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The point I'm imagining is the "origin" of the global reference frame that three.js uses. We need map that point in three.js to a point we define with mechanics.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay I think that makes sense to me.

scene.vframes = [frame1,frame2,frame3]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it would be better if there was not a setter like this; see other comment.

print scene.vframes
scene.generate_json()


157 changes: 157 additions & 0 deletions illustrative_example_for_viz/three_link_pendulum.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
#For this one we assume RigidBody links
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is this file here? I though you have this in another pull request. Do not include it in both PR's.

from sympy import symbols,sympify
from sympy.physics.mechanics import *

#Number of links = 3
N_links = 3

#Number of masses = 3
N_bobs = 3

#Defining Dynamic Symbols ................

#Generalized coordinates(angular) ...

alpha = dynamicsymbols('alpha1 alpha2 alpha3')
beta = dynamicsymbols('beta1 beta2 beta3')

#Generalized speeds(angular) ...
alphad = dynamicsymbols('alpha1 alpha2 alpha3',1)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These are not technically the generalized speeds. The generalized speeds should be defined as:

omega = alpha'

You need to define some generalized speeds, not just the derivatives of the coordinates.

so:

omega1, omega2, omega3 = dynamicsymbols('omega1 omega2 omega3')

And similarly for beta.

betad = dynamicsymbols('beta1 beta2 beta3',1)

#Mass of each bob:
m = symbols('m:'+str(N_bobs))


#Length and mass of each link ..
l = symbols('l:' + str(N_links))
M = symbols('M:' + str(N_links))
#For storing Inertia for each link :
Ixx = symbols('Ixx:'+str(N_links))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PEP8: spaces around operators

Iyy = symbols('Iyy:'+str(N_links))

#gravity and time ....
g, t = symbols('g t')


#Now defining an Inertial ReferenceFrame First ....

I = ReferenceFrame('I')

#And some other frames ...

A = ReferenceFrame('A')
A.orient(I,'Body',[alpha[0],beta[0],0],'ZXY')
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PEP8: space after comma

B = ReferenceFrame('B')
B.orient(I,'Body',[alpha[1],beta[1],0],'ZXY')
C = ReferenceFrame('C')
C.orient(I,'Body',[alpha[2],beta[2],0],'ZXY')


#Setting angular velocities of new frames ...
A.set_ang_vel(I, alphad[0] * I.z + betad[0] * I.x)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

these should be

A.set_ang_vel(I, omega1 * I.z + gamma1 * I.x)

B.set_ang_vel(I, alphad[1] * I.z + betad[1] * I.x)
C.set_ang_vel(I, alphad[2] * I.z + betad[2] * I.x)



# An Origin point, with velocity = 0
O = Point('O')
O.set_vel(I,0)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PEP8, space after comma


#Three more points, for masses ..
P1 = O.locatenew('P1', l[0] * A.y)
P2 = O.locatenew('P2', l[1] * B.y)
P3 = O.locatenew('P3', l[2] * C.y)

#Setting velocities of points with v2pt theory ...
P1.v2pt_theory(O, I, A)
P2.v2pt_theory(P1, I, B)
P3.v2pt_theory(P2, I, C)
points = [P1,P2,P3]

Pa1 = Particle('Pa1', points[0], m[0])
Pa2 = Particle('Pa2', points[1], m[1])
Pa3 = Particle('Pa3', points[2], m[2])
particles = [Pa1,Pa2,Pa3]



#defining points for links(RigidBodies)
#Assuming CoM as l/2 ...
P_link1 = O.locatenew('P_link1', l[0]/2 * A.y)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PEP8: Space around operators.

P_link2 = O.locatenew('P_link1', l[1]/2 * B.y)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't this be:

P_link2 = P1.locatenew('P_link1', l[1] / 2 * B.y)

P_link3 = O.locatenew('P_link1', l[2]/2 * C.y)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be:

P_link3 = P2.locatenew('P_link1', l[2] / 2 * C.y)

#setting velocities of these points with v2pt theory ...
P_link1.v2pt_theory(O, I, A)
P_link2.v2pt_theory(P_link1, I, B)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P_link1 and P_link2 do not exist on the same rigid body so this is incorrect. It should be:

P_link2.v2pt_theory(P1, I, B) 

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

did you meant do not exist on same referenceframe?
because P1 represents a Particle point, not exactly on the rigidbody.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

rigid body and reference frame are synonymous in this case. The point should be the one that is at the joints.

P_link3.v2pt_theory(P_link2, I, C)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as above.


points_rigid_body = [P_link1,P_link2,P_link3]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PEP8: Spaces after commas.



#defining inertia tensors for links

inertia_link1 = inertia(A,Ixx[0],Iyy[0],0)
inertia_link2 = inertia(B,Ixx[1],Iyy[1],0)
inertia_link3 = inertia(C,Ixx[2],Iyy[2],0)

#Defining links as Rigid bodies ...

link1 = RigidBody('link1', P_link1, A, M[0], (inertia_link1, O))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do you define your inertia about the origin? Isn't the better way to define your inertia about the center of mass of each link.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I defined on the rotation axis of each rigidbody,
link1 will rotate about O, link2 about P1 etc. Isnt this the correct way>?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The "clean" way to define your inertia tensor is about the body's reference frame and the center of mass. (at least in this case). Other times it may be useful to define inertia about other points, depending on the problem.

link2 = RigidBody('link2', P_link2, B, M[1], (inertia_link2, P1))
link3 = RigidBody('link3', P_link3, C, M[2], (inertia_link3, P2))
links = [link1,link2,link3]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PEP8



#Applying forces on all particles , and adding all forces in a list..
forces = []
for particle in particles:

mass = particle.get_mass()
point = particle.get_point()
forces.append((point, -mass * g * I.y) )
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A one liner:

forces = [(p.get_point(), -p.get_mass() * g * I.y) for p in particles]


#Applying forces on rigidbodies ..
for link in links:
mass = link.get_mass()
point = link.get_masscenter()
forces.append((point, -mass * g * I.y) )
kinetic_differentials = []
for i in range(0,N_bobs):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

range(N_bobs) does the same thing.

kinetic_differentials.append(alphad[i] - alpha[i])
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this should be

kinetic_differentials.append(omega1 - alphad[i]) 

omega = alpha'

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And it really should be kinematic_differential_equations. Kinetic means "involving forces", kinda. And Differentials are like dt; here, we really mean differential equations.

kinetic_differentials.append(betad[i] - beta[i])

#Adding particles and links in the same system ...
total_system = []
for particle in particles:
total_system.append(particle)

for link in links:
total_system.append(link)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This can be a one liner:

total_system = particles + links


q = []
for angle in alpha:
q.append(angle)
for angle in beta:
q.append(angle)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

q = alpha + beta

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you may have to do:

q = list(q) + list(beta)

print q
u = []

for vel in alphad:
u.append(vel)
for vel in betad:
u.append(vel)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

u = omega + delta


print u
kane = KanesMethod(I, q_ind=q, u_ind=u, kd_eqs=kinetic_differentials)
fr, frstar = kane.kanes_equations(forces, total_system)

print fr







2 changes: 2 additions & 0 deletions three_link_pendulum/README
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
This is a 3 link pendulum problem, assuming links as RigidBodies ..
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why is this file here?

I will add a fig soon ..
Loading