Skip to content
GitLab
Menu
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
robotran
mbsysc
Commits
670a2c61
Commit
670a2c61
authored
Aug 08, 2019
by
Louis Beauloye
Browse files
[Ctypes] user models + enabling free memory with user models
parent
c0f911d2
Changes
5
Hide whitespace changes
Inline
Side-by-side
MBsysC/mbs_common/mbs_load_xml/mbs_load_xml.c
View file @
670a2c61
...
...
@@ -707,6 +707,7 @@ MbsData* mbs_info_to_data(MbsInfos* mbs_infos, MbsData* s)
void
mbs_delete_data
(
MbsData
*
s
)
{
int
i
;
if
(
s
->
mbs_name
)
...
...
@@ -778,10 +779,10 @@ void mbs_delete_data(MbsData *s)
free_dvec_1
(
s
->
uxd
);
free_dvec_1
(
s
->
ux0
);
}
#ifndef SENSORKIN
// User models
if
(
s
->
Nuser_model
)
if
(
s
->
Nuser_model
&&
s
->
user_model
!=
NULL
)
{
mbs_delete_user_model
(
s
->
user_model
);
}
...
...
@@ -824,5 +825,5 @@ void mbs_delete_data(MbsData *s)
#endif
free
(
s
);
}
MBsysC/mbs_common/mbs_load_xml/mbs_xml_binder_public.h
View file @
670a2c61
...
...
@@ -243,6 +243,9 @@ typedef struct MbsInfoParameter
int
type
;
// scalar=1 ; vector=2 ; lut1D=3 ; lut2D=4 ; state=5 ; structure=6 : integer=7
int
n_value
;
double
*
value_list
;
/** pointer to the memory storing the value in the UserModel structure (redundant with MbsInfoDData **d_value but simpler) **/
void
*
val_ptr
;
MbsInfoDData
**
d_value
;
// d_data for the value
int
is_symmmetric
;
// asymmetric = 0, symmetric master = 1, symmetric salve = 2
...
...
@@ -255,9 +258,6 @@ typedef struct MbsInfoParameter
int
flag_PRJPATH
;
char
*
structure_lutfile
;
/** pointer to the memory storing the value in the UserModel structure (redundant with MbsInfoDData **d_value but simpler) **/
void
*
val_ptr
;
}
MbsInfoParameter
;
typedef
struct
MbsInfoUserModel
...
...
MBsysC/mbs_interface/MBsysPy/mbsysc_loader/forward_decl.py
View file @
670a2c61
...
...
@@ -45,6 +45,8 @@ class MbsInfoLink_c(ctypes.Structure):
pass
class
MbsInfoUserModels_c
(
ctypes
.
Structure
):
pass
class
MbsInfoUserModel_c
(
ctypes
.
Structure
):
pass
class
MbsInfoUserIOs_c
(
ctypes
.
Structure
):
pass
class
MbsInfoParameter_c
(
ctypes
.
Structure
):
...
...
MBsysC/mbs_interface/MBsysPy/mbsysc_loader/mbs_infos_c.py
View file @
670a2c61
...
...
@@ -28,6 +28,7 @@ from .forward_decl import MbsInfoCuts_c
from
.forward_decl
import
MbsInfoLinks_c
from
.forward_decl
import
MbsInfoLink_c
from
.forward_decl
import
MbsInfoUserModels_c
from
.forward_decl
import
MbsInfoUserModel_c
from
.forward_decl
import
MbsInfoUserIOs_c
from
.forward_decl
import
MbsInfoPoint_c
from
.forward_decl
import
MbsInfoSensor_c
...
...
@@ -99,10 +100,29 @@ MbsInfoLinks_c._fields_ = [
#==============================================================================
MbsInfoLink_c
.
_fields_
=
[
(
"name"
,
ctypes
.
c_char_p
)
(
"name"
,
ctypes
.
c_char_p
)
,
#remaining fields not implemented
]
#==============================================================================
# MbsInfoUserModels_c
#==============================================================================
MbsInfoUserModels_c
.
_fields_
=
[
(
"n_user_model"
,
ctypes
.
c_int
),
(
"user_model_list"
,
ctypes
.
POINTER
(
ctypes
.
POINTER
(
MbsInfoUserModel_c
)))
]
#==============================================================================
# MbsInfoUserModel_c
#==============================================================================
MbsInfoUserModel_c
.
_fields_
=
[
(
"name"
,
ctypes
.
c_char_p
),
(
"n_parameter"
,
ctypes
.
c_int
),
(
"parameter_list"
,
ctypes
.
POINTER
(
ctypes
.
POINTER
(
MbsInfoParameter_c
)))
]
#==============================================================================
# MbsInfoPoint_c
#==============================================================================
...
...
@@ -134,3 +154,15 @@ MbsInfoExtforce_c._fields_ = [
#remaining fields not implemented
]
#==============================================================================
# MbsInfoParameter_c
#==============================================================================
MbsInfoParameter_c
.
_fields_
=
[
(
"name"
,
ctypes
.
c_char_p
),
(
"type"
,
ctypes
.
c_int
),
(
"n_value"
,
ctypes
.
c_int
),
(
"value_list"
,
ctypes
.
POINTER
(
ctypes
.
c_double
)),
(
"val_ptr"
,
ctypes
.
POINTER
(
ctypes
.
c_double
))
#remaining fields not implemented
]
\ No newline at end of file
MBsysC/mbs_interface/MBsysPy/mbsyspy/mbs_data.py
View file @
670a2c61
...
...
@@ -52,7 +52,7 @@ from ..mbsysc_loader.callback import mbs_sensor_wrap
#==============================================================================
# Global parameter of the current module
#==============================================================================
__DEBUG__
=
Fals
e
__DEBUG__
=
Tru
e
__MODULE_DIR__
=
os
.
path
.
dirname
(
os
.
path
.
abspath
(
__file__
))
...
...
@@ -223,6 +223,10 @@ class MbsData(object):
fixed frame) applied to each body.
tsim : scalar
The time value.
user_model : dict
Dictionary containing the names of the user models as keys and a second
dictionary with their parameters as values. The second dictionary
contains the names of the parameters as keys and their values as values
ux : ndarray
Numpy array containing the values of the user variables.
ux0 : ndarray
...
...
@@ -385,6 +389,10 @@ class MbsData(object):
self
.
sensor_id
=
{}
self
.
__generate_id__
()
#UserModel
self
.
user_model
=
_StrictDict
()
self
.
__load_user_model__
()
# Loading user function
if
__DEBUG__
:
print
(
"DEBUG>> Loading user functions"
)
...
...
@@ -634,6 +642,11 @@ class MbsData(object):
The other symbolic function will be assigned when a module is
instancied.
Assign and wrap python user functions in which the arguments are not
dependent of another module instance (ie. MbsPart, MbsDirdyn...).
Store the functions in the MbsData instance
and assign the pointer of functions in the C structure
The functions will be assigned to the MbsData instance when
the 'run' function in other modules is called and unassigned
at the end.
...
...
@@ -696,10 +709,6 @@ class MbsData(object):
__Q
=
np
.
ctypeslib
.
as_array
(
Q
,
(
self
.
njoint
+
1
,))
fun
(
self
,
tsim
,
__Q
)
# def callback_undefined(self,function_name=None):
# print("undefined functions: "+function_name)
# return
def
__unassign_user_fct__
(
self
):
"""
Unassign all user function if all args are in MbsData instance.
...
...
@@ -762,6 +771,37 @@ class MbsData(object):
index
=
self
.
mbs_infos_ptr
.
contents
.
extforce_point_list
[
i
]
name
=
self
.
mbs_infos_ptr
.
contents
.
point_list
[
index
].
contents
.
extforce
.
contents
.
name
.
decode
(
'utf-8'
)
self
.
extforce_id
[
name
]
=
i
+
1
def
__load_user_model__
(
self
):
self
.
user_model
.
_locked
=
False
infos_c_ptr
=
self
.
mbs_infos_ptr
.
contents
for
i
in
range
(
infos_c_ptr
.
user_models
.
contents
.
n_user_model
):
user_model_list
=
infos_c_ptr
.
user_models
.
contents
.
user_model_list
[
i
].
contents
name
=
user_model_list
.
name
.
decode
(
'utf-8'
)
self
.
user_model
[
name
]
=
_StrictDict
()
self
.
user_model
[
name
].
_parent_key
=
name
self
.
user_model
[
name
].
_locked
=
False
self
.
user_model
[
name
].
_type
=
dict
()
for
j
in
range
(
user_model_list
.
n_parameter
):
parameter_list
=
user_model_list
.
parameter_list
[
j
].
contents
name2
=
parameter_list
.
name
.
decode
(
'utf-8'
)
val_ptr
=
parameter_list
.
val_ptr
value_list
=
parameter_list
.
value_list
self
.
user_model
[
name
].
_type
[
name2
]
=
parameter_list
.
type
size
=
parameter_list
.
n_value
UmPy
=
(
ctypes
.
cast
(
val_ptr
,
ctypes
.
c_void_p
).
value
==
ctypes
.
cast
(
value_list
,
ctypes
.
c_void_p
).
value
)
if
UmPy
:
self
.
user_model
[
name
][
name2
]
=
np
.
ctypeslib
.
as_array
(
val_ptr
,
(
1
,
size
))
else
:
#not yet tested, it requires user and symbolic fonctions in C
if
self
.
user_model
[
name
].
_type
[
name2
]
==
5
or
self
.
user_model
[
name
].
_type
[
name2
]
==
7
:
self
.
user_model
[
name
][
name2
]
=
np
.
ctypeslib
.
as_array
(
ctypes
.
cast
(
val_ptr
,
ctypes
.
POINTER
(
ctypes
.
c_int
)),
(
1
,
size
))
else
:
self
.
user_model
[
name
][
name2
]
=
np
.
ctypeslib
.
as_array
(
val_ptr
,
(
1
,
size
))
self
.
user_model
[
name
].
_locked
=
True
self
.
user_model
.
_locked
=
True
...
...
@@ -932,10 +972,7 @@ class MbsData(object):
mbs_part
=
MbsPart
(
self
)
mbs_part
.
set_options
(
**
kwargs
)
mbs_part
.
run
()
#==========================================================================
# Defining properties
#==========================================================================
...
...
@@ -1166,3 +1203,72 @@ class MbsData(object):
@
property
def
mbs_name
(
self
):
return
ctypes
.
string_at
(
self
.
mbs_data_ptr
.
contents
.
mbs_name
).
decode
(
"utf-8"
)
class
_StrictDict
(
dict
):
def
__init__
(
self
,
*
args
,
**
kwargs
):
dict
.
__init__
(
self
,
*
args
,
**
kwargs
)
self
.
_locked
=
True
self
.
_parent_key
=
None
self
.
_type
=
None
def
__setitem__
(
self
,
key
,
value
):
if
self
.
_locked
==
True
:
if
not
(
self
.
_type
is
None
):
if
self
.
_type
[
key
]
==
1
:
if
type
(
value
)
is
float
:
tab
=
self
.
__getarray__
(
key
)
tab
[
0
][
0
]
=
value
elif
type
(
value
)
is
int
:
tab
=
self
.
__getarray__
(
key
)
tab
[
0
][
0
]
=
int
(
value
)
else
:
print
(
"UserModel "
+
self
.
_parent_key
+
"."
+
key
+
" is a float, "
+
str
(
type
(
value
))
+
" was given"
)
elif
self
.
_type
[
key
]
==
7
:
if
type
(
value
)
is
int
:
tab
=
self
.
__getarray__
(
key
)
tab
[
0
][
0
]
=
value
else
:
print
(
"UserModel "
+
self
.
_parent_key
+
"."
+
key
+
" is an int, "
+
str
(
type
(
value
))
+
" was given"
)
elif
self
.
_type
[
key
]
==
2
or
self
.
_type
[
key
]
==
5
:
if
type
(
value
)
is
np
.
ndarray
or
type
(
value
)
is
list
:
tab
=
self
.
__getarray__
(
key
)
if
np
.
size
(
value
)
==
np
.
size
(
tab
):
tab
[:]
=
value
[:]
else
:
print
(
"UserModel "
+
self
.
_parent_key
+
"."
+
key
+
" is an array of size "
+
str
(
np
.
size
(
tab
))
+
", array of size "
+
str
(
np
.
size
(
value
))
+
" was given"
)
else
:
print
(
"UserModel "
+
self
.
_parent_key
+
"."
+
key
+
" is an array, "
+
str
(
type
(
value
))
+
" was given"
)
elif
self
.
_type
[
key
]
==
3
:
print
(
"Type lut1D for a user mode is not available in python"
)
elif
self
.
_type
[
key
]
==
4
:
print
(
"Type lut2D for a user mode is not available in python"
)
elif
self
.
_type
[
key
]
==
6
:
print
(
"Type structure for a user model is not available in python"
)
else
:
print
(
"Invalid type for the user model"
)
else
:
dict
.
__setitem__
(
self
,
key
,
value
)
def
__getarray__
(
self
,
key
):
return
dict
.
__getitem__
(
self
,
key
)
def
__getitem__
(
self
,
key
):
if
self
.
_type
is
None
:
return
dict
.
__getitem__
(
self
,
key
)
else
:
if
self
.
_type
[
key
]
==
1
or
self
.
_type
[
key
]
==
7
:
return
dict
.
__getitem__
(
self
,
key
)[
0
][
0
]
else
:
return
dict
.
__getitem__
(
self
,
key
)[
0
]
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment