Skip to content

Commit fd61f71

Browse files
juliac demo working!
Co-authored-by: Cody Tapscott <topolarity@tapscott.me>
1 parent b2f2d85 commit fd61f71

File tree

4 files changed

+53
-22
lines changed

4 files changed

+53
-22
lines changed

examples/juliac/juliac_pid.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ end
4444

4545
end
4646

47-
# compile using something like
47+
# compile using something like this, modified to suit your local paths
4848
# cd(@__DIR__)
4949
# run(`/home/fredrikb/repos/julia/julia --project --experimental /home/fredrikb/repos/julia/contrib/juliac.jl --output-lib juliac_pid --experimental --trim=unsafe-warn --compile-ccallable juliac_pid.jl`)
50-
# run(`ls -ltrh`) # marvel at the smallness of the binary
50+
# run(`ls -ltrh`)

examples/juliac/test_juliac_pid.c

Lines changed: 45 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,48 +1,74 @@
11
#include <stdio.h>
22
#include <stdlib.h>
33
#include <dlfcn.h>
4-
#include <julia.h>
4+
// #include <julia.h>
55

6-
// Define the type of the function calculate_control
6+
// Path to julia binary folder
7+
#define JULIA_PATH "/home/fredrikb/repos/julia/usr/bin/" // NOTE: modify this path
8+
9+
// Path to juliac compiled shared object file
10+
#define LIB_PATH "/home/fredrikb/.julia/dev/DiscretePIDs/examples/juliac/juliac_pid.so" // NOTE: modify this path
11+
12+
13+
14+
// Define the types of the julia @ccallable functions
15+
typedef void (*jl_init_with_image_t)(const char *bindir, const char *sysimage);
716
typedef double (*calculate_control_t)(double r, double y, double uff);
17+
typedef void (*set_K_t)(double K, double r, double y);
18+
typedef void (*set_Ti_t)(double Ti);
19+
typedef void (*set_Td_t)(double Td);
20+
typedef void (*reset_state_t)();
821

9-
int main() {
10-
jl_init();
1122

12-
const char *lib_path = "/home/fredrikb/.julia/dev/DiscretePIDs/examples/juliac/juliac_pid.so";
23+
int main() {
1324

1425
// Load the shared library
1526
printf("Loading juliac_pid.so\n");
16-
void *lib_handle = dlopen(lib_path, RTLD_LAZY);
27+
void *lib_handle = dlopen(LIB_PATH, RTLD_LAZY);
1728
if (!lib_handle) {
1829
fprintf(stderr, "Error: Unable to load library %s\n", dlerror());
1930
exit(EXIT_FAILURE);
2031
}
2132
printf("Loaded juliac_pid.so\n");
2233

23-
// Locate the calculate_control function
24-
printf("Finding calculate_control!\n");
34+
// Locate the julia functions function
35+
printf("Finding symbols\n");
36+
jl_init_with_image_t jl_init_with_image = (jl_init_with_image_t)dlsym(lib_handle, "jl_init_with_image");
37+
2538
calculate_control_t calculate_control = (calculate_control_t)dlsym(lib_handle, "calculate_control!");
26-
char *error = dlerror();
27-
if (error != NULL) {
28-
fprintf(stderr, "Error: Unable to find symbol calculate_control!: %s\n", error);
29-
dlclose(lib_handle);
39+
set_K_t set_K = (set_K_t)dlsym(lib_handle, "set_K!");
40+
set_Ti_t set_Ti = (set_Ti_t)dlsym(lib_handle, "set_Ti!");
41+
set_Td_t set_Td = (set_Td_t)dlsym(lib_handle, "set_Td!");
42+
reset_state_t reset_state = (reset_state_t)dlsym(lib_handle, "reset_state!");
43+
44+
45+
if (jl_init_with_image == NULL || calculate_control == NULL) {
46+
char *error = dlerror();
47+
fprintf(stderr, "Error: Unable to find symbol: %s\n", error);
3048
exit(EXIT_FAILURE);
3149
}
32-
printf("Found calculate_control!\n");
50+
printf("Found all symbols!\n");
51+
52+
// Init julia
53+
jl_init_with_image(JULIA_PATH, LIB_PATH);
3354

34-
// Call the function
35-
double r = 0.0, y = 0.0, uff = 0.0;
55+
// Trivial test program that computes a few control outputs and modifies K
56+
double r = 1.0, y = 0.0, uff = 0.0;
3657
double result = calculate_control(r, y, uff);
3758
printf("calculate_control! returned: %f\n", result);
59+
result = calculate_control(r, y, uff);
60+
printf("calculate_control! returned: %f\n", result);
61+
set_K(0.0, r, y);
62+
for (int i = 0; i < 3; ++i) {
63+
result = calculate_control(r, y, uff);
64+
printf("calculate_control! returned: %f\n", result);
65+
}
3866

39-
// Close the library
40-
dlclose(lib_handle);
41-
42-
jl_atexit_hook(0);
67+
// jl_atexit_hook(0);
4368
return 0;
4469
}
4570

4671

72+
// Compile this C program using a command like the one above, modified to suit your paths
4773
// export LD_LIBRARY_PATH=/home/fredrikb/repos/julia/usr/lib:$LD_LIBRARY_PATH
4874
// gcc -o pid_program test_juliac_pid.c -I /home/fredrikb/repos/julia/usr/include/julia -L/home/fredrikb/repos/julia/usr/lib -ljulia -ldl

examples/juliac/test_juliac_pid.jl

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,11 @@
22
cd(@__DIR__)
33

44
const T = Float64
5+
@info("Loading juliac_pid.so")
56
lib = Libc.Libdl.dlopen("/home/fredrikb/.julia/dev/DiscretePIDs/examples/juliac/juliac_pid.so")
7+
@info("Loaded juliac_pid.so, finding calculate_control!")
68
const calc = Libc.Libdl.dlsym(lib, :calculate_control!)
9+
@info("Found calculate_control!")
710

811
function pid(r::T, y::T, uff::T)
912
ccall(calc, T, (T, T, T), r, y, uff)

src/DiscretePIDs.jl

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ u = calculate_control!(pid, r, y, uff) # Equivalent to the above
7171
- `D`: Derivative part
7272
- `yold`: Last measurement signal
7373
74-
See also [`calculate_control!`](@ref), [`set_K!`](@ref), [`set_Ti!`](@ref), [`set_Td!`](@ref)
74+
See also [`calculate_control!`](@ref), [`set_K!`](@ref), [`set_Ti!`](@ref), [`set_Td!`](@ref), [`reset_state!`](@ref).
7575
"""
7676
function DiscretePID(;
7777
K::T = 1f0,
@@ -115,6 +115,8 @@ end
115115
set_K!(pid::DiscretePID, K, r, y)
116116
117117
Update `K` in the PID controller. This function takes the current reference and measurement as well in order to provide bumpless transfer. This is realized by updating the internal state `I`.
118+
119+
Note: Due to the bumpless transfer, setting ``K = 0`` does not imply that the controller output will be 0 if the integral state is non zero. To reset the controller state, call `reset_state!(pid)`.
118120
"""
119121
function set_K!(pid::DiscretePID, K, r, y)
120122
Kold = pid.K

0 commit comments

Comments
 (0)