-
Notifications
You must be signed in to change notification settings - Fork 0
/
virtual_agents.py
136 lines (111 loc) · 4.7 KB
/
virtual_agents.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
"""
Copyright (c) 2024 Idiap Research Institute, http://www.idiap.ch/
Written by Cem Bilaloglu <cem.bilaloglu@idiap.ch>
This file is part of diffusionVirtualFixtures.
diffusionVirtualFixtures is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License version 3 as
published by the Free Software Foundation.
diffusionVirtualFixtures is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with diffusionVirtualFixtures. If not, see <http://www.gnu.org/licenses/>.
"""
import numpy as np
class FirstOrderAgent:
"""
A class representing a first-order agent.
Attributes:
x (numpy.ndarray): The position of the agent.
dx (numpy.ndarray): The velocity of the agent.
max_velocity (float): The maximum velocity of the agent.
dt (float): The time step for updating the agent's position.
dim_t (int): The dimension of time for storing the agent's position history.
x_arr (numpy.ndarray): The array for storing the agent's position history.
t (int): The current time step for storing the agent's position history.
Methods:
update(gradient): Updates the agent's velocity and position based on the given gradient.
"""
def __init__(self, x, max_velocity=3, dt=1, dim_t=None):
self.x = np.array(x) # position
self.dx = np.zeros(self.x.shape)
self.max_velocity = max_velocity
self.dt = dt
self.dim_t = dim_t
if self.dim_t is None:
self.x_list = []
else:
self.x_arr = np.zeros((self.dim_t, 3))
self.t = 0
def update(self, gradient):
"""
Updates the agent's velocity and position based on the given gradient.
Args:
gradient (numpy.ndarray): The gradient used to update the agent's velocity.
Returns:
None
"""
self.dx = gradient # update the vel.
if np.linalg.norm(gradient) > self.max_velocity:
# clamp the vel.
self.dx = self.max_velocity * gradient / np.linalg.norm(gradient)
self.x = self.x + self.dt * self.dx
if self.dim_t is None:
self.x_list.append(self.x)
else:
self.x_arr[self.t, :] = self.x
self.t += 1
def __str__(self):
return f"dx:{np.linalg.norm(self.dx)}"
class SecondOrderAgent:
"""
A class representing a second-order agent.
Attributes:
x (numpy.ndarray): The position of the agent.
dx (numpy.ndarray): The velocity of the agent.
ddx (numpy.ndarray): The acceleration of the agent.
dt (float): The time step for updating the agent's state.
dim_t (int): The dimension of time (optional).
max_velocity (float): The maximum velocity of the agent.
max_acceleration (float): The maximum acceleration of the agent.
Methods:
update(gradient): Updates the agent's state based on the given gradient.
"""
def __init__(self, x, max_velocity=3, max_acceleration=1, dt=1, dim_t=None):
self.x = np.array(x) # position
self.dx = np.zeros(self.x.shape)
self.ddx = np.zeros(self.x.shape)
self.dt = dt
self.dim_t = dim_t
if self.dim_t is not None:
self.x_arr = np.zeros((dim_t, 3))
self.t = 0
self.max_velocity = max_velocity
self.max_acceleration = max_acceleration
def update(self, gradient):
"""
Updates the agent's state based on the given gradient.
Args:
gradient (numpy.ndarray): The gradient used to update the acceleration.
Returns:
None
"""
ddx = gradient # update the acc.
if np.linalg.norm(gradient) > self.max_acceleration:
# clamp acc.
ddx = self.max_acceleration * gradient / np.linalg.norm(gradient)
# print(f"ddx:{ddx}")
x_prev = np.copy(self.x)
self.x += +self.dt * self.dx + 0.5 * self.dt * self.dt * ddx
# print(f"x:{self.x-x_prev}")
# self.x += 0
if self.dim_t is not None:
self.x_arr[self.t, :] = self.x
self.t += 1
self.dx += self.dt * ddx # update the vel.
if np.linalg.norm(self.dx) > self.max_velocity:
# clamp the vel.
self.dx = self.max_velocity * self.dx / np.linalg.norm(self.dx)
def __str__(self):
return f"dx:{np.linalg.norm(self.dx)} ddx:{np.linalg.norm(self.ddx)}"