I want to stack some capsules to simulate a tube. It looks like:

Then, I apply the force to the top capsule to make this tube bending, and I expect these capsules bending to arc.

In order to achieve my purpose, I calculate the coordinate x/y/z for the top capsule, and calculate the force:

```
x = node_paths[-1].getMat()
m = np.array(x)
x = [m[0][0], m[1][0], m[2][0]]
y = [m[0][1], m[1][1], m[2][1]]
z = [m[0][2], m[1][2], m[2][2]]
f = xforce*np.array(x) + yforce*np.array(y)
last.node().set_active(True)
last.node().apply_central_force(force)
```

When press the keyboard `d`

, the `xforce`

would increase one: `xforce = xforce + 1`

. Finally, the result is:

And it do not change even I press `d`

.

The complete code to reproduce my experiment is:

```
import time
import direct.directbase.DirectStart
from panda3d.core import Vec3, TransformState, Point3, BitMask32, LPoint3, LVector3, Material
from panda3d.bullet import BulletWorld, BulletDebugNode, BulletCylinderShape, BulletCapsuleShape
from panda3d.bullet import BulletPlaneShape, BulletSphericalConstraint, BulletConeTwistConstraint
from panda3d.bullet import BulletRigidBodyNode, BulletTriangleMesh, BulletTriangleMeshShape
from panda3d.bullet import BulletBoxShape
from direct.showbase.InputStateGlobal import inputState
import numpy as np
base.cam.setPos(0, -10, 0)
base.cam.lookAt(0, 0, 0)
debugNode = BulletDebugNode('Debug')
debugNode.showWireframe(True)
debugNode.showConstraints(True)
debugNode.showBoundingBoxes(True)
debugNode.showNormals(False)
debugNP = render.attachNewNode(debugNode)
debugNP.show()
# World
world = BulletWorld()
world.setGravity(Vec3(0, 0, 0))
world.setDebugNode(debugNP.node())
# Plane
shape = BulletPlaneShape(Vec3(0, 0, 1), 0)
node = BulletRigidBodyNode('Ground')
node.addShape(shape)
nodePath = render.attachNewNode(node)
nodePath.setPos(0, 0, 0)
world.attachRigidBody(node)
inputState.watchWithModifiers('x_add', 'd')
inputState.watchWithModifiers('x_minu', 'a')
inputState.watchWithModifiers('y_add', 'w')
inputState.watchWithModifiers('y_minu', 's')
# inputState.watchWithModifiers('turnLeft', 'q')
# inputState.watchWithModifiers('turnRight', 'e')
inputState.watchWithModifiers('up', 'u')
num_segment = 10
segment_length = 1
segment_radius = 1
shape = BulletCapsuleShape(radius=segment_radius, height=segment_length)
previous_node = None
node_paths = []
# pos = [75.81992094545193, 314.34202388786053, 9.5]
for i in range(num_segment):
node = BulletRigidBodyNode(f'segment_{i}')
node.addShape(shape)
node.setMass(1.0)
node.set_linear_damping(0.1)
node.set_angular_damping(0.1)
if i == 0:
# node.set_static(True)
node_path = render.attachNewNode(node)
node_path.setPos(0, 0, segment_length / 2 + segment_radius)
constraint = BulletSphericalConstraint(node, Point3(0, 0, -segment_length / 2 - segment_radius))
world.attach_constraint(constraint)
else:
# # å°åäøäøŖčē¹čæę„å°å½åčē¹
constraint = BulletConeTwistConstraint(previous_node, node,
TransformState.make_pos(Vec3(0, 0, segment_length / 2 + segment_radius)),
TransformState.make_pos(
Vec3(0, 0, -segment_length / 2 - segment_radius)))
world.attach_constraint(constraint)
node_path = render.attachNewNode(node)
node_path.setPos(previous_node_path.get_pos() + Vec3(0, 0, segment_length + 2 * segment_radius))
previous_node = node
previous_node_path = node_path
world.attachRigidBody(node)
node_paths.append(node_path)
uselessConstrain = []
global xforce, yforce
xforce = 0
yforce = 0
def process_input():
global xforce, yforce
if inputState.isSet('y_add'):
yforce += 1
time.sleep(0.2)
if inputState.isSet('y_minu'):
yforce -= 1
time.sleep(0.2)
if inputState.isSet('x_minu'):
xforce += 1
time.sleep(0.2)
if inputState.isSet('x_add'):
xforce -= 1
time.sleep(0.2)
x = node_paths[-1].getMat()
m = np.array(x)
x = [m[0][0], m[1][0], m[2][0]]
y = [m[0][1], m[1][1], m[2][1]]
z = [m[0][2], m[1][2], m[2][2]]
f = xforce*np.array(x) + yforce*np.array(y)
print(xforce, yforce)
force = LVector3(f[0], f[1], f[2])
last = node_paths[-1]
last.node().set_active(True)
last.node().apply_central_force(force)
# Update
def update(task):
dt = globalClock.getDt()
process_input()
world.doPhysics(dt)
return task.cont
taskMgr.add(update, 'update')
base.run()
```

Any suggestion is appreciated~~~~