0

I would like to find the position [X,Y,Z] of several elements in order to have the global center of gravity at a desired point.

To do so, I defined 2 classes:

  • elements which store the element's mass and position
  • plane which takes a list of element and can compute its center of gravity according to the set of element.

I also defined an error function which compute the difference between the actual global center of gravity from the plane's set of elements and the desired center of gravity.

To minimize this function, I wanted to use the scypi.minimize function with the Nelder-Mead Simplex algorithm.

I put each element's coordinate into x0 and then pass x0 and the error function as parameter to minimize.

I received this error which I don't understand.:

ValueError: setting an array element with a sequence. 

Moreover according to what I want to do, you may have a better idea to solve/fix my problem?

here is the code :

import numpy as np
from scipy.optimize import minimize

class plane(object):
  def __init__(self, elts):
    self.elements=elts
    self.TotalMasse=self.calc_masse(self.elements) 
    self.cdg = self.calc_CDG()

  def __getitem__(self):
    return self.elements,self.TotalMasse

  def calc_masse(self,elements):
    Lm=[]
    for el in elements:
      Lm.append(el.masse)
    return sum(Lm)

  def calc_CDG(self):
    Xcdg=0
    Ycdg=0
    Zcdg=0
    for el in self.elements:
      Xcdg+=el.masse*el.position[0]/self.TotalMasse
      Ycdg+=el.masse*el.position[1]/self.TotalMasse
      Zcdg+=el.masse*el.position[2]/self.TotalMasse
    return [Xcdg,Ycdg,Zcdg]

class element(object):
  def __init__(self, mass, pos):
    self.masse=mass
    self.position=pos

  def __getitem__(self):
    return self.masse, self.position



def calculErreurPosCDG(cdg):
    global positionCDGconsigne
    return [positionCDGconsigne[0]-cdg[0], positionCDGconsigne[1]-cdg[1],positionCDGconsigne[2]-cdg[2]]

battery = element(0.5,[0.5,1,1])
motor = element(0.2,[1,1,0])
servoL = element(0.01,[-0.7,1,0])
servoR = element(0.01,[0.7,1,0])
reciever = element(0.01,[0.1,1,1])

elements=[battery, motor, servoL, servoR, reciever]

positionCDGconsigne=[1,1,1]

plane1=plane(elements)

x0=np.array([])
for el in elements:
  x0= np.append(x0,[el.position])

res=minimize(calculErreurPosCDG,x0,method='nelder-mead', options={'xtol':1e-8,'disp':True})
CraigTeegarden
  • 8,173
  • 8
  • 38
  • 43
CrH
  • 1
  • 1

2 Answers2

0

Your target function returns a list, while minimize expects a scalar. You need to set your problem first and specify what exactly do you mean by minimizing a vector-valued function.

ev-br
  • 24,968
  • 9
  • 65
  • 78
0

You should be able to run minimize three times per co-ordinate component (x, y and z), separately. Modifying calculErreurPosCDG to handle a single value rather than a vector should then make it work. Then it will be handling scalars only.

Added note: it is good practice to start the names of Classes in Python with an upper-case letter, and functions with a lower-case letter.

  • according to your advises, here is what i did : i modified x0 in order to take only the X coordinate i did this for x,y,z i modified the objectiv function : calculErreurPosCDG and the Plane class, in order to recompute the center of gravity after each iteration But the fact is, its diverging even if all elements are already in a good position (cf. Y-coordinates ) `def calculErreurPosCDGX(x0): global positionCDGconsigne,plane1 i=0 for el in elements: el.position[0]=x0[i] i+=1 plane1.update() print plane1.cdg return positionCDGconsigne[0]-plane1.cdg[0]` – CrH Mar 13 '13 at 15:06