0

So I am having a strange problem in python. I am using the code below to create a plot of places where the object has been. Here is my code:

def GoForward(self, duration):
    if (self.TowardsX - self.X == 0):
        Myro.robot.motors(self.Speed, self.Speed)
        Myro.wait(abs(duration))
        Myro.robot.stop()
        #get the amount of points forward
        divisible = (int) (duration / self.Scale)
        #add them to the direction
        self.TowardsY += divisible
        tempY = self.Y
        for y in xrange(self.Y, divisible + tempY):
            if (y % self.Scale == 0):
                self.Plot[(int) (self.X)][y] = 1
        return
    #calc slope
    slope = (self.TowardsY - self.Y) / (self.TowardsX - self.X)
    tempX = self.X
    tempY = self.Y
    #go forward
    #get the amount of points forward
    divisible = duration / self.Scale
    #add them to the direction
    self.TowardsX += divisible
    self.TowardsY += divisible
    Xs = []
    Ys = []
    for x in xrange(self.X, tempX + divisible):
        #find out if it is a plottable point
        if (((slope * (x - self.X)) + self.Y) % self.Scale == 0.0):
            Xs.append(x)
            Ys.append((int)((slope * (x - self.X)) + self.Y))
    #Plot the points
    for i in xrange(0, len(Xs)):
        for j in xrange(0, len(Ys)):
            if (self.Plot[Xs[i]][Ys[j]] == 0):
                self.Plot[Xs[i]][Ys[j]] = 1
    self.X += divisible
    self.Y += divisible

But, when I call GoForward(2) it fills five columns with ones, instead of the few points. Example:

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

Based off the parameter given to GoForward(n) it creates that many columns full of 0s... Why is this behavior happening? My code should not produce this effect, but I am inexperienced with python so is that why this is happening? Thanks in advance

EDIT

So I have changed the code for plotting the points to

for i in xrange(0, len(Xs)):
    if (self.Plot[Xs[i]][Ys[i]] == 0):
        self.Plot[Xs[i]][Ys[i]] = 1

Which will have the correct values, however it is still producing this strange behavior, and the problem lies in this code here.

EDIT 2

When I use the code:

self.Plot[3][3] = 1

It still produces an array of:

[[0, 0, 0, 1, 0, 0, 0, 0, 0, 0]
 [0, 0, 0, 1, 0, 0, 0, 0, 0, 0]
 [0, 0, 0, 1, 0, 0, 0, 0, 0, 0]
 [0, 0, 0, 1, 0, 0, 0, 0, 0, 0]
 [0, 0, 0, 1, 0, 0, 0, 0, 0, 0]
 [0, 0, 0, 1, 0, 0, 0, 0, 0, 0]
 [0, 0, 0, 1, 0, 0, 0, 0, 0, 0]
 [0, 0, 0, 1, 0, 0, 0, 0, 0, 0]
 [0, 0, 0, 1, 0, 0, 0, 0, 0, 0]
 [0, 0, 0, 1, 0, 0, 0, 0, 0, 0]]
6
  • What are you doing in the line that says divisible = (int) (duration / self.Scale)? You can't cast things like this in python. Commented Mar 10, 2014 at 1:42
  • @daveydave400 I am trying get the amount of "points" from the duration. Guess that was my C# experience haha Commented Mar 10, 2014 at 1:50
  • Ah ok. If the division thing mentioned in the answers doesn't help, try separating out some of the logic into its own function (for testing) and running it with user provided information instead of relying on the actual object's state. Commented Mar 10, 2014 at 1:55
  • @daveydave400 Xs and Ys have the correct values... so the problem lies in the plotting of the points... Ill look at it a bit more Commented Mar 10, 2014 at 2:03
  • @daveydave400 Check edits... Now I don't think the problem is 100% on my end Commented Mar 10, 2014 at 2:17

2 Answers 2

1

So to produce that grid you are showing you are printing self.Plot? And your saying this grid gets initialized to 0? What exactly is self.Plot? A list of lists and that's it? When you print self.Plot before running that loop does it print what you expect (which I assume should be all zeros)?

So if Xs and Ys are the points that should be 1 you could simplify the code to using one list of plottable points:

plottable_points = []
# for loop
    plottable_points.append( (x, int((slope * (x - self.X)) + self.Y)) )

for x, y in plottable_points:
    self.Plot[x][y] = 1

I'm not sure exactly how self.Plot is being initialized or used, but if you print things before and after each step you should be able to figure out where your logic is wrong.

Edit 1: Extra little python tip:

for x, y in zip(Xs, Ys):
    self.Plot[x][y] = 1

Does the same thing as my first code example does, but with your variables.

Edit 2:

The problem is actually with how you are initializing self.Plot. When you repeat a list like that, your outer list becomes a list of pointers...all pointing to the same object (in this case a list). So when you say self.Plot[3][3] = 1, you are actually setting that column in each row. Try initializing self.Plot with something like this (there may be a better way to do this, but I'm tired):

self.Plot = []
for col in range(height * multiplyBy):
    self.Plot.append([0] * width * multiplyBy)

# or:
self.Plot = [ [0] * width * multiply for col in range(height * multiplyBy) ]
Sign up to request clarification or add additional context in comments.

4 Comments

I initialize self.Plots by: Plots = [[0] * width * multiplyBy] * height * multiplyBy. multiplyBy is just 1.0 / Scale, and the issue is with setting the values in the array.
Thanks, that solved the issue. Also that is interesting behavior... Do you think this holds true in other languages?
Do you have a specific language in mind? It is possible in other languages, but probably less likely to happen. For example in C you'd be working very closely with the pointers and dynamically allocating the arrays so you'd probably realize the problem faster. You just happened to use a python shortcut that had a negative impact for you, but it could also be the desired output for other developers.
That's true with the whole C/C++ thing... Python is just a...different... language than I'm used to haha...
1

I would say that you should do a simple import (from future import division) before doing any more modifications. To me it seems the problem is the division. In Python 2.7 it returns you an integer. Take a look at this:

>>> 4/3
1
>>> 4//3
1

But if you import the new division functionality...

>>> from __future__ import division
>>> 4/3
1.3333333333333333

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.