java_functions.c 7.44 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12

#ifdef JAVA

#include "java_functions.h"
#include "cmake_config.h"

#include <stdlib.h>

// version of the JDK
#define JNI_VERSION JNI_VERSION_1_6

// path to the jar file containing mbsyspad bynary code
13
#define JAR_PATH ROBOTRAN_SOURCE_DIR"/mbsyspad/MBsysPad.jar"
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

#define START_VIEWPOINT 0 ///< default initial viewpoint

/*! \brief instantiate a java virtual machine so as to access to the 3D animation facilities of MBSysPad
 * 
 * \return JNI environment
 */
JNIEnv* create_vm()
{
    int res;

    JavaVM* jvm;
    JNIEnv* env;
    JavaVMInitArgs args;
    JavaVMOption options[2];
    
    // the following parameter should be adapted depending on the version of the JDK
    args.version = JNI_VERSION;
    // number of argument to pass to the jvm
    args.nOptions = 2;
    // path to the jar file containing mbsyspad bynary code
    options[0].optionString = "-Djava.class.path="JAR_PATH;
    // path to the folder containing additional libraries, in particular the java3D native file (libj3dcore-ogl.so for linux)
    options[1].optionString = "-Djava.library.path="J3D_PATH;

    args.options = options;
    args.ignoreUnrecognized = JNI_FALSE;

    res = JNI_CreateJavaVM(&jvm, (void **)&env, &args);

    if (res < 0)
    {
        switch ( res )
        {
            case -1:
                fprintf(stderr, "/* unknown error */\n");
                break;
            case -2:
                fprintf(stderr, "/* thread detached from the VM */\n");
                break;
            case -3:
                fprintf(stderr, "/* JNI version error */\n");
                break;
            case -4:
                fprintf(stderr, "/* not enough memory */\n");
                break;
            case -5:
                fprintf(stderr, "/* VM already created */\n");
                break;
            case -6:
                fprintf(stderr, "/* invalid arguments */\n");
                break;
            default:
                fprintf(stderr, "Can't create Java VM\n");
        }
        exit(1);
    }

    return env;
}

/*! \brief initialize the JNI structure
 * 
 * \param[in] nb_q number of joints in the .mbs file
 * \param[in] q_vec vector of size nb_q with the initial values for q
 * \param[in] mbs_file path and name of the .mbs file used for visualization
 * \return JNI structure
 */
Nicolas Van der Noot's avatar
Nicolas Van der Noot committed
82
JNI_struct* init_jni(int nb_q, double *q_vec, char *mbs_file, int start_viewpoint)
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
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
{
    JNI_struct *jni_struct;
    

    // - - - - - - - - - - - - - - - - -
    // declaration for 3D view with JNI

    jclass animFrameClass,  PadModelClass, MbsModelJ3DClass;
    jmethodID constructor;
    jmethodID loadMethod, setLocMethod;
    jmethodID getModelMethod, getMbs3DMethod, setVpMethod;
    jobject model, model3D;
    jstring mbsFilename;
    jdoubleArray doubleArrayArg;

    JNIEnv* env;
    jmethodID updateJointMethod;
    jobject obj;

    // - - - - - - - - - - - - - - - - - - - - - - -
    // initialise jni variable for 3D visualisation

    env = create_vm();

    animFrameClass = (*env)->FindClass(env, "be/robotran/test/LiveSimAnimFrame");

    // get the reference to the constructor of this class
    constructor = (*env)->GetMethodID(env, animFrameClass, "<init>", "()V");

    // get the reference to the load method which load the *.mbs file
    loadMethod = (*env)->GetMethodID(env, animFrameClass, "load", "(Ljava/lang/String;)V");
   
    // get the reference to the updateJoints method which update the 3D view during simulation
    updateJointMethod = (*env)->GetMethodID(env, animFrameClass, "updateJoints", "([D)V");
 
    // get the reference to the setLocation method 
    setLocMethod = (*env)->GetMethodID(env, animFrameClass, "setLocation", "(II)V");
    
    // create a jni string containing the path to the *.mbs file to load
    mbsFilename = (*env)->NewStringUTF(env, mbs_file);

    // create an instance of the 3D view
    obj = (*env)->NewObject(env, animFrameClass, constructor);
    
    // load the mbsfilename
    (*env)->CallObjectMethod(env, obj, loadMethod, mbsFilename);

    // Viewpoint
    // get the reference to the class
    PadModelClass    = (*env)->FindClass(env, "be/robotran/mbsyspad/PadModel");
    MbsModelJ3DClass = (*env)->FindClass(env, "be/robotran/mbs3Dviewer/j3Dviewer/MbsModelJ3D");

    // get the reference to the methods
    getModelMethod = (*env)->GetMethodID(env, animFrameClass, "getModel", "()Lbe/robotran/mbsyspad/PadModel;");
    getMbs3DMethod = (*env)->GetMethodID(env, PadModelClass, "getMbs3D", "()Lbe/robotran/mbs3Dviewer/viewerInterface/MbsModel3D;");
    setVpMethod    = (*env)->GetMethodID(env, MbsModelJ3DClass, "setViewpoint", "(I)V");

    model   = (*env)->CallObjectMethod(env, obj, getModelMethod);
    model3D = (*env)->CallObjectMethod(env, model, getMbs3DMethod);
    (*env)->CallObjectMethod(env, model3D, setVpMethod, -1);

    // move the frame
    (*env)->CallObjectMethod(env, obj, setLocMethod, 100,100);

    // instantiate a jni array of double
    doubleArrayArg = (*env)->NewDoubleArray(env, nb_q);

    // copy the current values of q_vec to the jni array
    (*env)->SetDoubleArrayRegion(env, doubleArrayArg, 0 , nb_q, q_vec);

Nicolas Van der Noot's avatar
Nicolas Van der Noot committed
153
154
155
    // adapt the viewpoint
    (*env)->CallObjectMethod(env, model3D, setVpMethod, start_viewpoint);

156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
    // update the 3D view
    (*env)->CallObjectMethod(env, obj, updateJointMethod, doubleArrayArg);

    // JNI structure
    jni_struct = (JNI_struct*) malloc(sizeof(JNI_struct));

    jni_struct->env               = env;
    jni_struct->updateJointMethod = updateJointMethod;
    jni_struct->obj               = obj;
    jni_struct->setVpMethod       = setVpMethod;
    jni_struct->model3D           = model3D;

    return jni_struct; 
}

/*! \brief Release memory
 * 
 * \param[out] jni_struct JNI structure to release
 */
void free_jni(JNI_struct *jni_struct)
{
    free(jni_struct);
}

/*! \brief update the Java visualization
 * 
 * \param[in,out] realtime real-time structure
 */
void update_java(Simu_realtime *realtime)
{   
    Realtime_java *java;
Nicolas Van der Noot's avatar
Nicolas Van der Noot committed
187
    MbsData* mbs_data;
188

Nicolas Van der Noot's avatar
Nicolas Van der Noot committed
189
190
    java     = realtime->ext->java;
    mbs_data = realtime->ext->mbs_data;
191

Nicolas Van der Noot's avatar
Nicolas Van der Noot committed
192
    user_realtime_visu(mbs_data, java->nb_q, java->cur_q);
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245

    if (java->visu_past_flag)
    {
        java->visu_past_flag = 0;
        update_jni(java->jni_struct, java, java->nb_q, java->past_q);
    }
    else
    {
        update_jni(java->jni_struct, java, java->nb_q, java->cur_q);
    }
}

/*! \brief update the 3D view with JNI
 * 
 * \param[in] jni_struct JNI structure
 * \param[in] java Java real-time structure
 * \param[in] nb_q number of joints to update for the visualization
 * \param[in] q_vec vector of size nb_q with the current values to plot
 */
void update_jni(JNI_struct *jni_struct, Realtime_java *java, int nb_q, double *q_vec)
{
    // variables declarationb
    jdoubleArray doubleArrayArg;
    JNIEnv* env;

    env = jni_struct->env;

    // instantiate a jni array of double
    doubleArrayArg = (*env)->NewDoubleArray(env, nb_q);

    // copy the current values of q_vec to the jni array
    (*env)->SetDoubleArrayRegion(env, doubleArrayArg, 0 , nb_q, q_vec);

    // adapt the viewpoint
    if (java->change_viewpoint)
    {
        java->change_viewpoint = 0;

        java->cur_viewpoint++;

        if (java->cur_viewpoint >= java->nb_viewpoints)
        {
            java->cur_viewpoint = START_VIEWPOINT;
        }

        (*env)->CallObjectMethod(env, jni_struct->model3D, jni_struct->setVpMethod, java->cur_viewpoint);
    }

    // update the 3D view
    (*env)->CallObjectMethod(env, jni_struct->obj, jni_struct->updateJointMethod, doubleArrayArg);
}

#endif