Module TeachMyAgent.environments.envs.Box2D_dynamics.climbing_dynamics
Expand source code
import Box2D
from Box2D.b2 import (edgeShape, circleShape, fixtureDef, polygonShape, revoluteJointDef, contactListener)
from TeachMyAgent.environments.envs.utils.custom_user_data import CustomUserDataObjectTypes
class ClimbingDynamics(object):
def before_step_climbing_dynamics(self, actions, body, world):
'''
Check if sensors are in 'grasping mode' (i.e. their associated action is greater than 0).
Otherwise, check if a joint is existing and destroy it.
'''
for i in range(len(body.sensors)):
action_to_check = actions[len(actions) - i - 1]
sensor_to_check = body.sensors[len(body.sensors) - i - 1]
if action_to_check > 0: # Check whether the sensor should grasp or release
sensor_to_check.userData.ready_to_attach = True
else:
sensor_to_check.userData.ready_to_attach = False
if sensor_to_check.userData.has_joint: # If release and it had a joint => destroy it
sensor_to_check.userData.has_joint = False
joint_to_destroy = next((_joint.joint for _joint in sensor_to_check.joints
if isinstance(_joint.joint, Box2D.b2RevoluteJoint)), None)
if joint_to_destroy is not None:
world.DestroyJoint(joint_to_destroy)
def after_step_climbing_dynamics(self, contact_detector, world):
'''
Add climbing joints if needed (i.e. objects are still overlapping after Box2D's solver execution)
'''
for sensor in contact_detector.contact_dictionaries:
if len(contact_detector.contact_dictionaries[sensor]) > 0 and \
sensor.userData.ready_to_attach and not sensor.userData.has_joint:
other_body = contact_detector.contact_dictionaries[sensor][0]
# Check if still overlapping after solver
# Super coarse yet fast way, mainly useful for creepers
other_body_shape = other_body.fixtures[0].shape
x_values = [v[0] for v in other_body_shape.vertices]
y_values = [v[1] for v in other_body_shape.vertices]
radius = sensor.fixtures[0].shape.radius + 0.01
if sensor.worldCenter[0] + radius > min(x_values) and sensor.worldCenter[0] - radius < max(x_values) and \
sensor.worldCenter[1] + radius > min(y_values) and sensor.worldCenter[1] - radius < max(y_values):
rjd = revoluteJointDef(
bodyA=sensor,
bodyB=other_body,
anchor=sensor.worldCenter # contact.worldManifold.points[0],
)
joint = world.CreateJoint(rjd)
joint.bodyA.userData.joint = joint
sensor.userData.has_joint = True
else:
contact_detector.contact_dictionaries[sensor].remove(other_body)
if len(contact_detector.contact_dictionaries[sensor]) == 0:
sensor.userData.has_contact = False
class ClimbingContactDetector(contactListener):
'''
Store contacts between sensors and graspable surfaces in a dictionary associated to the sensor.
'''
def __init__(self):
super(ClimbingContactDetector, self).__init__()
self.contact_dictionaries = {}
def BeginContact(self, contact):
bodies = [contact.fixtureA.body, contact.fixtureB.body]
for idx, body in enumerate(bodies):
if body.userData.object_type == CustomUserDataObjectTypes.BODY_SENSOR and body.userData.check_contact:
other_body = bodies[(idx + 1) % 2]
if other_body.userData.object_type == CustomUserDataObjectTypes.GRIP_TERRAIN or \
other_body.userData.object_type == CustomUserDataObjectTypes.SENSOR_GRIP_TERRAIN:
body.userData.has_contact = True
if body in self.contact_dictionaries:
self.contact_dictionaries[body].append(other_body)
else:
self.contact_dictionaries[body] = [other_body]
else:
return
def EndContact(self, contact):
bodies = [contact.fixtureA.body, contact.fixtureB.body]
for idx, body in enumerate(bodies):
other_body = bodies[(idx + 1) % 2]
if body.userData.object_type == CustomUserDataObjectTypes.BODY_SENSOR and \
body.userData.check_contact and body.userData.has_contact:
if other_body in self.contact_dictionaries[body]:
self.contact_dictionaries[body].remove(other_body)
if len(self.contact_dictionaries[body]) == 0:
body.userData.has_contact = False
def Reset(self):
self.contact_dictionaries = {}
Classes
class ClimbingContactDetector
-
Store contacts between sensors and graspable surfaces in a dictionary associated to the sensor.
Expand source code
class ClimbingContactDetector(contactListener): ''' Store contacts between sensors and graspable surfaces in a dictionary associated to the sensor. ''' def __init__(self): super(ClimbingContactDetector, self).__init__() self.contact_dictionaries = {} def BeginContact(self, contact): bodies = [contact.fixtureA.body, contact.fixtureB.body] for idx, body in enumerate(bodies): if body.userData.object_type == CustomUserDataObjectTypes.BODY_SENSOR and body.userData.check_contact: other_body = bodies[(idx + 1) % 2] if other_body.userData.object_type == CustomUserDataObjectTypes.GRIP_TERRAIN or \ other_body.userData.object_type == CustomUserDataObjectTypes.SENSOR_GRIP_TERRAIN: body.userData.has_contact = True if body in self.contact_dictionaries: self.contact_dictionaries[body].append(other_body) else: self.contact_dictionaries[body] = [other_body] else: return def EndContact(self, contact): bodies = [contact.fixtureA.body, contact.fixtureB.body] for idx, body in enumerate(bodies): other_body = bodies[(idx + 1) % 2] if body.userData.object_type == CustomUserDataObjectTypes.BODY_SENSOR and \ body.userData.check_contact and body.userData.has_contact: if other_body in self.contact_dictionaries[body]: self.contact_dictionaries[body].remove(other_body) if len(self.contact_dictionaries[body]) == 0: body.userData.has_contact = False def Reset(self): self.contact_dictionaries = {}
Ancestors
- Box2D.Box2D.b2ContactListener
Methods
def BeginContact(self, contact)
-
b2ContactListener_BeginContact(b2ContactListener self, b2Contact contact)
Called when two fixtures begin to touch.
Expand source code
def BeginContact(self, contact): bodies = [contact.fixtureA.body, contact.fixtureB.body] for idx, body in enumerate(bodies): if body.userData.object_type == CustomUserDataObjectTypes.BODY_SENSOR and body.userData.check_contact: other_body = bodies[(idx + 1) % 2] if other_body.userData.object_type == CustomUserDataObjectTypes.GRIP_TERRAIN or \ other_body.userData.object_type == CustomUserDataObjectTypes.SENSOR_GRIP_TERRAIN: body.userData.has_contact = True if body in self.contact_dictionaries: self.contact_dictionaries[body].append(other_body) else: self.contact_dictionaries[body] = [other_body] else: return
def EndContact(self, contact)
-
b2ContactListener_EndContact(b2ContactListener self, b2Contact contact)
Called when two fixtures cease to touch.
Expand source code
def EndContact(self, contact): bodies = [contact.fixtureA.body, contact.fixtureB.body] for idx, body in enumerate(bodies): other_body = bodies[(idx + 1) % 2] if body.userData.object_type == CustomUserDataObjectTypes.BODY_SENSOR and \ body.userData.check_contact and body.userData.has_contact: if other_body in self.contact_dictionaries[body]: self.contact_dictionaries[body].remove(other_body) if len(self.contact_dictionaries[body]) == 0: body.userData.has_contact = False
def Reset(self)
-
Expand source code
def Reset(self): self.contact_dictionaries = {}
class ClimbingDynamics
-
Expand source code
class ClimbingDynamics(object): def before_step_climbing_dynamics(self, actions, body, world): ''' Check if sensors are in 'grasping mode' (i.e. their associated action is greater than 0). Otherwise, check if a joint is existing and destroy it. ''' for i in range(len(body.sensors)): action_to_check = actions[len(actions) - i - 1] sensor_to_check = body.sensors[len(body.sensors) - i - 1] if action_to_check > 0: # Check whether the sensor should grasp or release sensor_to_check.userData.ready_to_attach = True else: sensor_to_check.userData.ready_to_attach = False if sensor_to_check.userData.has_joint: # If release and it had a joint => destroy it sensor_to_check.userData.has_joint = False joint_to_destroy = next((_joint.joint for _joint in sensor_to_check.joints if isinstance(_joint.joint, Box2D.b2RevoluteJoint)), None) if joint_to_destroy is not None: world.DestroyJoint(joint_to_destroy) def after_step_climbing_dynamics(self, contact_detector, world): ''' Add climbing joints if needed (i.e. objects are still overlapping after Box2D's solver execution) ''' for sensor in contact_detector.contact_dictionaries: if len(contact_detector.contact_dictionaries[sensor]) > 0 and \ sensor.userData.ready_to_attach and not sensor.userData.has_joint: other_body = contact_detector.contact_dictionaries[sensor][0] # Check if still overlapping after solver # Super coarse yet fast way, mainly useful for creepers other_body_shape = other_body.fixtures[0].shape x_values = [v[0] for v in other_body_shape.vertices] y_values = [v[1] for v in other_body_shape.vertices] radius = sensor.fixtures[0].shape.radius + 0.01 if sensor.worldCenter[0] + radius > min(x_values) and sensor.worldCenter[0] - radius < max(x_values) and \ sensor.worldCenter[1] + radius > min(y_values) and sensor.worldCenter[1] - radius < max(y_values): rjd = revoluteJointDef( bodyA=sensor, bodyB=other_body, anchor=sensor.worldCenter # contact.worldManifold.points[0], ) joint = world.CreateJoint(rjd) joint.bodyA.userData.joint = joint sensor.userData.has_joint = True else: contact_detector.contact_dictionaries[sensor].remove(other_body) if len(contact_detector.contact_dictionaries[sensor]) == 0: sensor.userData.has_contact = False
Methods
def after_step_climbing_dynamics(self, contact_detector, world)
-
Add climbing joints if needed (i.e. objects are still overlapping after Box2D's solver execution)
Expand source code
def after_step_climbing_dynamics(self, contact_detector, world): ''' Add climbing joints if needed (i.e. objects are still overlapping after Box2D's solver execution) ''' for sensor in contact_detector.contact_dictionaries: if len(contact_detector.contact_dictionaries[sensor]) > 0 and \ sensor.userData.ready_to_attach and not sensor.userData.has_joint: other_body = contact_detector.contact_dictionaries[sensor][0] # Check if still overlapping after solver # Super coarse yet fast way, mainly useful for creepers other_body_shape = other_body.fixtures[0].shape x_values = [v[0] for v in other_body_shape.vertices] y_values = [v[1] for v in other_body_shape.vertices] radius = sensor.fixtures[0].shape.radius + 0.01 if sensor.worldCenter[0] + radius > min(x_values) and sensor.worldCenter[0] - radius < max(x_values) and \ sensor.worldCenter[1] + radius > min(y_values) and sensor.worldCenter[1] - radius < max(y_values): rjd = revoluteJointDef( bodyA=sensor, bodyB=other_body, anchor=sensor.worldCenter # contact.worldManifold.points[0], ) joint = world.CreateJoint(rjd) joint.bodyA.userData.joint = joint sensor.userData.has_joint = True else: contact_detector.contact_dictionaries[sensor].remove(other_body) if len(contact_detector.contact_dictionaries[sensor]) == 0: sensor.userData.has_contact = False
def before_step_climbing_dynamics(self, actions, body, world)
-
Check if sensors are in 'grasping mode' (i.e. their associated action is greater than 0). Otherwise, check if a joint is existing and destroy it.
Expand source code
def before_step_climbing_dynamics(self, actions, body, world): ''' Check if sensors are in 'grasping mode' (i.e. their associated action is greater than 0). Otherwise, check if a joint is existing and destroy it. ''' for i in range(len(body.sensors)): action_to_check = actions[len(actions) - i - 1] sensor_to_check = body.sensors[len(body.sensors) - i - 1] if action_to_check > 0: # Check whether the sensor should grasp or release sensor_to_check.userData.ready_to_attach = True else: sensor_to_check.userData.ready_to_attach = False if sensor_to_check.userData.has_joint: # If release and it had a joint => destroy it sensor_to_check.userData.has_joint = False joint_to_destroy = next((_joint.joint for _joint in sensor_to_check.joints if isinstance(_joint.joint, Box2D.b2RevoluteJoint)), None) if joint_to_destroy is not None: world.DestroyJoint(joint_to_destroy)