mirror of
https://github.com/wpilibsuite/allwpilib
synced 2026-06-19 00:41:43 +00:00
Pull request for the Extensions interface only (#655)
* Modify halsim to be able to load extension libraries if they are available. It will read the list of libraries to try from the HALSIM_EXTENSIONS environment variable. Multiple libraries can be given if separated by ';' (Windows) or ':' (Unix). The library must have an 'HALSIM_InitExtension' method that returns >= 0 on success. The library is expected to use the interface expressed by hal/src/src/main/native/include/MockData * Add a simple halsim library that just prints robot values. This makes a good test bed for cross platform purposes, and provides the ultimate in light weight simulators. This initial version only prints PWM values.
This commit is contained in:
committed by
Peter Johnson
parent
2fc60680f4
commit
be77f9cb26
@@ -108,6 +108,11 @@ model {
|
||||
}
|
||||
}
|
||||
}
|
||||
binaries.all { binary ->
|
||||
if (binary.targetPlatform.operatingSystem.linux) {
|
||||
linker.args "-ldl"
|
||||
}
|
||||
}
|
||||
}
|
||||
if (project.hasProperty('buildHalStaticDeps')) {
|
||||
halSimStaticDeps(NativeLibrarySpec) {
|
||||
|
||||
25
hal/src/main/native/include/HAL/Extensions.h
Normal file
25
hal/src/main/native/include/HAL/Extensions.h
Normal file
@@ -0,0 +1,25 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) 2017 FIRST. All Rights Reserved. */
|
||||
/* Open Source Software - may be modified and shared by FRC teams. The code */
|
||||
/* must be accompanied by the FIRST BSD license file in the root directory of */
|
||||
/* the project. */
|
||||
/*----------------------------------------------------------------------------*/
|
||||
|
||||
#pragma once
|
||||
|
||||
/**
|
||||
* HAL Simulator Extensions are libraries that provide additional simulator
|
||||
* functionality, such as a Gazebo interface, or a more light weight simulation.
|
||||
*
|
||||
* An extension must expose the HALSIM_InitExtension entry point which is
|
||||
* invoked after the library is loaded.
|
||||
*
|
||||
* The entry point is expected to return < 0 for errors that should stop
|
||||
* the HAL completely, 0 for success, and > 0 for a non fatal error.
|
||||
*/
|
||||
typedef int halsim_extension_init_func_t(void);
|
||||
|
||||
extern "C" {
|
||||
int HAL_LoadOneExtension(const char* library);
|
||||
int HAL_LoadExtensions(void);
|
||||
}
|
||||
83
hal/src/main/native/sim/Extensions.cpp
Normal file
83
hal/src/main/native/sim/Extensions.cpp
Normal file
@@ -0,0 +1,83 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) 2017 FIRST. All Rights Reserved. */
|
||||
/* Open Source Software - may be modified and shared by FRC teams. The code */
|
||||
/* must be accompanied by the FIRST BSD license file in the root directory of */
|
||||
/* the project. */
|
||||
/*----------------------------------------------------------------------------*/
|
||||
|
||||
#include "HAL/Extensions.h"
|
||||
|
||||
#include <llvm/SmallString.h>
|
||||
#include <llvm/StringRef.h>
|
||||
|
||||
#include "HAL/HAL.h"
|
||||
|
||||
#if defined(WIN32) || defined(_WIN32)
|
||||
#include <windows.h>
|
||||
#else
|
||||
#include <dlfcn.h>
|
||||
#endif
|
||||
|
||||
#if defined(WIN32) || defined(_WIN32)
|
||||
#define DELIM ';'
|
||||
#define HTYPE HMODULE
|
||||
#define DLOPEN(a) LoadLibrary(a)
|
||||
#define DLSYM GetProcAddress
|
||||
#define DLCLOSE FreeLibrary
|
||||
#else
|
||||
#define DELIM ':'
|
||||
#define HTYPE void*
|
||||
#define PREFIX "lib"
|
||||
#define DLOPEN(a) dlopen(a, RTLD_LAZY)
|
||||
#define DLSYM dlsym
|
||||
#define DLCLOSE dlclose
|
||||
#endif
|
||||
|
||||
extern "C" {
|
||||
|
||||
int HAL_LoadOneExtension(const char* library) {
|
||||
int rc = 1; // It is expected and reasonable not to find an extra simulation
|
||||
HTYPE handle = DLOPEN(library);
|
||||
#if !defined(WIN32) && !defined(_WIN32)
|
||||
if (!handle) {
|
||||
llvm::SmallString<128> libraryName("lib");
|
||||
libraryName += library;
|
||||
#if defined(__APPLE__)
|
||||
libraryName += ".dylib";
|
||||
#else
|
||||
libraryName += ".so";
|
||||
#endif
|
||||
handle = DLOPEN(libraryName.c_str());
|
||||
}
|
||||
#endif
|
||||
if (!handle) return rc;
|
||||
|
||||
auto init = reinterpret_cast<halsim_extension_init_func_t*>(
|
||||
DLSYM(handle, "HALSIM_InitExtension"));
|
||||
|
||||
if (init) rc = (*init)();
|
||||
|
||||
if (rc != 0) DLCLOSE(handle);
|
||||
return rc;
|
||||
}
|
||||
|
||||
/**
|
||||
* Load any extra halsim libraries provided in the HALSIM_EXTENSIONS
|
||||
* environment variable.
|
||||
*/
|
||||
int HAL_LoadExtensions(void) {
|
||||
int rc = 1;
|
||||
llvm::SmallVector<llvm::StringRef, 2> libraries;
|
||||
const char* e = std::getenv("HALSIM_EXTENSIONS");
|
||||
if (!e) return rc;
|
||||
llvm::StringRef env{e};
|
||||
env.split(libraries, DELIM, -1, false);
|
||||
for (auto& libref : libraries) {
|
||||
llvm::SmallString<128> library(libref);
|
||||
rc = HAL_LoadOneExtension(library.c_str());
|
||||
if (rc < 0) break;
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
} // extern "C"
|
||||
@@ -10,6 +10,7 @@
|
||||
#include "ErrorsInternal.h"
|
||||
#include "HAL/DriverStation.h"
|
||||
#include "HAL/Errors.h"
|
||||
#include "HAL/Extensions.h"
|
||||
#include "HAL/handles/HandlesInternal.h"
|
||||
#include "MockData/RoboRioDataInternal.h"
|
||||
#include "MockHooksInternal.h"
|
||||
@@ -203,6 +204,7 @@ HAL_Bool HAL_Initialize(int32_t timeout, int32_t mode) {
|
||||
// Second check in case another thread was waiting
|
||||
if (initialized) return true;
|
||||
|
||||
if (HAL_LoadExtensions() < 0) return false;
|
||||
hal::RestartTiming();
|
||||
HAL_InitializeDriverStation();
|
||||
|
||||
|
||||
@@ -8,3 +8,4 @@ include 'wpilibj'
|
||||
include 'wpilibjIntegrationTests'
|
||||
include 'wpilibjExamples'
|
||||
include 'myRobot'
|
||||
include 'simulation:halsim_print'
|
||||
|
||||
26
simulation/halsim_print/build.gradle
Normal file
26
simulation/halsim_print/build.gradle
Normal file
@@ -0,0 +1,26 @@
|
||||
description = "A simulation shared object that simply prints robot behaviors"
|
||||
|
||||
apply plugin: 'edu.wpi.first.NativeUtils'
|
||||
apply plugin: 'cpp'
|
||||
|
||||
ext.skipAthena = true
|
||||
|
||||
apply from: "../../config.gradle"
|
||||
|
||||
|
||||
model {
|
||||
components {
|
||||
halsim_print(NativeLibrarySpec)
|
||||
}
|
||||
|
||||
binaries {
|
||||
all {
|
||||
project(':hal').addHalCompilerArguments(it)
|
||||
project(':hal').addHalToLinker(it)
|
||||
}
|
||||
withType(StaticLibraryBinarySpec) {
|
||||
it.buildable = false
|
||||
}
|
||||
}
|
||||
}
|
||||
apply from: 'publish.gradle'
|
||||
43
simulation/halsim_print/publish.gradle
Normal file
43
simulation/halsim_print/publish.gradle
Normal file
@@ -0,0 +1,43 @@
|
||||
apply plugin: 'maven-publish'
|
||||
apply plugin: 'edu.wpi.first.wpilib.versioning.WPILibVersioningPlugin'
|
||||
|
||||
if (!hasProperty('releaseType')) {
|
||||
WPILibVersion {
|
||||
releaseType = 'dev'
|
||||
}
|
||||
}
|
||||
|
||||
def pubVersion = ''
|
||||
if (project.hasProperty("publishVersion")) {
|
||||
pubVersion = project.publishVersion
|
||||
} else {
|
||||
pubVersion = WPILibVersion.version
|
||||
}
|
||||
|
||||
def baseArtifactId = 'halsim-print'
|
||||
def artifactGroupId = 'edu.wpi.first.halsim'
|
||||
|
||||
|
||||
model {
|
||||
publishing {
|
||||
def libSpec
|
||||
$.components.each {
|
||||
if (it in NativeLibrarySpec) {
|
||||
$.binaries.each {
|
||||
if (it in SharedLibraryBinarySpec) {
|
||||
libSpec = it.sharedLibraryFile
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
publications {
|
||||
cpp(MavenPublication) {
|
||||
artifact libSpec
|
||||
artifactId = baseArtifactId
|
||||
groupId artifactGroupId
|
||||
version pubVersion
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
29
simulation/halsim_print/src/halsim_print/cpp/PrintPWM.cpp
Normal file
29
simulation/halsim_print/src/halsim_print/cpp/PrintPWM.cpp
Normal file
@@ -0,0 +1,29 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) 2017 FIRST. All Rights Reserved. */
|
||||
/* Open Source Software - may be modified and shared by FRC teams. The code */
|
||||
/* must be accompanied by the FIRST BSD license file in the root directory of */
|
||||
/* the project. */
|
||||
/*----------------------------------------------------------------------------*/
|
||||
|
||||
#include "PrintPWM.h"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include "MockData/HAL_Value.h"
|
||||
#include "MockData/NotifyListener.h"
|
||||
#include "MockData/PWMData.h"
|
||||
|
||||
static void PWMCallback(const char* name, void* param,
|
||||
const struct HAL_Value* value) {
|
||||
auto pwm = static_cast<PrintPWM*>(param);
|
||||
pwm->Publish(value->data.v_double);
|
||||
}
|
||||
|
||||
PrintPWM::PrintPWM(int port) {
|
||||
m_port = port;
|
||||
HALSIM_RegisterPWMSpeedCallback(port, PWMCallback, this, false);
|
||||
}
|
||||
|
||||
void PrintPWM::Publish(double value) {
|
||||
std::cout << "PWM " << m_port << ": " << value << std::endl;
|
||||
}
|
||||
34
simulation/halsim_print/src/halsim_print/cpp/main.cpp
Normal file
34
simulation/halsim_print/src/halsim_print/cpp/main.cpp
Normal file
@@ -0,0 +1,34 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) 2017 FIRST. All Rights Reserved. */
|
||||
/* Open Source Software - may be modified and shared by FRC teams. The code */
|
||||
/* must be accompanied by the FIRST BSD license file in the root directory of */
|
||||
/* the project. */
|
||||
/*----------------------------------------------------------------------------*/
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include <HAL/Ports.h>
|
||||
|
||||
#include "HALSimPrint.h"
|
||||
#include "PrintPWM.h"
|
||||
|
||||
/**
|
||||
* Currently, robots never terminate, so we keep a single static object
|
||||
* and it is never properly released or cleaned up.
|
||||
*/
|
||||
static HALSimPrint halsim;
|
||||
|
||||
extern "C" {
|
||||
#if defined(WIN32) || defined(_WIN32)
|
||||
__declspec(dllexport)
|
||||
#endif
|
||||
int HALSIM_InitExtension(void) {
|
||||
std::cout << "Print Simulator Initializing." << std::endl;
|
||||
|
||||
int pwmCount = HAL_GetNumPWMChannels();
|
||||
halsim.m_pwms.reserve(pwmCount);
|
||||
for (int i = 0; i < pwmCount; i++) halsim.m_pwms.emplace_back(i);
|
||||
|
||||
return 0;
|
||||
}
|
||||
} // extern "C"
|
||||
@@ -0,0 +1,17 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) 2017 FIRST. All Rights Reserved. */
|
||||
/* Open Source Software - may be modified and shared by FRC teams. The code */
|
||||
/* must be accompanied by the FIRST BSD license file in the root directory of */
|
||||
/* the project. */
|
||||
/*----------------------------------------------------------------------------*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
|
||||
class PrintPWM;
|
||||
|
||||
class HALSimPrint {
|
||||
public:
|
||||
std::vector<PrintPWM> m_pwms;
|
||||
};
|
||||
19
simulation/halsim_print/src/halsim_print/headers/PrintPWM.h
Normal file
19
simulation/halsim_print/src/halsim_print/headers/PrintPWM.h
Normal file
@@ -0,0 +1,19 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) 2017 FIRST. All Rights Reserved. */
|
||||
/* Open Source Software - may be modified and shared by FRC teams. The code */
|
||||
/* must be accompanied by the FIRST BSD license file in the root directory of */
|
||||
/* the project. */
|
||||
/*----------------------------------------------------------------------------*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "HALSimPrint.h"
|
||||
|
||||
class PrintPWM {
|
||||
public:
|
||||
explicit PrintPWM(int port);
|
||||
void Publish(double value);
|
||||
|
||||
private:
|
||||
int m_port;
|
||||
};
|
||||
Reference in New Issue
Block a user