Module TeachMyAgent.environments.envs.bodies.swimmers.FishBody
Expand source code
import numpy as np
from Box2D.b2 import edgeShape, circleShape, fixtureDef, polygonShape, revoluteJointDef, contactListener
from TeachMyAgent.environments.envs.bodies.swimmers.SwimmerAbstractBody import SwimmerAbstractBody
from TeachMyAgent.environments.envs.utils.custom_user_data import CustomBodyUserData, CustomMotorUserData
# Head
HULL_POLYGONS = [
(-20, +12), (+6, +12),
(+15, +4), (+15, -4),
(+6, -12), (-20, -12)
]
BODY_P1 = [
(-8, +9), (+8, +12),
(+8, -12), (-8, -9)
]
BODY_P2 = [
(-8, +4), (+8, +9),
(+8, -9), (-8, -4)
]
# Tail
BODY_P3 = [
(-4, +2), (+4, +4),
(+4, -4), (-4, -2)
]
FIN = [
(-1, -10), (-1, +10),
(+1, +10), (+1, -10)
]
HULL_BOTTOM_WIDTH = 35
SPEED_HIP = 4
SPEED_KNEE = 6
class FishBody(SwimmerAbstractBody):
'''
Swimming 'fish' embodiment.
'''
def __init__(self, scale, density, motors_torque=80, nb_steps_outside_water=600):
'''
Creates a fish with three body parts, a fin and a tale.
Head contact is allowed for the fish.
Args:
scale: Scale value used in the environment (to adapt the embodiment to its environment)
motors_torque: Maximum torque the embodiment can use on its motors
density: Water density (in order to make the agent in a zero-gravity-like setup)
nb_steps_outside_water: How many consecutive steps the embodiment can survive outside water
'''
super(FishBody, self).__init__(scale, motors_torque, density, nb_steps_outside_water)
self.TORQUE_PENALTY = 0.00035
self.AGENT_WIDTH = HULL_BOTTOM_WIDTH / self.SCALE
self.AGENT_HEIGHT = 18 /self.SCALE
self.AGENT_CENTER_HEIGHT = 9 / self.SCALE
self.remove_reward_on_head_angle = True
self.fins = []
self.tail = None
def draw(self, world, init_x, init_y, force_to_center):
init_y = init_y + 1
#### HULL ####
HULL_FD = fixtureDef(
shape=polygonShape(vertices=[(x / self.SCALE, y / self.SCALE) for x, y in HULL_POLYGONS]),
density=self.DENSITY,
friction=0.1,
categoryBits=0x20,
maskBits=0x000F) # 0.99 bouncy
hull = world.CreateDynamicBody(
position=(init_x, init_y),
fixtures=HULL_FD
)
hull.color1 = (0.5, 0.4, 0.9)
hull.color2 = (0.3, 0.3, 0.5)
# hull.ApplyForceToCenter((force_to_center, 0), True)
hull.userData = CustomBodyUserData(True, is_contact_critical=False, name="head")
self.body_parts.append(hull)
self.reference_head_object = hull
#### P1 ####
body_p1_x = init_x - 35 / 2 / self.SCALE - 16 / 2 / self.SCALE
BODY_P1_FD = fixtureDef(
shape=polygonShape(vertices=[(x / self.SCALE, y / self.SCALE) for x, y in BODY_P1]),
density=self.DENSITY,
restitution=0.0,
categoryBits=0x20,
maskBits=0x000F)
body_p1 = world.CreateDynamicBody(
position=(body_p1_x, init_y),
fixtures=BODY_P1_FD
)
body_p1.color1 = (0.5, 0.4, 0.9)
body_p1.color2 = (0.3, 0.3, 0.5)
rjd = revoluteJointDef(
bodyA=hull,
bodyB=body_p1,
anchor=(init_x - 35 / 2 / self.SCALE, init_y),
enableMotor=True,
enableLimit=True,
maxMotorTorque=self.MOTORS_TORQUE,
motorSpeed=1,
lowerAngle=-0.1 * np.pi,
upperAngle=0.2 * np.pi,
)
body_p1.userData = CustomBodyUserData(True, name="body")
self.body_parts.append(body_p1)
joint_motor = world.CreateJoint(rjd)
joint_motor.userData = CustomMotorUserData(SPEED_KNEE, True, contact_body=body_p1)
self.motors.append(joint_motor)
#### P2 ####
body_p2_x = body_p1_x - 16 / 2 / self.SCALE - 16 / 2 / self.SCALE
BODY_P2_FD = fixtureDef(
shape=polygonShape(vertices=[(x / self.SCALE, y / self.SCALE) for x, y in BODY_P2]),
density=self.DENSITY,
restitution=0.0,
categoryBits=0x20,
maskBits=0x000F)
body_p2 = world.CreateDynamicBody(
position=(body_p2_x, init_y),
fixtures=BODY_P2_FD
)
body_p2.color1 = (0.5, 0.4, 0.9)
body_p2.color2 = (0.3, 0.3, 0.5)
rjd = revoluteJointDef(
bodyA=body_p1,
bodyB=body_p2,
anchor=(body_p1_x - 16 / 2 / self.SCALE, init_y),
enableMotor=True,
enableLimit=True,
maxMotorTorque=self.MOTORS_TORQUE,
motorSpeed=1,
lowerAngle=-0.15 * np.pi,
upperAngle=0.15 * np.pi,
)
body_p2.userData = CustomBodyUserData(True, name="body")
self.body_parts.append(body_p2)
joint_motor = world.CreateJoint(rjd)
joint_motor.userData = CustomMotorUserData(SPEED_KNEE, True, contact_body=body_p2)
self.motors.append(joint_motor)
#### P3 ####
body_p3_x = body_p2_x - 16 / 2 / self.SCALE - 8 / 2 / self.SCALE
BODY_P3_FD = fixtureDef(
shape=polygonShape(vertices=[(x / self.SCALE, y / self.SCALE) for x, y in BODY_P3]),
density=self.DENSITY,
restitution=0.0,
categoryBits=0x20,
maskBits=0x000F)
body_p3 = world.CreateDynamicBody(
position=(body_p3_x, init_y),
fixtures=BODY_P3_FD
)
body_p3.color1 = (0.5, 0.4, 0.9)
body_p3.color2 = (0.3, 0.3, 0.5)
rjd = revoluteJointDef(
bodyA=body_p2,
bodyB=body_p3,
anchor=(body_p2_x - 16 / 2 / self.SCALE, init_y),
enableMotor=True,
enableLimit=True,
maxMotorTorque=self.MOTORS_TORQUE,
motorSpeed=1,
lowerAngle=-0.3 * np.pi,
upperAngle=0.3 * np.pi,
)
body_p3.userData = CustomBodyUserData(True, name="body")
self.body_parts.append(body_p3)
self.tail = body_p3
joint_motor = world.CreateJoint(rjd)
joint_motor.userData = CustomMotorUserData(SPEED_KNEE, True, contact_body=body_p3)
self.motors.append(joint_motor)
#### FIN ####
FIN_FD = fixtureDef(
shape=polygonShape(vertices=[(x / self.SCALE, y / self.SCALE) for x, y in FIN]),
density=self.DENSITY,
restitution=0.0,
categoryBits=0x20,
maskBits=0x000F)
fin_positions = [
# [init_x + 35 / 2 / self.SCALE / 2, init_y],
# [init_x - 35 / 2 / self.SCALE / 2, init_y],
[init_x, init_y - 22 / 2 / self.SCALE + 0.2],
# [init_x - 35 / 2 / self.SCALE / 2, init_y - 22 / 2 / self.SCALE + 0.1],
]
fin_angle = -0.2 * np.pi
middle_fin_x_distance = np.sin(fin_angle) * 20 / 2 / self.SCALE
middle_fin_y_distance = np.cos(fin_angle) * 20 / 2 / self.SCALE
for fin_pos in fin_positions:
current_fin_x = fin_pos[0] + middle_fin_x_distance
current_fin_y = fin_pos[1] - middle_fin_y_distance
fin = world.CreateDynamicBody(
position=(current_fin_x, current_fin_y),
fixtures=FIN_FD,
angle=fin_angle
)
fin.color1 = (0.5, 0.4, 0.9)
fin.color2 = (0.3, 0.3, 0.5)
rjd = revoluteJointDef(
bodyA=hull,
bodyB=fin,
anchor=(fin_pos[0], fin_pos[1]),
enableMotor=True,
enableLimit=True,
maxMotorTorque=self.MOTORS_TORQUE,
motorSpeed=1,
lowerAngle=-0.3 * np.pi,
upperAngle=0.2 * np.pi,
)
fin.userData = CustomBodyUserData(True, name="fin")
self.body_parts.append(fin)
self.fins.append(fin)
joint_motor = world.CreateJoint(rjd)
joint_motor.userData = CustomMotorUserData(SPEED_KNEE, True, contact_body=fin)
self.motors.append(joint_motor)
Classes
class FishBody (scale, density, motors_torque=80, nb_steps_outside_water=600)
-
Swimming 'fish' embodiment.
Creates a fish with three body parts, a fin and a tale.
Head contact is allowed for the fish.
Args
scale
- Scale value used in the environment (to adapt the embodiment to its environment)
motors_torque
- Maximum torque the embodiment can use on its motors
density
- Water density (in order to make the agent in a zero-gravity-like setup)
nb_steps_outside_water
- How many consecutive steps the embodiment can survive outside water
Expand source code
class FishBody(SwimmerAbstractBody): ''' Swimming 'fish' embodiment. ''' def __init__(self, scale, density, motors_torque=80, nb_steps_outside_water=600): ''' Creates a fish with three body parts, a fin and a tale. Head contact is allowed for the fish. Args: scale: Scale value used in the environment (to adapt the embodiment to its environment) motors_torque: Maximum torque the embodiment can use on its motors density: Water density (in order to make the agent in a zero-gravity-like setup) nb_steps_outside_water: How many consecutive steps the embodiment can survive outside water ''' super(FishBody, self).__init__(scale, motors_torque, density, nb_steps_outside_water) self.TORQUE_PENALTY = 0.00035 self.AGENT_WIDTH = HULL_BOTTOM_WIDTH / self.SCALE self.AGENT_HEIGHT = 18 /self.SCALE self.AGENT_CENTER_HEIGHT = 9 / self.SCALE self.remove_reward_on_head_angle = True self.fins = [] self.tail = None def draw(self, world, init_x, init_y, force_to_center): init_y = init_y + 1 #### HULL #### HULL_FD = fixtureDef( shape=polygonShape(vertices=[(x / self.SCALE, y / self.SCALE) for x, y in HULL_POLYGONS]), density=self.DENSITY, friction=0.1, categoryBits=0x20, maskBits=0x000F) # 0.99 bouncy hull = world.CreateDynamicBody( position=(init_x, init_y), fixtures=HULL_FD ) hull.color1 = (0.5, 0.4, 0.9) hull.color2 = (0.3, 0.3, 0.5) # hull.ApplyForceToCenter((force_to_center, 0), True) hull.userData = CustomBodyUserData(True, is_contact_critical=False, name="head") self.body_parts.append(hull) self.reference_head_object = hull #### P1 #### body_p1_x = init_x - 35 / 2 / self.SCALE - 16 / 2 / self.SCALE BODY_P1_FD = fixtureDef( shape=polygonShape(vertices=[(x / self.SCALE, y / self.SCALE) for x, y in BODY_P1]), density=self.DENSITY, restitution=0.0, categoryBits=0x20, maskBits=0x000F) body_p1 = world.CreateDynamicBody( position=(body_p1_x, init_y), fixtures=BODY_P1_FD ) body_p1.color1 = (0.5, 0.4, 0.9) body_p1.color2 = (0.3, 0.3, 0.5) rjd = revoluteJointDef( bodyA=hull, bodyB=body_p1, anchor=(init_x - 35 / 2 / self.SCALE, init_y), enableMotor=True, enableLimit=True, maxMotorTorque=self.MOTORS_TORQUE, motorSpeed=1, lowerAngle=-0.1 * np.pi, upperAngle=0.2 * np.pi, ) body_p1.userData = CustomBodyUserData(True, name="body") self.body_parts.append(body_p1) joint_motor = world.CreateJoint(rjd) joint_motor.userData = CustomMotorUserData(SPEED_KNEE, True, contact_body=body_p1) self.motors.append(joint_motor) #### P2 #### body_p2_x = body_p1_x - 16 / 2 / self.SCALE - 16 / 2 / self.SCALE BODY_P2_FD = fixtureDef( shape=polygonShape(vertices=[(x / self.SCALE, y / self.SCALE) for x, y in BODY_P2]), density=self.DENSITY, restitution=0.0, categoryBits=0x20, maskBits=0x000F) body_p2 = world.CreateDynamicBody( position=(body_p2_x, init_y), fixtures=BODY_P2_FD ) body_p2.color1 = (0.5, 0.4, 0.9) body_p2.color2 = (0.3, 0.3, 0.5) rjd = revoluteJointDef( bodyA=body_p1, bodyB=body_p2, anchor=(body_p1_x - 16 / 2 / self.SCALE, init_y), enableMotor=True, enableLimit=True, maxMotorTorque=self.MOTORS_TORQUE, motorSpeed=1, lowerAngle=-0.15 * np.pi, upperAngle=0.15 * np.pi, ) body_p2.userData = CustomBodyUserData(True, name="body") self.body_parts.append(body_p2) joint_motor = world.CreateJoint(rjd) joint_motor.userData = CustomMotorUserData(SPEED_KNEE, True, contact_body=body_p2) self.motors.append(joint_motor) #### P3 #### body_p3_x = body_p2_x - 16 / 2 / self.SCALE - 8 / 2 / self.SCALE BODY_P3_FD = fixtureDef( shape=polygonShape(vertices=[(x / self.SCALE, y / self.SCALE) for x, y in BODY_P3]), density=self.DENSITY, restitution=0.0, categoryBits=0x20, maskBits=0x000F) body_p3 = world.CreateDynamicBody( position=(body_p3_x, init_y), fixtures=BODY_P3_FD ) body_p3.color1 = (0.5, 0.4, 0.9) body_p3.color2 = (0.3, 0.3, 0.5) rjd = revoluteJointDef( bodyA=body_p2, bodyB=body_p3, anchor=(body_p2_x - 16 / 2 / self.SCALE, init_y), enableMotor=True, enableLimit=True, maxMotorTorque=self.MOTORS_TORQUE, motorSpeed=1, lowerAngle=-0.3 * np.pi, upperAngle=0.3 * np.pi, ) body_p3.userData = CustomBodyUserData(True, name="body") self.body_parts.append(body_p3) self.tail = body_p3 joint_motor = world.CreateJoint(rjd) joint_motor.userData = CustomMotorUserData(SPEED_KNEE, True, contact_body=body_p3) self.motors.append(joint_motor) #### FIN #### FIN_FD = fixtureDef( shape=polygonShape(vertices=[(x / self.SCALE, y / self.SCALE) for x, y in FIN]), density=self.DENSITY, restitution=0.0, categoryBits=0x20, maskBits=0x000F) fin_positions = [ # [init_x + 35 / 2 / self.SCALE / 2, init_y], # [init_x - 35 / 2 / self.SCALE / 2, init_y], [init_x, init_y - 22 / 2 / self.SCALE + 0.2], # [init_x - 35 / 2 / self.SCALE / 2, init_y - 22 / 2 / self.SCALE + 0.1], ] fin_angle = -0.2 * np.pi middle_fin_x_distance = np.sin(fin_angle) * 20 / 2 / self.SCALE middle_fin_y_distance = np.cos(fin_angle) * 20 / 2 / self.SCALE for fin_pos in fin_positions: current_fin_x = fin_pos[0] + middle_fin_x_distance current_fin_y = fin_pos[1] - middle_fin_y_distance fin = world.CreateDynamicBody( position=(current_fin_x, current_fin_y), fixtures=FIN_FD, angle=fin_angle ) fin.color1 = (0.5, 0.4, 0.9) fin.color2 = (0.3, 0.3, 0.5) rjd = revoluteJointDef( bodyA=hull, bodyB=fin, anchor=(fin_pos[0], fin_pos[1]), enableMotor=True, enableLimit=True, maxMotorTorque=self.MOTORS_TORQUE, motorSpeed=1, lowerAngle=-0.3 * np.pi, upperAngle=0.2 * np.pi, ) fin.userData = CustomBodyUserData(True, name="fin") self.body_parts.append(fin) self.fins.append(fin) joint_motor = world.CreateJoint(rjd) joint_motor.userData = CustomMotorUserData(SPEED_KNEE, True, contact_body=fin) self.motors.append(joint_motor)
Ancestors
Inherited members