How to simulate an object balancing on another in pybullet? - reinforcement-learning

I am trying to simulate a ball balancing on a board with pybullet and openAI gym, but for now I am working with any shapes. I have the gym part down, but I am not sure how to approach this with pybullet. Here is an example of code I wrote up for one object, I want to make that move and balance another object on it. here is the code for the openAI env, and what I have worked on so far to render it with pybullet:
import os import gym import numpy as np import pybullet as pb import pybullet_data import math import random
class BeamEnv(gym.Env):
def __init__(self, obs_low_bounds = np.array([ 0, 0, "TBD", -45]),
obs_high_bounds = np.array([12, 12, "TBD", 45])):
self.physicsClient = pb.connect(pb.GUI) pb.setAdditionalSearchPath(pybullet_data.getDataPath()) self._seed()
"""Environment for a ball and beam system where agent has control of tilt.
Args:
obs_low_bounds (list, optional): [target location(in), ball location(in),
ball velocity(in/s), beam angle(deg)]. Defaults to [ 0, 0, "TBD", -45].
obs_high_bounds (list, optional): As above so below. Defaults to [12, 12, "TBD", 45].
"""
super(BeamEnv, self).__init__()
# Hyperparameters
self.ACC_GRAV = 386.22 # [in/s]
self.MOTOR_SPEED = 46.875 # 1.28[sec/60deg] converted to [deg/s]
self.TIME_STEP = 0.1 # [s]
# Observation Space
# _bounds = []
self.obs_low_bounds = obs_low_bounds
self.obs_high_bounds = obs_high_bounds
self._determine_max_velocity()
self.observation_space = gym.spaces.Box(low = self.obs_low_bounds,
high = self.obs_high_bounds,
dtype = np.float32)
# Action Space
# increase, decrease or keep current angle
self.action_space = gym.spaces.Descrete(3)
# Reward Range
self.reward_range = (-1, 1)
def _set_velocity_bounds(self):
"""Use Inclined Plane and Kinematics Formulas
to determine min/max velocities and set the obs_low/high_bounds
"""
# Max Distance
distance_max = self.obs_high_bounds[1]
# Max Angle
ang_max = self.obs_high_bounds[3]
# Max acceletation (Inclined Plane Formula)
a_max = self.ACC_GRAV * np.sin(np.deg2rad(ang_max))
# Max Velocity (vf^2 = v0^2 + 2ad)
vel_max = np.sqrt(2*a_max*distance_max)
# Set Bounds
self.obs_low_bounds[2] = -vel_max
self.obs_high_bounds[2] = vel_max
def _compute_observation(self): cubePos, cube0rn = pb.getBasePositionAndOrientation(self.botId) cubeEuler = pb.getEulerFromQuaternion(cubeOrn) linear, angular = pb.getBaseVelocity(self.botId) return[cubeEuler[0],angular[0],self.vt]
def _compute_reward(self): _, cubeOrn = pb.getBasePosition(self.botId) cubeEuler = pb.getEulerFromQuaternion(cube0rn) return(1 - abs(cubeEuler[0])) *
0.1 - abs(self.vt - self.vd)
def _compute_done(self): cubePos, _ = pb.getBasePositionAndOrientation(self.botId) return cubePos[2] < 0.15 or self._envStepCounter >= 1500
def reset(self, target_location = None,
ball_location = None):
pb.resetSimulation() pb.setGravity(0,0,-9.8) """default timeStep is 1/240s""" pb.setTimeStep(0.01) planeId = pb.loadURDF('plane.urdf') #loading bot cubeStarPos=[0,0,0.001] cubeStartOrientation = pb.getQuaternionFromEuler([0,0,0]) path = os.path.abspath(os.path.dirname(__file__)) self.botId = pb.loadURDF(os.path.join(path, "beam.xml"), cubeStartPos, cubeStartOrientation) self._observation = self._compute_observation() return np.array(self._observation)
"""Reset the environment so the ball is not moving, there is no angle,
Args:
target_location (float, optional): Desired location of ball. Defaults to random.
ball_location (float, optional): Current location of ball. Defaults to random.
Returns:
list: observation of (target location, ball location, ball velocity, beam angle)
"""
# Set target location
if target_location is not None:
self.target_location = target_location
else:
possible_targets = list(range(self.obs_low_bounds[0], self.obs_high_bounds[0]))
self.target_location = random.choice(possible_targets)
# Set ball location
if ball_location is not None:
self.ball_location = ball_location
else:
possible_ball_locations = list(range(self.obs_low_bounds[1], self.obs_high_bounds[1]))
self.ball_location = random.choice(possible_ball_locations)
# Set Intial Velocity and Angle to Zero
self.ball_velocity = 0 # [in/s]
self.beam_angle = 0 # [deg]
return self._next_observation()
def _next_observation(self):
"""Determines what will happen in the next time step
Returns:
list: observation of (target location, ball location, ball velocity, beam angle)
"""
# Calculate Acceleration (Inclined Plane Equation)
ball_acceleration = self.ACC_GRAV * np.sin(np.deg2rad(self.beam_angle))
# Calculate Next Position (x = x0 + v0t + 0.5at^2)
self.ball_location = self.ball_location + self.ball_velocity * self.TIME_STEP + 0.5 * ball_acceleration * self.TIME_STEP**2
# Calculate New Velocity (v = v0 + at)
self.ball_velocity = self.ball_velocity + ball_acceleration * self.TIME_STEP
# Clip Ball Location
self.ball_location = max(min(self.ball_location,
self.obs_high_bounds[1]),
self.obs_low_bounds[1])
# Clip Ball Velocity
self.ball_velocity = max(min(self.ball_velocity,
self.obs_high_bounds[2]),
self.obs_low_bounds[2])
# Return Observation
return [self.target_location, self.ball_location, self.ball_velocity, self.beam_angle]
def _take_action(self,action):
"""Determines change in angle due to action
Args:
action (int): increase, decrease or keep current angle
"""
# Change action to signs by subtracting by 1 ie (0,1,2) --> (-1,0,1)
action -= 1
# Change the angle by unit step
self.beam_angle = self.beam_angle + action * self.MOTOR_SPEED * self.TIME_STEP
# Clip
self.beam_angle = max(min(self.beam_angle,
self.obs_high_bounds[3]),
self.obs_low_bounds[3])
def step(self, action):
"""Take action, collect reward and get new observation
Args:
action (int): increase, decrease or keep current angle
Returns:
tuple: (observation, reward, done, info)
"""
# Take the action
self._take_action(action)
# Determine Success
if (round(abs((self.target_location - self.ball_location)),3) == 0) & (round(self.ball_velocity, 3) == 0) & (round(self.beam_angle, 3) == 0):
done = True
else:
done = False
# Find Reward
reward = 1 if done else -1
# Find Next Observation
obs = self._next_observation()
# Return what happened
return obs, reward, done, {}
def _seed(self, seed=None): self.np_random, seed = seeding.np_random(seed) return[seed]
here is an object in pybullet, the board I will be balancing an object on. I am not sure how to make it move by a variable force or render it based on my openAI gym script.
import numpy
import pybullet as pb
physicsClient = pb.connect(pb.GUI)
> #creates plane import pybullet_data pb.setAdditionalSearchPath(pybullet_data.getDataPath()) planeId =
> pb.loadURDF('plane.urdf')
>
>
> visualShapeId = pb.createVisualShape(
> shapeType=pb.GEOM_MESH,
> fileName='procedural_objects/126/126.obj',
> rgbaColor=None,
> meshScale=[0.1, 0.1, 0.1])
>
> collisionShapeId = pb.createCollisionShape(
> shapeType=pb.GEOM_MESH,
> fileName='procedural_objects/126/126.obj',
> meshScale=[0.1, 0.1, 0.1])
>
> #connects visual shape and collider multiBodyId = pb.createMultiBody(
> baseMass=1.0,
> baseCollisionShapeIndex=collisionShapeId,
> baseVisualShapeIndex=visualShapeId,
> basePosition=[0, 0, 1],
> baseOrientation=pb.getQuaternionFromEuler([0, 0, 0]))
>
> pb.setGravity(0, 0, -9.8) pb.setRealTimeSimulation(1)
> #use setTimeStep fn to override default time step (1/240s)
any advice how to get pybullet to generate a random shape (ignore ball) balancing on another random shape?

Related

Actor Critic model returns NaN for action probabilities

I am new to RL and walking through the Keras implementation of Actor Critic.
As a variant of it, I am trying to learn the strategy for WORDLE. However, after a few runs, my action spaces all go down to nan.
actions = [nan nan nan ... nan nan nan]
Not sure what's happening. Could someone have any insights or pointers?
Attaching my code for reference.
Thanks
import pandas as pd
import numpy as np
import random
import string
import random
import tensorflow as tf
from tensorflow import keras
from tensorflow.keras import layers
# Configuration parameters for the whole setup
gamma = 0.9 # Discount factor for past rewards
max_runs = 10000
eps = np.finfo(np.float32).eps.item() # Smallest number such that 1.0 + eps != 1.0
my_file = open("<wordle set of words data path>", "r")
content = my_file.read()
content = list(content.split('\n'))
lower_alphabet = list(string.ascii_letters)[:26]
def get_secret_word():
return random.choice(content)
def reset_available_action_space():
return [1 for i in range(len(content))]
def reset_guessed_alphabet_state():
return [0 for i in range(len(lower_alphabet))]
# array of 26 which represents which alphabet is available in word
def reset_contains_alphabet_state():
return [0 for i in range(len(lower_alphabet))]
# Array of 26*5.
# First 26 represent which alphabet was correctly guessed at the first slot
# Second 26 represent which alphabet was correctly guessed at the second slot. And so on for the next 5 slots.
def reset_correct_alphabet_pos_state():
return [0 for i in range(len(lower_alphabet)*5)]
def select_and_update_AVAILABLE_ACTION_SPACE(actions):
action_index = 0
while AVAILABLE_ACTION_SPACE[actions[action_index]] == False:
action_index += 1
AVAILABLE_ACTION_SPACE[actions[action_index]] = 0
return actions[action_index]
def env_reset():
AVAILABLE_ACTION_SPACE = reset_available_action_space()
guessed_alphabet_state = reset_guessed_alphabet_state()
contains_alphabet_state = reset_contains_alphabet_state()
correct_alphabet_pos_state = reset_correct_alphabet_pos_state()
state = guessed_alphabet_state + contains_alphabet_state + correct_alphabet_pos_state
SECRET_WORD = get_secret_word()
return state, SECRET_WORD, AVAILABLE_ACTION_SPACE
def env_step(action, state):
guessed_word = content[action]
guessed_alphabet_state = state[:26]
contains_alphabet_state = state[26:52]
correct_alphabet_pos_state = state[52:]
done = False
reward = -10
if SECRET_WORD == guessed_word:
done = True
reward = 10
secret_word = list(SECRET_WORD)
guessed_word = list(guessed_word)
for index_, char_ in enumerate(guessed_word):
alphabet_index = lower_alphabet.index(char_)
guessed_alphabet_state[alphabet_index] = 1
if char_ in secret_word:
contains_alphabet_state[alphabet_index] = 1
if secret_word[index_] == char_:
correct_alphabet_pos_state[26*index_ + alphabet_index] = 1
state = guessed_alphabet_state + contains_alphabet_state + correct_alphabet_pos_state
return state, reward, done
num_inputs = 182
num_actions = len(content)
num_hidden_1 = 256
num_hidden_2 = 128
inputs = layers.Input(shape=(num_inputs,))
common = layers.Dense(num_hidden_1, activation="relu")(inputs)
common = layers.Dense(num_hidden_2, activation="relu")(common)
action = layers.Dense(num_actions, activation="softmax")(common)
critic = layers.Dense(1)(common)
model = keras.Model(inputs=inputs, outputs=[action, critic])
optimizer = keras.optimizers.Adam(learning_rate=0.001)
huber_loss = keras.losses.Huber()
action_probs_history = []
critic_value_history = []
rewards_history = []
running_reward = 0
episode_count = 0
for runs in range(max_runs):
max_steps_per_episode = 6
state, SECRET_WORD, AVAILABLE_ACTION_SPACE = env_reset()
episode_reward = 0
with tf.GradientTape() as tape:
for timestep in range(max_steps_per_episode):
state_tensor = tf.convert_to_tensor(state)
state_tensor = tf.expand_dims(state, 0)
action_probs, critic_value = model(state_tensor)
critic_value_history.append(critic_value[0, 0])
actions = np.random.choice(num_actions, size=max_steps_per_episode+1, replace = False, p=np.squeeze(action_probs))
action = select_and_update_AVAILABLE_ACTION_SPACE(actions)
action_probs_history.append(tf.math.log(action_probs[0, action]))
state, reward, done = env_step(action, state)
rewards_history.append(reward)
episode_reward += reward
if done:
break
# Update running reward to check condition for solving
running_reward = 0.05 * episode_reward + (1 - 0.05) * running_reward
# Calculate expected value from rewards
# - At each timestep what was the total reward received after that timestep
# - Rewards in the past are discounted by multiplying them with gamma
# - These are the labels for our critic
returns = []
discounted_sum = 0
for r in rewards_history[::-1]:
discounted_sum = r + gamma * discounted_sum
returns.insert(0, discounted_sum)
# Normalize
returns = np.array(returns)
returns = (returns - np.mean(returns)) / (np.std(returns) + eps)
returns = returns.tolist()
# Calculating loss values to update our network
history = zip(action_probs_history, critic_value_history, returns)
actor_losses = []
critic_losses = []
for log_prob, value, ret in history:
# At this point in history, the critic estimated that we would get a
# total reward = `value` in the future. We took an action with log probability
# of `log_prob` and ended up recieving a total reward = `ret`.
# The actor must be updated so that it predicts an action that leads to
# high rewards (compared to critic's estimate) with high probability.
diff = ret - value
actor_losses.append(-log_prob * diff) # actor loss
# The critic must be updated so that it predicts a better estimate of
# the future rewards.
critic_losses.append(
huber_loss(tf.expand_dims(value, 0), tf.expand_dims(ret, 0))
)
# Backpropagation
loss_value = sum(actor_losses) + sum(critic_losses)
grads = tape.gradient(loss_value, model.trainable_variables)
optimizer.apply_gradients(zip(grads, model.trainable_variables))
# Clear the loss and reward history
action_probs_history.clear()
critic_value_history.clear()
rewards_history.clear()
# Log details
episode_count += 1
if episode_count % 10 == 0:
template = "running reward: {:.2f} at episode {}"
print(template.format(running_reward, episode_count))
wordle set of words data path => https://gist.github.com/cfreshman/a03ef2cba789d8cf00c08f767e0fad7b
My State Space is [guessed alphabets, alphabets contained in the secret word, alphabet in the correct position]
guessed alphabets => Array of 26 size (a-z)
alphabets contained in the secret word => Array of 26 size (a-z)
alphabet in the correct position => Array of 26 * 5 [(a-z), (a-z), (a-z), (a-z), (a-z)] (as each word is 5 letters)
The Available action spaces get updated after every action. The previously taken actions are no longer available for future actions.
I have tried both relu and tanh for activation
Observation: Critic Value keeps increasing to an extremely large values

making my multi-agent environment by deep reinforcement learning

I should make my own environment and apply dqn algorithm in a multi-agent environment.
I have 4 agents . Each state of my environment has 5 variables state=[p1, p2, p3, p4,p5], at each time step,we update the different parameters of all states. Action is one of amount: {-2,-1,0,1,2} given the best q-value.
param0,param1,param2,param3,param4=[[0 for x in range(numframe)] for y in range(number_nodes)]
`timestep p4[agent0]=random.randint(0,2)
p4[agent1]=p4[agent0]+action
p4[agent2]=p4[agent1]+action
p4[agent3]=p4[agent2]+action
(actions find by a DNN in dqn and can be one of {-2,-1,0,1,2})`
param0..5=[[0 for x in range(numframe)] for y in range(number_nodes)]
numframe: shows amount for experience-replay, number_nodes=4 showing number of agents
I have written the following code based on [dqn-keras-code][1],
1- how I could change it to work as multi-agent?
2- how I could change to write my reset? (I should reset to 0each of parameters)
I write some code but as I am beginner in dqn and multi-agent, I saw the following error: (I know it has also some problem related to multi-agent)
line 156, in <module>
state = env.reset()
TypeError: reset() missing 1 required positional argument: 'self'
Could you please help me more than this error how I can fix my reset section and step section?
Here is my code:
import random
import numpy as np
import tensorflow as tf
from collections import deque
from keras.models import Sequential
from keras.layers import Dense
from keras.optimizers import Adam
#-----------------------------------------------------------------
global param0,param1,param2,param3,param4,state,next_state,action_space,action_size,w,m, reward,episodes,time_t,state
#--------------------------------------------------------------------------
episodes=2000
number_nodes=5 #one more than number of nodes
timemax=500
action_size=5
state_size=5
action_space=[-2,-1,0,1,2]
m=16 #4*(ltime+ftime)=16
numframe=16
#-------------------------------------------------------------------------
class env:
def __init__(self):
self.action_space=[-2,-1,0,1,2] # X=[-2,2]
self.action_size = len(self.action_space)
self.state = None
return action_space, action_size
def reset(self):
#self.action_space=[0,0,0,0,0]
for ii in range (1,4): #both sides
param1[ii]=0
param2[ii]=0
param3[ii]=0
param4[ii]=0
param0[ii]=0
reward[ii]=0
state[ii]=[param0[ii],param1[ii],param2[ii],param3[ii],param4[ii]]
return state
# def reset(self):
# self.state = self.np_random.uniform(low=-0.05, high=0.05, size=(4,))
# self.steps_beyond_done = None
# return np.array(self.state)
def step(self,action):
state = self.state
param1, param2, param3, param4, param0 = state
param0[0]=random.randint(0,2) #produce a random param0
#relationship between parameteres for refreshing
param0[1]=param0[0]+action
param0[2]=param0[1]+action
param0[3]=param0[2]+action
param0[4]=param0[3]+action
for i in range (1,4):
param1[time_t][i]=param4[time_t][i+1]-param0[i+1]
#action[i]=agent.init(state_size, action_size)
#relationship between parameteres for refreshing
param2[time_t][i]=param0[i]+action
param3[time_t][i]=param2[time_t][i]
param4[time_t][i]=param3[time_t][i]
#param1,param3,param4,param0
next_state[i]=[param1[time_t][i],param2[time_t][i],param3[time_t][i],param4[time_t][i],param0[i]]
cp= [2, 0, 0, 0]
ch= [2, 2, 2, 2]
# reward function
if param1[i]>=0:
reward[i]+=ch[i]*param1[time_t][i]
else:
reward[i]+=cp[i]*param1[time_t][i]
return next_state, reward
#-------------------------------------------------
class DQNAgent:
def __init__(self, state_size, action_size):
self.state_size = state_size
self.action_size = action_size
self.memory = deque(maxlen=2000)
self.gamma = 0.95 # discount rate
self.epsilon = 1.0 # exploration rate
self.epsilon_min = 0.01
self.epsilon_decay = 0.995
self.learning_rate = 0.001
self.model = self._build_model()
def _build_model(self):
# Neural Net for Deep-Q learning Model
model = Sequential()
model.add(Dense(24, input_dim=self.state_size, activation='relu'))
model.add(Dense(24, activation='relu'))
model.add(Dense(self.action_size, activation='linear'))
model.compile(loss='mse',
optimizer=Adam(lr=self.learning_rate))
return model
def remember(self, state, action, reward, next_state, done):
self.memory.append((state, action, reward, next_state, done))
def act(self, state):
if np.random.rand() <= self.epsilon:
return random.randrange(self.action_size)
act_values = self.model.predict(state)
return np.argmax(act_values[0]) # returns action
def replay(self, batch_size):
minibatch = random.sample(self.memory, batch_size)
for state, action, reward, next_state, done in minibatch:
target = reward
if not done:
target = (reward + self.gamma *
np.amax(self.model.predict(next_state)[0]))
target_f = self.model.predict(state)
target_f[0][action] = target
self.model.fit(state, target_f, epochs=1, verbose=0)
if self.epsilon > self.epsilon_min:
self.epsilon *= self.epsilon_decay
def load(self, name):
self.model.load_weights(name)
def save(self, name):
self.model.save_weights(name)
if __name__ == "__main__":
#env = gym.make('CartPole-v1')
#state_size = env.observation_space.shape[0]
#action_size = env.action_space.n
state_size=4
action_size=5
agent = DQNAgent(state_size, action_size)
# agent.load("./save/cartpole-dqn.h5")
done = False
batch_size = 32
for e in range(episodes):
state = env.reset()
state = np.reshape(state, [1, state_size])
for time in range(500):
# env.render()
action = agent.act(state)
next_state, reward, done, _ = env.step(action)
reward = reward if not done else -10
next_state = np.reshape(next_state, [1, state_size])
agent.remember(state, action, reward, next_state, done)
state = next_state
if done:
print("episode: {}/{}, score: {}, e: {:.2}"
.format(e, EPISparam2DES, time, agent.epsilon))
break
if len(agent.memory) > batch_size:
agent.replay(batch_size)
# if e % 10 == 0:
# agent.save("./save/cartpole-dqn.h5")
agent = DQNAgent(state_size, action_size)
# agent.load("./save/cartpole-dqn.h5")
[1]: https://github.com/keon/deep-q-learning/blob/master/dqn.py
The DQN algorithm you linked to is for a single agent game. You have to change it quite a bit to work with multiple agents. There are multiple papers written on the subject. If you want to truly understand what your code is doing, I suggest finding a paper that tries to solve an environment similar to yours and then applying the concepts within that paper to your code.

Move an object towards a target in PyBullet

I'm pretty new to PyBullet and physics engines in general. My first step is trying to get one object to move towards another.
import pybullet as p
import time
import pybullet_data
DURATION = 10000
physicsClient = p.connect(p.GUI)#or p.DIRECT for non-graphical version
p.setAdditionalSearchPath(pybullet_data.getDataPath()) #optionally
print("data path: %s " % pybullet_data.getDataPath())
p.setGravity(0,0,-10)
planeId = p.loadURDF("plane.urdf")
cubeStartPos = [0,0,1]
cubeStartOrientation = p.getQuaternionFromEuler([0,0,0])
boxId = p.loadURDF("r2d2.urdf",cubeStartPos, cubeStartOrientation)
gemId = p.loadURDF("duck_vhacd.urdf", [2,2,1], p.getQuaternionFromEuler([0,0,0]) )
for i in range (DURATION):
p.stepSimulation()
time.sleep(1./240.)
gemPos, gemOrn = p.getBasePositionAndOrientation(gemId)
cubePos, cubeOrn = p.getBasePositionAndOrientation(boxId)
oid, lk, frac, pos, norm = p.rayTest(cubePos, gemPos)[0]
#rt = p.rayTest(cubePos, gemPos)
#print("rayTest: %s" % rt[0][1])
print("rayTest: Norm: ")
print(norm)
p.applyExternalForce(objectUniqueId=boxId, linkIndex=-1, forceObj=pos
,posObj=gemPos, flags=p.WORLD_FRAME)
print(cubePos,cubeOrn)
p.disconnect()
But this just gets R2 to wiggle a bit. How do I do this?
First of all, if you are moving a robot, you should do something a little more complicated, by providing some commands to the joints of the robot. Here is an example
Now assuming that you are moving something less complicated by applying an external force, the simplest thing you can do is multiply a factor alpha with the difference between the two positions; this would be your force.
For your example this would be:
import numpy as np
import pybullet as p
import time
import pybullet_data
DURATION = 10000
ALPHA = 300
physicsClient = p.connect(p.GUI) # or p.DIRECT for non-graphical version
p.setAdditionalSearchPath(pybullet_data.getDataPath()) # optionally
print("data path: %s " % pybullet_data.getDataPath())
p.setGravity(0, 0, -10)
planeId = p.loadURDF("plane.urdf")
cubeStartPos = [0, 0, 1]
cubeStartOrientation = p.getQuaternionFromEuler([0, 0, 0])
boxId = p.loadURDF("r2d2.urdf", cubeStartPos, cubeStartOrientation)
gemId = p.loadURDF("duck_vhacd.urdf", [
2, 2, 1], p.getQuaternionFromEuler([0, 0, 0]))
for i in range(DURATION):
p.stepSimulation()
time.sleep(1./240.)
gemPos, gemOrn = p.getBasePositionAndOrientation(gemId)
boxPos, boxOrn = p.getBasePositionAndOrientation(boxId)
force = ALPHA * (np.array(gemPos) - np.array(boxPos))
p.applyExternalForce(objectUniqueId=boxId, linkIndex=-1,
forceObj=force, posObj=boxPos, flags=p.WORLD_FRAME)
print('Applied force magnitude = {}'.format(force))
print('Applied force vector = {}'.format(np.linalg.norm(force)))
p.disconnect()

Constant Runtime Error -Python - Tkinter

My problem here is that I get a Runtime Error every time I run my code. Also, I am unable to bind my "Repeat" button with the "RUN" function. I do not understand why the button will not work and I am also unsure why the "self.canvas.delete()" does not work and why the new frame does not open when the puzzle has been solved (when all of the disks have been moved to a new pole) and why it opens straight away.
from Tkinter import *
import sys
import time
def Hanoi(n, src, dst, tmp, move):
if n == 0:
return n
else:
Hanoi(n-1, src, tmp, dst, move)
move(src, dst)
Hanoi(n-1, tmp, dst, src, move)
class hanoi():
master = Tk()
width = 2000
height = 400
time = 0.1
big_sep = 30
small_sep = 5
def __init__(self):
self.User_Input = input("Please enter the amount of disks")
self.canvas = Canvas(hanoi.master, height = hanoi.height, width = hanoi.width)
self.canvas.pack()
self.poles = [[], [], []]
self.Add_Objects()
def Add_Objects(self):
floor_size = 1000-2*hanoi.small_sep
self.disk_height = (400 - 4*hanoi.big_sep) / self.User_Input
self.disk_width = (floor_size - 4*hanoi.small_sep) / 3
disk_h = self.disk_height
disk_w = self.disk_width
global disk_h
global disk_w
width = hanoi.width
height = hanoi.height
small_sep = hanoi.small_sep
big_sep = hanoi.big_sep
#create poles
bar_pos = [ 4*small_sep + disk_w/2 + (disk_w+small_sep)*i for i in range(0,3) ]
for x in bar_pos:
print x
self.canvas.create_rectangle(x-small_sep, big_sep, x+small_sep, 400-big_sep-1, fill='black')
#create bases
for x in bar_pos:
print i
self.canvas.create_rectangle(x-(13*small_sep), 370, x+(13*small_sep), 410, fill = "brown")
#create disks
for i in range(self.User_Input):
print 2*small_sep + 4*small_sep*i, height-big_sep-1-disk_h*i,2*small_sep + disk_w - 4*small_sep*i, height-big_sep-1-disk_h*(i+1)
disk = self.canvas.create_rectangle(2*small_sep + 4*small_sep*i, 400-big_sep-1-disk_h*i,2*small_sep + disk_w - 4*small_sep*i, 400-big_sep-1-disk_h*(i+1),fill='blue')
self.poles[0].append(disk)
self.canvas.update()
def Move_Object(self, origin, dest):
print len(self.poles[dest]), self.User_Input-1
current_disk = self.poles[origin].pop()
self.poles[dest].append(current_disk)
x_distance = (dest - origin) * (disk_w)
y_distance = ((len(self.poles[origin]) - len(self.poles[dest])+1) * disk_h)
self.canvas.move(current_disk, x_distance, y_distance)
self.canvas.update()
time.sleep(hanoi.time)
if len(self.poles[dest]) == self.User_Input:
self.canvas.delete()
new_frame = Frame(hanoi.master, width = 300, height = 300)
new_frame.pack()
print "Yayar"
newb = Button(new_frame, text = "Replay", )
newb.place(relx = 0.5, rely = 0.5)
newb.bind("<ButtonPress-1>", self.RUN)
def RUN(self):
Hanoi(self.User_Input, 0, 2, 1, self.Move_Object)
if __name__ == "__main__":
print "hello"
hanoi().RUN()

Pygame, simple physics engine, how to hold points between planes?

I'm trying to write this tutorial in Pygame(Python) and having problems about holding points between planes.
My code is: fiz2.py
Vector class: vector.py
If you move mouse on the Pygame screen, the planes will rotate. And when the planes are rotating, points are passing through planes and going outside.
I tried to fix points' positions on every iteration but they still passed the planes. I have no idea about where should I fix their positions.
NOTE: I know my code is a little bit messy, this is my first 2d program and I had really hard times getting used to Pygame's coordinate plane and vectors. I will re-write when I solve this.
NOTE2: Yes, I wrote the comment about how to hold points between planes on the tutorial, I understand the way he fixes positions but have no idea about how(and where, in code) to implement it.
Thanks.
I can't tell looking at the code. My guess is a variable-timestep, causing instability. But I can't verify if the math is right. Although, I have useful information :
Vectors
You can simplify code, by using vectors as a class vs list/tuple. (velocity, acceleration, location) are treated as one object, verses separate .x and .y values.
# example:
pos[0] += vel[0]
pos[1] += vel[1]
# vs
pos += vel
There is a python-only implementation: euclid.py You can use to compare with your vector.py.
Or use NumPy [ used for 3d graphics, in openGL. ] Is a popular, mature lib.
physics
(It looks like you want to learn by writing your own physics), but check out PyMunk
colors
You can use: pygame.Color
import pygame
from pygame import Color
color = Color('white')
color2 = Color('lightgray')
color3 = Color(0,128,128)
collisions
Look at pygame.sprite.*collide , and pygame.Rect.*collide
pygame Game loop with numpy vector's
Boilerplate I wrote
""" Pygame boilerplate. <ninmonkey>2011/04
pygame main Game() loop, and numpy for vector math.
note:
this might not be the most effecient way to use numpy as vectors, but it's an intro.
And this does not force fixed-timesteps. If you want a stable simulation, you need to use a fixed timestep.
see: http://gafferongames.com/game-physics/fix-your-timestep/
Keys:
ESC : exit
Space : game_init()
"""
import pygame
from pygame.locals import *
from pygame import Color, Rect
import numpy as np
def get_screen_size():
"""return screen (width, height) tuple"""
screen = pygame.display.get_surface()
return screen.get_size()
class Actor():
"""basic actor, moves randomly.
members:
loc = position vector
velocity = velocity vector
width, height
"""
def __init__(self, loc=None, velocity=None):
"""optional initial loc and velocity vectors"""
self.width = 50
self.height = 50
# if loc or velocity are not set: use random
if loc is None: self.rand_loc()
else: self.loc = loc
if velocity is None: self.rand_velocity()
else: self.velocity = velocity
def update(self):
"""update movement"""
self.loc += self.velocity
def rand_velocity(self):
"""set a random vector , based on random direction. Using unit circle:
x = cos(deg) * speed
"""
rad = np.radians( np.random.randint(0,360) )
speed = np.random.randint(1,15)
x = np.cos(rad)
y = np.sin(rad)
velocity = np.array( [x,y])
velocity *= speed
self.velocity = velocity
def rand_loc(self):
"""random location onscreen"""
width,height = get_screen_size()
x = np.random.randint(0,width)
y = np.random.randint(0,height)
self.loc = np.array([x,y])
def is_onscreen(self):
"""test is screen.colliderect(actor) true?"""
x,y = self.loc
w,h = get_screen_size()
screen = Rect(0, 0, w, h)
actor = Rect(x, y, self.width, self.height)
if screen.colliderect(actor): return True
else: return False
class GameMain():
"""game Main entry point. handles intialization of game and graphics."""
done = False
debug = False
color_gray = Color('lightgray')
def __init__(self, width=800, height=600, color_bg=None):
"""Initialize PyGame"""
pygame.init()
self.width, self.height = width, height
self.screen = pygame.display.set_mode(( self.width, self.height ))
pygame.display.set_caption( "boilerplate : pygame" )
self.clock = pygame.time.Clock()
self.limit_fps = True
self.limit_fps_max = 60
if color_bg is None: color_bg = Color(50,50,50)
self.color_bg = color_bg
self.game_init()
def game_init(self):
"""new game/round"""
self.actors = [Actor() for x in range(10)]
def loop(self):
"""Game() main loop"""
while not self.done:
self.handle_events()
self.update()
self.draw()
if self.limit_fps: self.clock.tick( self.limit_fps_max )
else: self.clock.tick()
def update(self):
"""update actors, handle physics"""
for a in self.actors:
a.update()
if not a.is_onscreen():
a.rand_loc()
def handle_events(self):
"""handle regular events. """
events = pygame.event.get()
# kmods = pygame.key.get_mods() # key modifiers
for event in events:
if event.type == pygame.QUIT: sys.exit()
elif event.type == KEYDOWN:
if (event.key == K_ESCAPE): self.done = True
elif (event.key == K_SPACE): self.game_init()
def draw(self):
"""render screen"""
# clear screen
self.screen.fill( self.color_bg )
# Actor: draw
for a in self.actors:
x,y = a.loc
w,h = a.width, a.height
r = Rect(x, y, w, h)
self.screen.fill(self.color_gray, r)
# will call update on whole screen Or flip buffer.
pygame.display.flip()
if __name__ == '__main__':
g = GameMain()
g.loop()