commit
4f33861787
35 changed files with 6645 additions and 0 deletions
-
82lwrserv/Makefile
-
14lwrserv/Point.h
-
417lwrserv/SocketObject.cpp
-
172lwrserv/SocketObject.h
-
36lwrserv/StringTool.cpp
-
13lwrserv/StringTool.h
-
1079lwrserv/SvrHandling.cpp
-
61lwrserv/SvrHandling.h
-
38lwrserv/defines.h
-
504lwrserv/friComm.h
-
288lwrserv/friremote.cpp
-
194lwrserv/friremote.h
-
543lwrserv/friudp.cpp
-
257lwrserv/friudp.h
-
36lwrserv/global.cpp
-
32lwrserv/global.h
-
24lwrserv/header.h
-
BINlwrserv/include/libblas.dll
-
BINlwrserv/include/libblas.lib
-
BINlwrserv/include/liblapack.dll
-
BINlwrserv/include/liblapack.lib
-
354lwrserv/mat.h
-
520lwrserv/program.cpp
-
1368lwrserv/pthread/pthread.h
-
BINlwrserv/pthread/pthreadVC2.dll
-
BINlwrserv/pthread/pthreadVC2.lib
-
BINlwrserv/pthread/pthreadVCE2.dll
-
BINlwrserv/pthread/pthreadVCE2.lib
-
BINlwrserv/pthread/pthreadVSE2.dll
-
BINlwrserv/pthread/pthreadVSE2.lib
-
183lwrserv/pthread/sched.h
-
169lwrserv/pthread/semaphore.h
-
14lwrserv/resource.h
-
13lwrserv/sgn.h
-
234lwrserv/vec.h
@ -0,0 +1,82 @@ |
|||||
|
################################################################################
|
||||
|
# Contents: makefile with dependency generation #
|
||||
|
# 26.05.2015 #
|
||||
|
#------------------------------------------------------------------------------#
|
||||
|
# makefile for cpp/c bins and libs #
|
||||
|
# autor Philipp Schoenberger #
|
||||
|
# ph.schoenberger@googlemail.com #
|
||||
|
################################################################################
|
||||
|
LIBS = pthread |
||||
|
|
||||
|
OUT_BINARY = lwrserv |
||||
|
|
||||
|
CC = g++ |
||||
|
GLOBAL_FLAGS = -g -o2 -ansi -pedantic -DHAVE_SOCKLEN_T |
||||
|
CFLAGS = $(GLOBAL_FLAGS) |
||||
|
CXXFLAGS = $(GLOBAL_FLAGS) |
||||
|
CPPFLAGS = $(GLOBAL_FLAGS) |
||||
|
LDFLAGS = $(patsubst %,-l%,$(LIBS)) |
||||
|
|
||||
|
BUILD_DIR = build |
||||
|
|
||||
|
# Sources
|
||||
|
SRC_C := $(wildcard *.c) |
||||
|
SRC_H := $(wildcard *.h) |
||||
|
SRC_CPP := $(wildcard *.cpp) |
||||
|
SRC_HPP := $(wildcard *.hpp) |
||||
|
#SRC_CXX := $(wildcard *.cxx)
|
||||
|
#SRC_CC := $(wildcard *.C)
|
||||
|
|
||||
|
# Objects
|
||||
|
OBJS_C = $(patsubst %.c,$(BUILD_DIR)/%.o,$(SRC_C)) |
||||
|
OBJS_CPP = $(patsubst %.cpp,$(BUILD_DIR)/%.o,$(SRC_CPP)) |
||||
|
|
||||
|
|
||||
|
OBJS=$(patsubst %.o,%.o,$(OBJS_C) $(OBJS_CPP)) |
||||
|
|
||||
|
# Dependencies
|
||||
|
DEPS_H = $(patsubst %.h,$(BUILD_DIR)/%.d,$(SRC_H)) |
||||
|
DEPS_HPP = $(patsubst %.hpp,$(BUILD_DIR)/%.d,$(SRC_HPP)) |
||||
|
|
||||
|
DEPS=$(OBJS:%.o=%.d) |
||||
|
#DEPS+=$(DEPS_H)
|
||||
|
#DEPS+=$(DEPS_HPP)
|
||||
|
|
||||
|
.DEFAULT: all |
||||
|
Q=@ |
||||
|
|
||||
|
all: $(BUILD_DIR) $(BUILD_DIR)/$(OUT_BINARY) |
||||
|
|
||||
|
$(BUILD_DIR): |
||||
|
$(Q)echo " [mk] $(BUILD_DIR)" |
||||
|
$(Q)mkdir -p $(BUILD_DIR) |
||||
|
|
||||
|
clean: |
||||
|
$(Q)echo " [rm] $(BUILD_DIR)" |
||||
|
$(Q)rm -rf $(BUILD_DIR) |
||||
|
|
||||
|
$(BUILD_DIR)/$(OUT_BINARY): $(BUILD_DIR) $(DEPS) $(DEP_LIBS) $(OBJS) |
||||
|
$(Q)echo " [ld] $@" |
||||
|
$(Q)( $(CC) $(CFLAGS) $(OBJS) $(LDFLAGS) -o $(OUT_BINARY)) || exit 1 |
||||
|
|
||||
|
$(BUILD_DIR)/%.o : %.c $(BUILD_DIR) |
||||
|
$(Q)echo " [CC] $@" |
||||
|
$(Q)( $(CC) -c $(CFLAGS) $(CPPFLAGS) $< -o $@ ) || exit 1 |
||||
|
|
||||
|
$(BUILD_DIR)/%.o : %.cpp $(BUILD_DIR) |
||||
|
$(Q)echo " [CXX] $@" |
||||
|
$(Q)( $(CXX) -c $(CXXFLAGS) $(CPPFLAGS) $< -o $@ ) || exit 1 |
||||
|
|
||||
|
$(BUILD_DIR)/%.d: $(BUILD_DIR) %.c |
||||
|
$(Q)echo " [DEP] $@" |
||||
|
$(Q)touch $@ |
||||
|
$(Q)echo -n "$@ $(patsubst %.d,%.o,$@):" >$@ |
||||
|
$(Q)$(CC) -M $(CFLAGS) $(filter %.cpp,$^ ) | sed 's:$*.o\:::' >> $@ |
||||
|
|
||||
|
$(BUILD_DIR)/%.d: $(BUILD_DIR) %.cpp |
||||
|
$(Q)echo " [DEP] $@" |
||||
|
$(Q)touch $@ |
||||
|
$(Q)echo -n "$@ $(patsubst %.d,%.o,$@):" >$@ |
||||
|
$(Q)$(CC) -M $(filter-out -g -o0 -o1 -o2 ,$(CPPFLAGS)) $(filter %.cpp,$^) | sed 's:$*.o\:::' >> $@ |
||||
|
|
||||
|
-include $(DEPS) |
@ -0,0 +1,14 @@ |
|||||
|
#ifndef POINT_H |
||||
|
#define POINT_H |
||||
|
|
||||
|
class Point { |
||||
|
public: |
||||
|
|
||||
|
Point (int x=0, int y=0) { |
||||
|
this->x = x; |
||||
|
this->y = y; |
||||
|
} |
||||
|
|
||||
|
int x, y; |
||||
|
}; |
||||
|
#endif // POINT_H |
@ -0,0 +1,417 @@ |
|||||
|
#include "SocketObject.h"
|
||||
|
|
||||
|
#include <stdio.h>
|
||||
|
#include <stdlib.h>
|
||||
|
#include <string.h>
|
||||
|
#include <iostream>
|
||||
|
#include <cerrno>
|
||||
|
#include <iomanip>
|
||||
|
|
||||
|
using namespace std; |
||||
|
|
||||
|
#if defined(__msdos__) || defined(WIN32)
|
||||
|
SocketObject::SocketObject(void) |
||||
|
{ |
||||
|
#ifdef __SOCKET_OBJECT_DEBUG
|
||||
|
cout << "Windows SocketObject Konstruktor" << endl; |
||||
|
#endif
|
||||
|
WSADATA wsaData; |
||||
|
WORD wVersionRequested; |
||||
|
|
||||
|
wVersionRequested = MAKEWORD( 2, 0 ); |
||||
|
_skSocket = INVALID_SOCKET; |
||||
|
WSAStartup(wVersionRequested, &wsaData); |
||||
|
} |
||||
|
|
||||
|
SocketObject::SocketObject(SocketObject& sk) |
||||
|
{ |
||||
|
WSADATA wsaData; |
||||
|
WORD wVersionRequested; |
||||
|
|
||||
|
wVersionRequested = MAKEWORD( 2, 0 ); |
||||
|
_skSocket = sk._skSocket; |
||||
|
sk._skSocket = INVALID_SOCKET; |
||||
|
WSAStartup(wVersionRequested, &wsaData); |
||||
|
} |
||||
|
|
||||
|
SocketObject::~SocketObject(void) |
||||
|
{ |
||||
|
Disconnect(); |
||||
|
} |
||||
|
#endif
|
||||
|
|
||||
|
|
||||
|
void SocketObject::setBlockingMode(bool nonblock) |
||||
|
{ |
||||
|
int errorCode = 0; |
||||
|
#if defined(__msdos__) || defined(WIN32)
|
||||
|
u_long iMode = 1; |
||||
|
|
||||
|
if (!nonblock) |
||||
|
iMode=0; |
||||
|
|
||||
|
if (0 != ioctlsocket(_skSocket, FIONBIO, &iMode)) |
||||
|
{ |
||||
|
errorCode = WSAGetLastError(); |
||||
|
cout << "Set blocking mode ("<<iMode<<") failed! Errorcode "<< errorCode; |
||||
|
} |
||||
|
#else
|
||||
|
//CHANGED: Use the boolean value
|
||||
|
if (nonblock) |
||||
|
fcntl(_skSocket, F_SETFL, O_NONBLOCK); |
||||
|
#endif
|
||||
|
} |
||||
|
|
||||
|
|
||||
|
int SocketObject::Bind(unsigned short int iPort) |
||||
|
{ |
||||
|
#if defined(__msdos__) || defined(WIN32)
|
||||
|
|
||||
|
struct sockaddr_in saServerAddress; |
||||
|
// TCP-Socket erschaffen
|
||||
|
_skSocket = socket(AF_INET, SOCK_STREAM, 0); |
||||
|
if (_skSocket == INVALID_SOCKET) |
||||
|
{ |
||||
|
#ifdef __SOCKET_OBJECT_DEBUG
|
||||
|
cout << "SocketObject::Bind(): INVALID SOCKET" << endl; |
||||
|
#endif
|
||||
|
return 0; |
||||
|
} |
||||
|
// serverAdress wählen
|
||||
|
memset(&saServerAddress, 0, sizeof(sockaddr_in)); |
||||
|
saServerAddress.sin_family = AF_INET; |
||||
|
saServerAddress.sin_addr.s_addr = htonl(INADDR_ANY); |
||||
|
saServerAddress.sin_port = htons(iPort); |
||||
|
|
||||
|
if ( bind(_skSocket, (sockaddr*)&saServerAddress, sizeof(sockaddr))== SOCKET_ERROR) |
||||
|
{ |
||||
|
Disconnect(); |
||||
|
return -1; |
||||
|
} else |
||||
|
{ |
||||
|
#ifdef __SOCKET_OBJECT_DEBUG
|
||||
|
cout << "SocketObject::Bind(): Alles ok" << endl; |
||||
|
#endif
|
||||
|
return 0; |
||||
|
} |
||||
|
|
||||
|
#else
|
||||
|
|
||||
|
struct sockaddr_in saServerAddress; |
||||
|
|
||||
|
#ifdef __SOCKET_OBJECT_DEBUG
|
||||
|
std::cout << "Port: " << iPort << endl; |
||||
|
#endif
|
||||
|
|
||||
|
// Socket erschaffen
|
||||
|
_skSocket = socket(AF_INET, SOCK_STREAM, 0); |
||||
|
if (_skSocket < 0) |
||||
|
{ |
||||
|
#ifdef __SOCKET_OBJECT_DEBUG
|
||||
|
std::cout << "Fehler bei Bind - socket()" << std::endl; |
||||
|
#endif
|
||||
|
return -1; |
||||
|
} |
||||
|
|
||||
|
const int y = 1; |
||||
|
/* Socketoptionen fuer schnelles Verbinden setzen*/ |
||||
|
setsockopt(_skSocket, SOL_SOCKET, SO_REUSEADDR, &y, sizeof(int)); |
||||
|
|
||||
|
/* Initialisieren der aockaddr_in - structure */ |
||||
|
// Server-Adresse mit 0 vorbelegen
|
||||
|
memset(&saServerAddress, 0, sizeof(struct sockaddr_in)); |
||||
|
// Domain
|
||||
|
saServerAddress.sin_family = AF_INET; |
||||
|
// Addresse
|
||||
|
saServerAddress.sin_addr.s_addr = INADDR_ANY; |
||||
|
// Port
|
||||
|
saServerAddress.sin_port = htons( iPort ); |
||||
|
|
||||
|
// Versuch Socket an Port zu binden
|
||||
|
if (0 > bind(_skSocket, (sockaddr*) &saServerAddress, sizeof(sockaddr))) |
||||
|
{ |
||||
|
// Socket will nicht mehr lesen und schreiben
|
||||
|
shutdown(_skSocket,2); |
||||
|
#ifdef __SOCKET_OBJECT_DEBUG
|
||||
|
std::cout << "Fehler bei Bind!" << std::endl; |
||||
|
#endif
|
||||
|
return -1; |
||||
|
} else |
||||
|
{ |
||||
|
return 0; |
||||
|
} |
||||
|
#endif
|
||||
|
} |
||||
|
|
||||
|
|
||||
|
int SocketObject::Listen( void ) |
||||
|
{ |
||||
|
// lauscht bei _skSocket, max Warteschlange = 2
|
||||
|
return listen(_skSocket, 2); |
||||
|
// WIN32 : ,32
|
||||
|
} |
||||
|
|
||||
|
|
||||
|
bool SocketObject::Accept(SocketObject &skAcceptSocket) |
||||
|
{ |
||||
|
struct sockaddr_in saClientAddress; |
||||
|
int iClientSize = sizeof(sockaddr_in); |
||||
|
|
||||
|
#if defined(__msdos__) || defined(WIN32)
|
||||
|
|
||||
|
skAcceptSocket._skSocket = accept(_skSocket, (struct sockaddr*)&saClientAddress, &iClientSize); |
||||
|
return !( skAcceptSocket._skSocket == INVALID_SOCKET); |
||||
|
|
||||
|
#else
|
||||
|
|
||||
|
skAcceptSocket._skSocket = accept( _skSocket, (sockaddr*) &saClientAddress,(socklen_t*) &iClientSize); |
||||
|
return !( skAcceptSocket._skSocket == -1); |
||||
|
|
||||
|
#endif
|
||||
|
} |
||||
|
|
||||
|
|
||||
|
bool SocketObject::Connect(const char* szServerAddress, unsigned short int iPort, bool nonblock) |
||||
|
{ |
||||
|
#if defined(__msdos__) || defined(WIN32)
|
||||
|
|
||||
|
struct sockaddr_in server_addr; |
||||
|
LPHOSTENT lpHost; |
||||
|
int error; |
||||
|
|
||||
|
// Open the socket
|
||||
|
_skSocket = socket(AF_INET, SOCK_STREAM, 0); |
||||
|
if (_skSocket == INVALID_SOCKET) |
||||
|
return false; |
||||
|
|
||||
|
u_long iMode = 0; |
||||
|
if (nonblock) |
||||
|
iMode = 1; |
||||
|
ioctlsocket(_skSocket, FIONBIO, &iMode); |
||||
|
|
||||
|
memset(&server_addr,0,sizeof(struct sockaddr_in)); |
||||
|
server_addr.sin_family = AF_INET; |
||||
|
server_addr.sin_addr.s_addr = inet_addr(szServerAddress); |
||||
|
|
||||
|
if (server_addr.sin_addr.s_addr == INADDR_NONE) |
||||
|
{ |
||||
|
lpHost = gethostbyname(szServerAddress); |
||||
|
if (lpHost != NULL) |
||||
|
{ |
||||
|
server_addr.sin_addr.s_addr = ((LPIN_ADDR)lpHost->h_addr)->s_addr; |
||||
|
} |
||||
|
else |
||||
|
return false; |
||||
|
} |
||||
|
|
||||
|
server_addr.sin_port = htons(iPort); |
||||
|
error = connect(_skSocket, (struct sockaddr*)&server_addr, sizeof(sockaddr)); |
||||
|
if (error == SOCKET_ERROR) |
||||
|
{ |
||||
|
Disconnect(); |
||||
|
return false; |
||||
|
} |
||||
|
return true; |
||||
|
|
||||
|
#else
|
||||
|
|
||||
|
struct sockaddr_in server_addr; |
||||
|
int status; |
||||
|
|
||||
|
// Socket erschaffen
|
||||
|
_skSocket = socket(AF_INET, SOCK_STREAM, 0); |
||||
|
if (_skSocket < 0) |
||||
|
return false; |
||||
|
|
||||
|
if (nonblock) |
||||
|
fcntl(_skSocket, F_SETFL, O_NONBLOCK); |
||||
|
|
||||
|
// Initilisieren der sockaddr_in- Struktur
|
||||
|
memset(&server_addr, 0, sizeof(struct sockaddr_in)); |
||||
|
server_addr.sin_family = AF_INET; |
||||
|
// server-Adresse bergeben
|
||||
|
server_addr.sin_addr.s_addr = inet_addr(szServerAddress); |
||||
|
// std::cout << inet_ntoa (server_addr.sin_addr)<< std::endl;
|
||||
|
// Port
|
||||
|
server_addr.sin_port = htons(iPort); |
||||
|
|
||||
|
// Verbindung herstellen
|
||||
|
status = connect(_skSocket, (struct sockaddr*)&server_addr, sizeof(sockaddr)); |
||||
|
|
||||
|
if (status < 0) |
||||
|
{ |
||||
|
shutdown(_skSocket,2); |
||||
|
return false; |
||||
|
} |
||||
|
return true; |
||||
|
|
||||
|
#endif
|
||||
|
} |
||||
|
|
||||
|
|
||||
|
bool SocketObject::Connect(const string szServerAddress, unsigned short int iPort, bool nonblock) |
||||
|
{ |
||||
|
return Connect((char*) szServerAddress.c_str(), iPort, nonblock); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
void SocketObject::Disconnect() |
||||
|
{ |
||||
|
#if defined(__msdos__) || defined(WIN32)
|
||||
|
if (_skSocket != INVALID_SOCKET) |
||||
|
{ |
||||
|
closesocket(_skSocket); |
||||
|
_skSocket = INVALID_SOCKET; |
||||
|
} |
||||
|
#else
|
||||
|
close(_skSocket); |
||||
|
#endif
|
||||
|
} |
||||
|
|
||||
|
int SocketObject::Recv(char *szBuffer, int iBufferLength, int iFlags) |
||||
|
{ |
||||
|
return recv(_skSocket, szBuffer, iBufferLength, iFlags); |
||||
|
} |
||||
|
|
||||
|
int SocketObject::Recv (string& s) |
||||
|
{ |
||||
|
char buf [MAXRECV+1]; |
||||
|
// cout << WSAGetLastError() << " in SocketObject::Recv, vor recv" << endl;
|
||||
|
s = ""; |
||||
|
memset(buf, 0, MAXRECV+1); |
||||
|
int status = Recv(buf, MAXRECV, 0); |
||||
|
|
||||
|
switch (status) |
||||
|
{ |
||||
|
case -1: |
||||
|
#ifdef __SOCKET_OBJECT_DEBUG
|
||||
|
cout << "status: -1 errno: " << errno << " in SocketObject::Recv" << endl; |
||||
|
#endif
|
||||
|
break; |
||||
|
case 0: |
||||
|
break; |
||||
|
|
||||
|
default: |
||||
|
s = buf; |
||||
|
// strip the (expected) CRLF
|
||||
|
if(s.length() == 1) |
||||
|
{ |
||||
|
if(s[s.length()-1]=='\n' || s[s.length()-1]=='\r') |
||||
|
s.resize(s.length()-1); |
||||
|
} else if(s.length() >= 2) |
||||
|
{ |
||||
|
if(s[s.length()-1]=='\n' && s[s.length()-2]=='\r') |
||||
|
s.resize(s.length()-2); |
||||
|
else if(s[s.length()-1]=='\n' || s[s.length()-1]=='\r') |
||||
|
s.resize(s.length()-1); |
||||
|
} |
||||
|
break; |
||||
|
} |
||||
|
return status; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
int SocketObject::receiveLine(char* array, int arraySize) |
||||
|
{ |
||||
|
//std::string ret;
|
||||
|
char r; |
||||
|
int pos = 0; |
||||
|
|
||||
|
while (pos<arraySize-2) |
||||
|
{ |
||||
|
switch(recv(_skSocket, &r, 1, 0)) |
||||
|
{ |
||||
|
case 0: // not connected anymore;
|
||||
|
return 0; |
||||
|
case -1: |
||||
|
return -1; |
||||
|
} |
||||
|
|
||||
|
// check for carriage return or line feed (MAC: CR, Linux: LF, Windows: CRLF)
|
||||
|
if ((r == char(13)) || (r == char(10))) |
||||
|
{ |
||||
|
if (pos > 0) |
||||
|
{ |
||||
|
array[pos]='\0'; |
||||
|
return pos; |
||||
|
} |
||||
|
}else |
||||
|
{ |
||||
|
array[pos] = r; |
||||
|
pos++; |
||||
|
} |
||||
|
} |
||||
|
return pos; |
||||
|
} |
||||
|
|
||||
|
std::string SocketObject::receiveLine() |
||||
|
{ |
||||
|
std::string ret; |
||||
|
char r; |
||||
|
|
||||
|
while (1) |
||||
|
{ |
||||
|
//This will not work under windows if the blocking mode is non-blocking
|
||||
|
// -1 will indicate that there is no value, it is not an error !!!
|
||||
|
//http://msdn.microsoft.com/en-us/library/ms740121(VS.85).aspx
|
||||
|
//For linux see:
|
||||
|
//http://linux.about.com/library/cmd/blcmdl2_recv.htm
|
||||
|
//If no messages are available at the socket, the receive calls wait for a message to arrive,
|
||||
|
//unless the socket is nonblocking (see fcntl(2)) in which case the value -1 is returned and
|
||||
|
// the external variable errno set to EAGAIN.
|
||||
|
switch(recv(_skSocket, &r, 1, 0)) |
||||
|
{ |
||||
|
case 0: // not connected anymore;
|
||||
|
return SOCKETOBJECT_NOT_CONNECTED; |
||||
|
case -1: // error
|
||||
|
return SOCKETOBJECT_RECV_ERROR; |
||||
|
} |
||||
|
|
||||
|
// check for carriage return or line feed (MAC: CR, Linux: LF, Windows: CRLF)
|
||||
|
if ((r == char(13)) || (r == char(10))) |
||||
|
{ |
||||
|
if (ret.length() > 0) |
||||
|
return ret; |
||||
|
} else |
||||
|
{ |
||||
|
ret += r; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
int SocketObject::Send(const char *szBuffer, int iBufferLength, int iFlags) |
||||
|
{ |
||||
|
return send(_skSocket,szBuffer,iBufferLength, iFlags); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
int SocketObject::Send (const string s) |
||||
|
{ |
||||
|
string str = s; |
||||
|
// add the (expected) CRLF
|
||||
|
if(str == "") |
||||
|
{ |
||||
|
str = "\n\r"; |
||||
|
} else if(str.size() == 1) |
||||
|
{ |
||||
|
if(str[0] == '\r') |
||||
|
{ |
||||
|
str = "\n\r"; |
||||
|
} else if(str[0] != '\n') |
||||
|
{ |
||||
|
str += "\n\r"; |
||||
|
} |
||||
|
} else if(str.size() >= 2) |
||||
|
{ |
||||
|
if(str[str.length()-1] != '\n' || str[str.length()-2]!='\r') |
||||
|
{ |
||||
|
str += "\n\r"; |
||||
|
} |
||||
|
} |
||||
|
#if defined(__msdos__) || defined(WIN32)
|
||||
|
return Send((char*) str.c_str(), (int) str.size(), 0); |
||||
|
#else
|
||||
|
return Send((char*) str.c_str(), (int) str.size(), (int) MSG_NOSIGNAL); |
||||
|
#endif
|
||||
|
} |
||||
|
|
@ -0,0 +1,172 @@ |
|||||
|
/** \class SocketObject |
||||
|
* |
||||
|
* \brief Die Klasse SocketObject kapselt die Verwendung von Sockets |
||||
|
* |
||||
|
* Die Klasse SocketObject liefert eine komfortable Benutzungs-Schnittstelle |
||||
|
* für Sockets. |
||||
|
* Sie bietet Methoden zum Senden und Empfangen von verschiedenen Datentypen, |
||||
|
* sowie Methoden zum Verbindungsauf- und abbau. |
||||
|
*/ |
||||
|
#ifndef _SOCKETOBJECT_H |
||||
|
#define _SOCKETOBJECT_H |
||||
|
|
||||
|
#if (defined(__msdos__) || defined(WIN32)) |
||||
|
#include <winsock.h> |
||||
|
#else |
||||
|
#include <sys/types.h> |
||||
|
#include <sys/socket.h> |
||||
|
#include <netinet/in.h> |
||||
|
#include <arpa/inet.h> |
||||
|
#include <netdb.h> |
||||
|
#include <fcntl.h> |
||||
|
#include <unistd.h> |
||||
|
#endif |
||||
|
|
||||
|
#include <string> |
||||
|
#include <sstream> |
||||
|
#include <vector> |
||||
|
|
||||
|
|
||||
|
#define SOCKETOBJECT_NOT_CONNECTED "SOCKETOBJECT_NOT_CONNECTED" |
||||
|
#define SOCKETOBJECT_RECV_ERROR "SOCKETOBJECT_RECV_ERROR" |
||||
|
|
||||
|
class SocketObject { |
||||
|
|
||||
|
public: |
||||
|
|
||||
|
static const int MAXRECV = 1024; |
||||
|
|
||||
|
|
||||
|
private: |
||||
|
|
||||
|
#if defined(__msdos__) || defined(WIN32) |
||||
|
SOCKET _skSocket; |
||||
|
#else |
||||
|
int _skSocket; |
||||
|
#endif |
||||
|
|
||||
|
|
||||
|
|
||||
|
public: |
||||
|
|
||||
|
#if defined(__msdos__) || defined(WIN32) |
||||
|
// Konstruktor der Klasse |
||||
|
SocketObject(); |
||||
|
|
||||
|
// Copy-Konstruktor |
||||
|
SocketObject(SocketObject& sk); |
||||
|
|
||||
|
// Destruktor der Klasse |
||||
|
~SocketObject(); |
||||
|
#endif |
||||
|
|
||||
|
/****** NUR SERVER - METHODEN ******/ |
||||
|
|
||||
|
/** \brief Bindet Socket an einen Port |
||||
|
* |
||||
|
* Die bind()-Methdode gibt dem Socket einen |
||||
|
* lokalen Namen, damit andere Prozesse mit |
||||
|
* ihm kommunizieren können. |
||||
|
* Wird <b>nur vom Server</b> benutzt! |
||||
|
* |
||||
|
* @param iPort Port an den gebunden werden soll |
||||
|
* |
||||
|
* @return 0 = ok, SOCKET_ERROR = Fehler |
||||
|
* |
||||
|
*/ |
||||
|
int Bind(unsigned short int iPort); |
||||
|
|
||||
|
/** \brief Wartet auf eigehende Verbindungsanfragen |
||||
|
* |
||||
|
* Die Listen()-Methode erwartet eingehende |
||||
|
* Verbindungsanfragen. |
||||
|
* Wird <b>nur vom Server</b> benutzt! |
||||
|
* |
||||
|
* @return 0 = ok, SOCKET_ERROR = Fehler |
||||
|
* |
||||
|
*/ |
||||
|
int Listen(); |
||||
|
|
||||
|
/** \brief Acceptiert eingehende Verbindungsanfrage |
||||
|
* |
||||
|
* Die accept()-Methode akzeptiert eine eingehende |
||||
|
* Verbindung und "startet" die Verbindung" |
||||
|
* Wird <b>nur vom Server</b> benutzt! |
||||
|
* |
||||
|
* @param skAcceptSocket zu akzeptierender Socket |
||||
|
*/ |
||||
|
bool Accept(SocketObject &skAcceptSocket); |
||||
|
|
||||
|
/****** SERVER - METHODEN ENDE ******/ |
||||
|
|
||||
|
/****** NUR CLIENT - METHODEN ******/ |
||||
|
/** \brief Stellt Verbindsanfage an den Server |
||||
|
* |
||||
|
* Mittels der connect()-Methode stellt der Client |
||||
|
* eine Verbindungsanfrage an den Server her, der |
||||
|
* |
||||
|
* |
||||
|
* Wird <b>nur vom Client</b> benutzt! |
||||
|
* |
||||
|
* @param szServerAdrress Adresse des Servers |
||||
|
* @param iPort Port des Server |
||||
|
*/ |
||||
|
bool Connect(const char *szServerAddress, unsigned short int iPort, bool nonblock); |
||||
|
|
||||
|
/** \brief Stellt Verbindsanfage an den Server |
||||
|
* |
||||
|
* Mittels der connect()-Methode stellt der Client |
||||
|
* eine Verbindungsanfrage an den Server her, der |
||||
|
* Die IP wird hier als String übergeben |
||||
|
* Wird <b>nur vom Client</b> benutzt! |
||||
|
* |
||||
|
* @param ServerAdrress Adresse des Servers |
||||
|
* @param iPort Port des Server |
||||
|
*/ |
||||
|
bool Connect(const std::string ServerAddress, unsigned short int iPort, bool nonblock = false); |
||||
|
|
||||
|
void setBlockingMode(bool nonblock); |
||||
|
|
||||
|
std::string receiveLine(); |
||||
|
int receiveLine(char* array, int arraySize); |
||||
|
|
||||
|
/****** CLIENT - METHODEN ENDE ******/ |
||||
|
/** |
||||
|
* Die send()-Methode sendet Daten an den verbundenen |
||||
|
* Socket |
||||
|
* |
||||
|
* @param szBuffer zu sendende Nachricht |
||||
|
* @param iBufferLength Läge der Nachricht |
||||
|
* @param iFlags Flags |
||||
|
* |
||||
|
* @return Anzahl der gesendeten Bytes |
||||
|
*/ |
||||
|
int Send(const char *szBuffer, int iBufferLength, int iFlags); |
||||
|
|
||||
|
/** \brief Senden eines Strings |
||||
|
* |
||||
|
* Die Methode sendet einen String an den Kommunikationspartner |
||||
|
* |
||||
|
* @param toSend String, der gesendet werden soll |
||||
|
* |
||||
|
* @return Anzahl der gesendeten Bytes |
||||
|
*/ |
||||
|
int Send(const std::string toSend); |
||||
|
|
||||
|
/** \brief Empfängt Characters |
||||
|
* |
||||
|
* @param szBuffer hier wird die Nachricht reingeschrieben |
||||
|
* @param iBufferLength max. Läge der Nachricht |
||||
|
* @param iFlags Flags |
||||
|
* |
||||
|
* @return Anzahl der gesendeten Bytes |
||||
|
*/ |
||||
|
int Recv(char *szBuffer, int iBufferLength, int iFlags); |
||||
|
int Recv (std::string& s); |
||||
|
|
||||
|
void Disconnect(); |
||||
|
|
||||
|
|
||||
|
}; |
||||
|
|
||||
|
#endif |
@ -0,0 +1,36 @@ |
|||||
|
#include "header.h"
|
||||
|
|
||||
|
void StringTool::String2CmdArg(string s, string & cmd, string & arg) |
||||
|
{ |
||||
|
string message = stripWhiteSpace(s); |
||||
|
if (message.find_first_of(STRING_WHITESPACES, 1) != string::npos) |
||||
|
{ |
||||
|
cmd = stripWhiteSpace(message.substr(0, message.find_first_of(STRING_WHITESPACES, 1))); |
||||
|
arg = stripWhiteSpace(message.substr(message.find_first_of(STRING_WHITESPACES, 1))); |
||||
|
} else |
||||
|
{ |
||||
|
cmd = message; |
||||
|
arg = ""; |
||||
|
} |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
string StringTool::stripWhiteSpace(string s) |
||||
|
{ |
||||
|
unsigned int i, j; |
||||
|
if (s.length() > 0) |
||||
|
{ |
||||
|
i = s.find_first_not_of(STRING_WHITESPACES); |
||||
|
j = s.find_last_not_of(STRING_WHITESPACES); |
||||
|
|
||||
|
if (i == string::npos) |
||||
|
i = 0; |
||||
|
if (j == string::npos) |
||||
|
j = s.length()-1; |
||||
|
|
||||
|
return string(s, i, j-i+1); |
||||
|
} |
||||
|
return string(""); |
||||
|
} |
||||
|
|
||||
|
|
@ -0,0 +1,13 @@ |
|||||
|
#include <string> |
||||
|
|
||||
|
#ifndef STRING_TOOL |
||||
|
#define STRING_TOOL |
||||
|
|
||||
|
class StringTool |
||||
|
{ |
||||
|
private: |
||||
|
public: |
||||
|
void String2CmdArg(std::string s, std::string & cmd, std::string & arg); |
||||
|
std::string stripWhiteSpace(std::string s); |
||||
|
}; |
||||
|
#endif |
1079
lwrserv/SvrHandling.cpp
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
@ -0,0 +1,61 @@ |
|||||
|
#include "defines.h" |
||||
|
#include "StringTool.h" |
||||
|
#include <string> |
||||
|
#include "friremote.h" |
||||
|
|
||||
|
#ifndef SVR_HANDLING |
||||
|
#define SVR_HANDLING |
||||
|
|
||||
|
// Serve status |
||||
|
typedef enum {waiting, handshake, accepted, done} svr_state; |
||||
|
|
||||
|
class SvrHandling : private StringTool |
||||
|
{ |
||||
|
private: |
||||
|
svr_state c_state; |
||||
|
//Handshake |
||||
|
bool handshakeAccepted(SocketObject& client); |
||||
|
//Handle client |
||||
|
void handle(SocketObject& client); |
||||
|
//Handling request for current Joint Values |
||||
|
void GetPositionJoints(SocketObject& client); |
||||
|
//Get Position as POSE Matrix |
||||
|
void GetPositionHomRowWise(SocketObject& client); |
||||
|
//Get Force/torque values from TCP |
||||
|
void GetForceTorqueTcp(SocketObject& client); |
||||
|
//Move to given Joint combination |
||||
|
void MovePTPJoints(SocketObject& client, std::string& args); |
||||
|
//Move to given POSE position |
||||
|
void MoveHomRowWiseStatus(SocketObject& client, std::string& args); |
||||
|
//Set Velocity |
||||
|
void SetSpeed(SocketObject& client, std::string& args); |
||||
|
//Set Acceleration |
||||
|
void SetAccel(SocketObject& client, std::string& args); |
||||
|
//Starting Potential Field Movement Mode |
||||
|
void StartPotFieldMode(SocketObject& client, std::string& args); |
||||
|
//Stopping Potential Field Movement Mode |
||||
|
void StopPotFieldMode(SocketObject& client, std::string& args); |
||||
|
//Setting Target Position HomRowWise for Potential Move |
||||
|
void SetPos(SocketObject& client, std::string& args); |
||||
|
//Setting Target Position as Joints for Potential Move |
||||
|
void SetJoints(SocketObject& client, std::string& args); |
||||
|
//Cartesian Movement |
||||
|
//Move to given POSE position |
||||
|
void MoveCartesian(SocketObject& client, std::string& args); |
||||
|
//Do Ultrasound |
||||
|
void DoUltrasound(SocketObject& client, std::string& args); |
||||
|
//Quit |
||||
|
void quit(SocketObject& client); |
||||
|
//DEBUGGING |
||||
|
void debug(SocketObject& client); |
||||
|
public: |
||||
|
//Constructor |
||||
|
SvrHandling(); |
||||
|
//Destructor |
||||
|
virtual ~SvrHandling(); |
||||
|
//Rund server @port |
||||
|
void run(int port); |
||||
|
//Get current timestamp |
||||
|
std::string timestamp(); |
||||
|
}; |
||||
|
#endif |
@ -0,0 +1,38 @@ |
|||||
|
|
||||
|
#ifndef __DEFINES_H__ |
||||
|
#define __DEFINES_H__ |
||||
|
|
||||
|
#define SVR_NAME "lwrsvr 4.11d" |
||||
|
#define SVR_DEFAULT_PORT 8000 |
||||
|
#define SVR_HANDSHAKE "Hello Robot" |
||||
|
#define SVR_HELLO_MSG std::string("welcome to ") + SVR_NAME + ("!") |
||||
|
#define SVR_ACCEPTED std::string("accepted") |
||||
|
#define SVR_FAILED std::string("Failed.") |
||||
|
#define STRING_WHITESPACES " \t\r\n" |
||||
|
#define SVR_TRUE_RSP "true" |
||||
|
#define SVR_FALSE_RSP "false" |
||||
|
#define M_PI 3.141592654f |
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
|
//Begin SVR_COMMANDS |
||||
|
#define CMD_GetPositionJoints "GPJ" |
||||
|
#define CMD_GetPositionHomRowWise "GPHRW" |
||||
|
#define CMD_GetForceTorqueTcp "GFT" |
||||
|
#define CMD_MovePTPJoints "MPTPJ" |
||||
|
#define CMD_MoveHomRowWiseStatus "MHRWS" |
||||
|
#define CMD_SetSpeed "SS" |
||||
|
#define CMD_SetAccel "SA" |
||||
|
#define CMD_StartPotFieldMode "STPF" |
||||
|
#define CMD_StopPotFieldMode "SPPF" |
||||
|
#define CMD_SetPos "SP" |
||||
|
#define CMD_SetJoints "SJ" |
||||
|
#define CMD_QUIT "Quit" |
||||
|
#define CMD_ISKUKA "IsKukaLWR" |
||||
|
#define CMD_MoveCartesian "MC" |
||||
|
#define CMD_DoUltrasound "DU" |
||||
|
//End SVR_COMMANDS |
||||
|
|
||||
|
#endif /* __DEFINES_H__ */ |
||||
|
|
@ -0,0 +1,504 @@ |
|||||
|
/*{{[PH] |
||||
|
**************************************************************************** |
||||
|
Project: FRI |
||||
|
|
||||
|
This material is the exclusive property of KUKA Roboter GmbH |
||||
|
and must be returned to KUKA Roboter GmbH immediately upon |
||||
|
request. This material and the information illustrated or |
||||
|
contained herein may not be used, reproduced, stored in a |
||||
|
retrieval system, or transmitted in whole or in part in any |
||||
|
way - electronic, mechanical, photocopying, recording, or |
||||
|
otherwise, without the prior written consent of KUKA Roboter GmbH. |
||||
|
|
||||
|
All Rights Reserved |
||||
|
Copyright (C) 2009 |
||||
|
KUKA Roboter GmbH |
||||
|
Augsburg, Germany |
||||
|
|
||||
|
[PH]}} |
||||
|
*/ |
||||
|
|
||||
|
/* |
||||
|
{{[FH] |
||||
|
**************************************************************************** |
||||
|
friComm.h |
||||
|
|
||||
|
NOTE: FRI (Fast Research inteface) is subject to radical change |
||||
|
|
||||
|
|
||||
|
[FH]}} |
||||
|
*/ |
||||
|
/** |
||||
|
\author (Andreas Stemmer,DLR) |
||||
|
\author (Guenter Schreiber,KUKA) |
||||
|
\file |
||||
|
\brief This header file describes the basic communcation structures for |
||||
|
the FastRobotInterface |
||||
|
|
||||
|
|
||||
|
- all data is transmitted in Intel byte order (little endian) |
||||
|
- structs use 4 byte padding |
||||
|
- all floats are IEEE 754 single precision floats with 4 bytes |
||||
|
- for the sequence counters in the header, the number following |
||||
|
#FRI_UINT16_MAX is assumed to be zero (normal integer overflow) |
||||
|
- For Checking, that your compiler setup interprets the binary communication as expceted, |
||||
|
use the macros #FRI_CHECK_SIZES_OK, #FRI_PREPARE_CHECK_BYTE_ORDER, #FRI_CHECK_BYTE_ORDER_OK in your code. |
||||
|
|
||||
|
*/ |
||||
|
/***************************************************************************** |
||||
|
|
||||
|
friComm.h |
||||
|
|
||||
|
created: 09/05/26 by Andreas Stemmer |
||||
|
|
||||
|
$Revision: 1.17 $ $Author: stemmer $ $Date: 2010/02/12 15:15:18 $ |
||||
|
|
||||
|
(C) by Institute of Robotics and Mechatronics, DLR |
||||
|
|
||||
|
Description: |
||||
|
|
||||
|
This header file describes the basic communcation structures for |
||||
|
the FastRobotInterface |
||||
|
|
||||
|
Note: |
||||
|
|
||||
|
|
||||
|
|
||||
|
*****************************************************************************/ |
||||
|
|
||||
|
#ifndef FRICOMM_H |
||||
|
#define FRICOMM_H |
||||
|
|
||||
|
|
||||
|
#define LBR_MNJ 7 /*!< Number of Managed Joints for Light Weight Robot */ |
||||
|
#define FRI_USER_SIZE 16 /*!< Number of Userdefined data, which are exchanged to KRL Interpreter */ |
||||
|
#define FRI_CART_FRM_DIM 12 /*!< Number of data within a 3x4 Cartesian frame - homogenous matrix */ |
||||
|
#define FRI_CART_VEC 6 /*!< Number of data for a Cartesian vector */ |
||||
|
|
||||
|
|
||||
|
typedef unsigned char fri_uint8_t; /*!< 1 byte unsigned */ |
||||
|
typedef unsigned short fri_uint16_t; /*!< 2 byte unsigned */ |
||||
|
typedef unsigned int fri_uint32_t; /*!< 4 byte unsigned */ |
||||
|
typedef int fri_int32_t; /*!< 4 byte signed */ |
||||
|
typedef float fri_float_t; /*!< 4 byte IEEE 754 float */ |
||||
|
#define FRI_UINT16_MAX ((1<<16) - 1) /*!< Biggest UINT16 w.r.t the interface - porting isno fun */ |
||||
|
|
||||
|
|
||||
|
/** header data used in every packet in both directions |
||||
|
* |
||||
|
* */ |
||||
|
typedef struct |
||||
|
{ |
||||
|
/** sequence counter (increasing with every packet) of the sender |
||||
|
Used for detecting packet loss of UDP Transfer, |
||||
|
put in your code s.th. like |
||||
|
* fri_uint16_t seqCount; |
||||
|
* seqCount++; |
||||
|
* cmd.head.sendSeqCount=seqCount; |
||||
|
*/ |
||||
|
fri_uint16_t sendSeqCount; |
||||
|
|
||||
|
/** reflected sequence counter (mirrored from last received packet) |
||||
|
Used for detecting packet loss of UDP transfer and latency statistics |
||||
|
\sa tFriIntfStatistics |
||||
|
* remote side: put s.th. like |
||||
|
* cmd.head.reflSeqCount=msr.head.sendSeqCount; |
||||
|
*/ |
||||
|
fri_uint16_t reflSeqCount; |
||||
|
|
||||
|
/** overall packet size |
||||
|
Remote side: FRI_CMD_DATA_SIZE |
||||
|
*/ |
||||
|
fri_uint16_t packetSize; |
||||
|
|
||||
|
/** unique datagram id to detect version problems etc. |
||||
|
Remote side: FRI_DATAGRAM_ID_CMD |
||||
|
*/ |
||||
|
fri_uint16_t datagramId; |
||||
|
} tFriHeader; |
||||
|
#define FRI_HEADER_SIZE 8 |
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
|
/** data for direct interaction with KRL */ |
||||
|
typedef struct |
||||
|
{ |
||||
|
/** 16 float values (corresponds to $FRI_TO_REA[] and $FRI_FRM_REA[]) */ |
||||
|
fri_float_t realData[FRI_USER_SIZE]; |
||||
|
|
||||
|
/** 16 int values (corresponds to $FRI_TO_INT[] and $FRI_FRM_INT[]) */ |
||||
|
fri_int32_t intData[FRI_USER_SIZE]; |
||||
|
|
||||
|
/** 16 bool values, stored in one int */ |
||||
|
fri_uint16_t boolData; |
||||
|
|
||||
|
/** manual padding to a multiple of 4 bytes */ |
||||
|
fri_uint16_t fill; |
||||
|
} tFriKrlData; |
||||
|
#define FRI_KRL_DATA_SIZE 132 |
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
|
/** reported communication statistics (average rating over the last |
||||
|
100 packets) */ |
||||
|
typedef struct |
||||
|
{ |
||||
|
/** avg. answer rate (should be close to 1) */ |
||||
|
fri_float_t answerRate; |
||||
|
|
||||
|
/** avg. latency in seconds (should be as small as possible) */ |
||||
|
fri_float_t latency; |
||||
|
|
||||
|
/** avg. jitter in seconds (should be as small as possible) */ |
||||
|
fri_float_t jitter; |
||||
|
|
||||
|
/** avg. missing answer packets (should be as small as possible) */ |
||||
|
fri_float_t missRate; |
||||
|
|
||||
|
/** absolute missing answer packets */ |
||||
|
fri_uint32_t missCounter; |
||||
|
} tFriIntfStatistics; |
||||
|
#define FRI_INTF_STATISTICS_SIZE 20 |
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
|
/** feedback about the interface itself */ |
||||
|
typedef struct |
||||
|
{ |
||||
|
/** current system time in seconds */ |
||||
|
fri_float_t timestamp; |
||||
|
|
||||
|
/** state of interface (monitor or command FRI_STATE) */ |
||||
|
fri_uint16_t state; |
||||
|
|
||||
|
/** quality of communication (FRI_QUALITY) */ |
||||
|
fri_uint16_t quality; |
||||
|
|
||||
|
/** configured sample time for sent measurment packets */ |
||||
|
fri_float_t desiredMsrSampleTime; |
||||
|
|
||||
|
/** configured sample time for received command packets */ |
||||
|
fri_float_t desiredCmdSampleTime; |
||||
|
|
||||
|
/** configured safety limits */ |
||||
|
fri_float_t safetyLimits; |
||||
|
|
||||
|
/** communication statistics */ |
||||
|
tFriIntfStatistics stat; |
||||
|
} tFriIntfState; |
||||
|
#define FRI_INTF_STATE_SIZE (20 + FRI_INTF_STATISTICS_SIZE) |
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
|
/** these are the states that are reported */ |
||||
|
typedef enum |
||||
|
{ |
||||
|
FRI_STATE_INVALID =-1, /**< State invalid e.g. not initialized */ |
||||
|
FRI_STATE_OFF = 0, /**< internal state only (no active interface) */ |
||||
|
FRI_STATE_MON = 1, /**< FRI is in monitor mode */ |
||||
|
FRI_STATE_CMD = 2 /**< FRI is in command mode */ |
||||
|
} FRI_STATE; |
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
|
/** quality of the connection is classified in four steps */ |
||||
|
typedef enum |
||||
|
{ |
||||
|
FRI_QUALITY_INVALID =-1, /**< not allowed, since improber initialized */ |
||||
|
FRI_QUALITY_UNACCEPTABLE = 0, /**< commanding is not allowed */ |
||||
|
FRI_QUALITY_BAD = 1, /**< commanding is allowed */ |
||||
|
FRI_QUALITY_OK = 2, /**< commanding is allowed */ |
||||
|
FRI_QUALITY_PERFECT = 3 /**< commanding is allowed */ |
||||
|
} FRI_QUALITY; |
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
|
/** currently active controller */ |
||||
|
typedef enum |
||||
|
{ |
||||
|
/** only joint position can be commanded */ |
||||
|
FRI_CTRL_POSITION = 1, |
||||
|
/** joint/cart positions, joint/cart stiffness, joint/cart damping |
||||
|
and additional TCP F/T can be commanded */ |
||||
|
FRI_CTRL_CART_IMP = 2, |
||||
|
/** joint positions, stiffness and damping and additional joint |
||||
|
torques can be commanded */ |
||||
|
FRI_CTRL_JNT_IMP = 3, |
||||
|
/** for all the other modes... */ |
||||
|
FRI_CTRL_OTHER = 0 |
||||
|
} FRI_CTRL; |
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
|
/** feedback about the robot */ |
||||
|
typedef struct |
||||
|
{ |
||||
|
/** power state of drives (bitfield) */ |
||||
|
fri_uint16_t power; |
||||
|
|
||||
|
/** selected control strategy (FRI_CTRL) */ |
||||
|
fri_uint16_t control; |
||||
|
|
||||
|
/** drive errors (leads to power off) */ |
||||
|
fri_uint16_t error; |
||||
|
|
||||
|
/** drive warnings */ |
||||
|
fri_uint16_t warning; |
||||
|
|
||||
|
/** temperature of drives */ |
||||
|
fri_float_t temperature[LBR_MNJ]; |
||||
|
} tFriRobotState; |
||||
|
#define FRI_ROBOT_STATE_SIZE 36 |
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
|
/** current robot data */ |
||||
|
typedef struct |
||||
|
{ |
||||
|
/** measured joint angles (in rad) |
||||
|
* KRL: $AXIS_ACT_MSR |
||||
|
* */ |
||||
|
fri_float_t msrJntPos[LBR_MNJ]; |
||||
|
|
||||
|
/** measured Cartesian frame (in m) |
||||
|
* KRL: $POS_ACT_MSR |
||||
|
* Reference: Base and tool are specified by $stiffness.base, $stiffness.tool |
||||
|
* */ |
||||
|
fri_float_t msrCartPos[FRI_CART_FRM_DIM]; |
||||
|
|
||||
|
/** commanded joint angle (in rad, before FRI) |
||||
|
* KRL: $AXIS_ACT_CMD |
||||
|
* */ |
||||
|
fri_float_t cmdJntPos[LBR_MNJ]; |
||||
|
|
||||
|
/** commanded joint offset (in rad, due to FRI) */ |
||||
|
fri_float_t cmdJntPosFriOffset[LBR_MNJ]; |
||||
|
|
||||
|
/** commanded Cartesian frame (in m, before FRI) |
||||
|
* KRL: $POS_ACT_CMD |
||||
|
* Reference: Base and tool are specified by $stiffness.base, $stiffness.tool |
||||
|
* */ |
||||
|
fri_float_t cmdCartPos[FRI_CART_FRM_DIM]; |
||||
|
|
||||
|
/** commanded Cartesian frame (in m, due to FRI) */ |
||||
|
fri_float_t cmdCartPosFriOffset[FRI_CART_FRM_DIM]; |
||||
|
|
||||
|
/** measured joint torque (in Nm) |
||||
|
* KRL $TORQUE_AXIS_ACT |
||||
|
* */ |
||||
|
fri_float_t msrJntTrq[LBR_MNJ]; |
||||
|
|
||||
|
/** estimated external torque (in Nm) |
||||
|
* KRL: $TORQUE_AXIS_EST |
||||
|
* */ |
||||
|
fri_float_t estExtJntTrq[LBR_MNJ]; |
||||
|
|
||||
|
/** estimated TCP force/torque (N, Nm) |
||||
|
KRL: $TORQUE_TCP_EST |
||||
|
- reference frame: $STIFFNESS.TASKFRAME |
||||
|
- Layout: Fx, Fy, Fz, Tz, Ty, Tx |
||||
|
*/ |
||||
|
fri_float_t estExtTcpFT[FRI_CART_VEC]; |
||||
|
|
||||
|
/** Jacobian matrix |
||||
|
* reference frame: $STIFFNESS.TASKFRAME |
||||
|
* row major (#FRI_CART_VEC x #LBR_MNJ) |
||||
|
* You should be able to cast it directly into a C-matrix with the layout of |
||||
|
J[FRI_CART_VEC][LBR_MNJ] |
||||
|
* Or copy it like |
||||
|
for ( int i = 0; i < FRI_CART_VEC; i++) |
||||
|
for ( int j = 0; j < LBR_MNJ; j++) |
||||
|
J[i][j] = jacobian[i*LBR_MNJ+j] |
||||
|
* Interpretation of the colums [ _X_ _Y_ _Z_ _RZ_ _RY_ _RX_] |
||||
|
* The Jacobian is generated by "geometric" reasoning with a corresponding physical |
||||
|
interpretation of instantaneous angular velocity |
||||
|
*/ |
||||
|
fri_float_t jacobian[FRI_CART_VEC*LBR_MNJ]; |
||||
|
|
||||
|
/** mass matrix */ |
||||
|
fri_float_t massMatrix[LBR_MNJ*LBR_MNJ]; |
||||
|
|
||||
|
/** gravity (in m/s^2) */ |
||||
|
fri_float_t gravity[LBR_MNJ]; |
||||
|
} tFriRobotData; |
||||
|
#define FRI_ROBOT_DATA_SIZE (175*4) /**< Binary size of #tFriRobotData */ |
||||
|
|
||||
|
|
||||
|
|
||||
|
/** Identification constant for the structure #tFriMsrData |
||||
|
Note: This datagram id will be abused for versioning as well */ |
||||
|
#define FRI_DATAGRAM_ID_MSR 0x2006 |
||||
|
/** Data that is sent from the KRC to the external controller. |
||||
|
The structure is identified by #FRI_DATAGRAM_ID_MSR |
||||
|
*/ |
||||
|
typedef struct |
||||
|
{ |
||||
|
/** the header */ |
||||
|
tFriHeader head; |
||||
|
|
||||
|
/** data from KRL */ |
||||
|
tFriKrlData krl; |
||||
|
|
||||
|
/** state of interface */ |
||||
|
tFriIntfState intf; |
||||
|
|
||||
|
/** robot state */ |
||||
|
tFriRobotState robot; |
||||
|
|
||||
|
/** robot data */ |
||||
|
tFriRobotData data; |
||||
|
} tFriMsrData; |
||||
|
#define FRI_MSR_DATA_SIZE (FRI_HEADER_SIZE + FRI_KRL_DATA_SIZE + \ |
||||
|
FRI_INTF_STATE_SIZE + FRI_ROBOT_STATE_SIZE + \ |
||||
|
FRI_ROBOT_DATA_SIZE) |
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
|
/** The bitfield is subject to change, any use of hardcoded constants |
||||
|
is NOT RECOMMENDED! Use the provided defines instead! */ |
||||
|
#define FRI_CMD_JNTPOS 0x0001 |
||||
|
// Currently not supported #define FRI_CMD_JNTVEL 0x0002 |
||||
|
#define FRI_CMD_JNTTRQ 0x0004 |
||||
|
#define FRI_CMD_JNTSTIFF 0x0010 |
||||
|
#define FRI_CMD_JNTDAMP 0x0020 |
||||
|
|
||||
|
#define FRI_CMD_CARTPOS 0x0100 |
||||
|
//Currently not supported #define FRI_CMD_CARTVEL 0x0200 |
||||
|
#define FRI_CMD_TCPFT 0x0400 |
||||
|
#define FRI_CMD_CARTSTIFF 0x1000 |
||||
|
#define FRI_CMD_CARTDAMP 0x2000 |
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
|
/** new robot commands */ |
||||
|
typedef struct |
||||
|
{ |
||||
|
/** bitfield which selects which commanded values are relevant */ |
||||
|
fri_uint32_t cmdFlags; |
||||
|
|
||||
|
/** commanded joint angle (in rad) |
||||
|
#FRI_CMD_JNTPOS |
||||
|
*/ |
||||
|
fri_float_t jntPos[LBR_MNJ]; |
||||
|
|
||||
|
/** commanded Cartesian frame (in m) |
||||
|
#FRI_CMD_CARTPOS |
||||
|
*/ |
||||
|
fri_float_t cartPos[FRI_CART_FRM_DIM]; |
||||
|
|
||||
|
/** commanded additional joint torque (in Nm) |
||||
|
#FRI_CMD_JNTTRQ*/ |
||||
|
fri_float_t addJntTrq[LBR_MNJ]; |
||||
|
|
||||
|
/** commanded additional TCP force/torque (N, Nm) |
||||
|
#FRI_CMD_TCPFT |
||||
|
* reference frame: $STIFFNESS.TASKFRAM |
||||
|
* Layout [Fx, Fy, Fz, Tz, Ty, Tx]*/ |
||||
|
fri_float_t addTcpFT[FRI_CART_VEC]; |
||||
|
|
||||
|
/** joint stiffness (Nm/rad) |
||||
|
#FRI_CMD_JNTSTIFF */ |
||||
|
fri_float_t jntStiffness[LBR_MNJ]; |
||||
|
|
||||
|
/** joint damping (normalized) |
||||
|
#FRI_CMD_JNTDAMP*/ |
||||
|
fri_float_t jntDamping[LBR_MNJ]; |
||||
|
|
||||
|
/** Cartesian stiffness (N/m, Nm/rad) |
||||
|
* #FRI_CMD_CARTSTIFF |
||||
|
* Layout [Cx, Cy, Cz, Ca(Rz), Cb(Ry), Cc(Rx)]*/ |
||||
|
fri_float_t cartStiffness[FRI_CART_VEC]; |
||||
|
|
||||
|
/** Cartesian damping (normalized) |
||||
|
* #FRI_CMD_CARTDAMP |
||||
|
* Layout [Dx, Dy, Dz, Da(Rz), Db(Ry), Dc(Rx)]*/ |
||||
|
fri_float_t cartDamping[FRI_CART_VEC]; |
||||
|
} tFriRobotCommand; |
||||
|
#define FRI_ROBOT_COMMAND_SIZE (59*4) |
||||
|
|
||||
|
|
||||
|
|
||||
|
/** Symbolic define to identify #tFriCmdData |
||||
|
Note: This datagram id will be abused for versioning as well */ |
||||
|
#define FRI_DATAGRAM_ID_CMD 0x1005 |
||||
|
/** The commanding structure, which is sent to the KRC Side. |
||||
|
Identified by #FRI_DATAGRAM_ID_CMD */ |
||||
|
typedef struct |
||||
|
{ |
||||
|
/** the header */ |
||||
|
tFriHeader head; |
||||
|
|
||||
|
/** data to KRL */ |
||||
|
tFriKrlData krl; |
||||
|
|
||||
|
/** robot commands */ |
||||
|
tFriRobotCommand cmd; |
||||
|
} tFriCmdData; |
||||
|
#define FRI_CMD_DATA_SIZE (FRI_HEADER_SIZE + FRI_KRL_DATA_SIZE + FRI_ROBOT_COMMAND_SIZE) |
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
|
/** a convenience macro for the user to check if padding on the used |
||||
|
platform is as expected: if (!FRI_CHECK_SIZES_OK) ... */ |
||||
|
#define FRI_CHECK_SIZES_OK \ |
||||
|
((sizeof(tFriHeader) == FRI_HEADER_SIZE) && \ |
||||
|
(sizeof(tFriKrlData) == FRI_KRL_DATA_SIZE) && \ |
||||
|
(sizeof(tFriIntfStatistics) == FRI_INTF_STATISTICS_SIZE) && \ |
||||
|
(sizeof(tFriIntfState) == FRI_INTF_STATE_SIZE) && \ |
||||
|
(sizeof(tFriRobotState) == FRI_ROBOT_STATE_SIZE) && \ |
||||
|
(sizeof(tFriRobotData) == FRI_ROBOT_DATA_SIZE) && \ |
||||
|
(sizeof(tFriRobotCommand) == FRI_ROBOT_COMMAND_SIZE) && \ |
||||
|
(sizeof(tFriMsrData) == FRI_MSR_DATA_SIZE) && \ |
||||
|
(sizeof(tFriCmdData) == FRI_CMD_DATA_SIZE)) |
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
|
/** convenience macros for the user to check if byte order and float |
||||
|
representation on the used platform is as expected: |
||||
|
{ |
||||
|
FRI_PREPARE_CHECK_BYTE_ORDER |
||||
|
if (!FRI_CHECK_BYTE_ORDER_OK) ... |
||||
|
}*/ |
||||
|
#define FRI_PREPARE_CHECK_BYTE_ORDER \ |
||||
|
union {fri_uint32_t a; fri_uint8_t b[4]; fri_float_t c;} _friTestByteOrder; \ |
||||
|
_friTestByteOrder.a = 0x40490FDB; |
||||
|
/** convenience macros for the user to check if byte order and float |
||||
|
representation on the used platform is as expected: |
||||
|
{ |
||||
|
FRI_PREPARE_CHECK_BYTE_ORDER |
||||
|
if (!FRI_CHECK_BYTE_ORDER_OK) ... |
||||
|
}*/ |
||||
|
#define FRI_CHECK_BYTE_ORDER_OK \ |
||||
|
((_friTestByteOrder.a == 0x40490FDB) &&\ |
||||
|
(_friTestByteOrder.b[0] == 0xDB) &&\ |
||||
|
(_friTestByteOrder.b[1] == 0x0F) &&\ |
||||
|
(_friTestByteOrder.b[2] == 0x49) &&\ |
||||
|
(_friTestByteOrder.b[3] == 0x40) &&\ |
||||
|
(_friTestByteOrder.c > 3.141592) &&\ |
||||
|
(_friTestByteOrder.c < 3.141593)) |
||||
|
|
||||
|
|
||||
|
/**! Versioning Major Version */ |
||||
|
#define FRI_MAJOR_VERSION 1 |
||||
|
/**! Versioning Minor sub version for minor fixes */ |
||||
|
#define FRI_SUB_VERSION 0 |
||||
|
#define EXPAND_CONCAT(X1,X2,X3,X4,X5,X6,X7) X1 ## X2 ## X3 ## X4 ## X5 ## X6 ## X7 |
||||
|
#define CONCAT(name1,name2,name3,name4) EXPAND_CONCAT(#name1,".",#name2,".",#name3,".",#name4) |
||||
|
|
||||
|
/**! The Versionstring with all significant information */ |
||||
|
#define FRI_VERSION_STRING CONCAT(FRI_MAJOR_VERSION, FRI_SUB_VERSION,FRI_DATAGRAM_ID_CMD,FRI_DATAGRAM_ID_MSR) |
||||
|
//"." #F "." #FRI_DATAGRAM_ID_MSR |
||||
|
|
||||
|
#endif /* FRICOMM_H */ |
@ -0,0 +1,288 @@ |
|||||
|
/*{{[PH]
|
||||
|
**************************************************************************** |
||||
|
Project: FRI |
||||
|
|
||||
|
This material is the exclusive property of KUKA Roboter GmbH |
||||
|
and must be returned to KUKA Roboter GmbH immediately upon |
||||
|
request. This material and the information illustrated or |
||||
|
contained herein may not be used, reproduced, stored in a |
||||
|
retrieval system, or transmitted in whole or in part in any |
||||
|
way - electronic, mechanical, photocopying, recording, or |
||||
|
otherwise, without the prior written consent of KUKA Roboter GmbH. |
||||
|
|
||||
|
All Rights Reserved |
||||
|
Copyright (C) 2009 |
||||
|
KUKA Roboter GmbH |
||||
|
Augsburg, Germany |
||||
|
|
||||
|
[PH]}} |
||||
|
*/ |
||||
|
|
||||
|
/*
|
||||
|
{{[FH] |
||||
|
**************************************************************************** |
||||
|
friRemote.cpp |
||||
|
|
||||
|
NOTE: This sample, as the corresponding FRI (Fast Research inteface) is subject to radical change |
||||
|
|
||||
|
|
||||
|
[FH]}} |
||||
|
*/ |
||||
|
/**
|
||||
|
\addtogroup friRemoteLib |
||||
|
\brief Library for FRI (FastResearchInterface) |
||||
|
*/ |
||||
|
/* @{ */ |
||||
|
|
||||
|
/** *************************************************************************
|
||||
|
\author (Guenter Schreiber) |
||||
|
\file |
||||
|
\brief FRI Remote class encapsulating UDP package handshakes |
||||
|
* * |
||||
|
***************************************************************************/ |
||||
|
#include "friremote.h"
|
||||
|
|
||||
|
#include <iostream>
|
||||
|
#include <stdlib.h>
|
||||
|
|
||||
|
friRemote::friRemote(int port,char *hintToRemoteHost):remote(port,hintToRemoteHost) |
||||
|
{ |
||||
|
//std::cout << __FUNCTION__ << " " <<port <<std::endl;
|
||||
|
//std::cout << "FRI Version " << FRI_MAJOR_VERSION << "." << FRI_SUB_VERSION << "." <<FRI_DATAGRAM_ID_CMD << "." <<FRI_DATAGRAM_ID_MSR << std::endl;
|
||||
|
memset((void*)(& msr),0x0,sizeof(msr)); |
||||
|
memset((void*)(& cmd), 0x0,sizeof(cmd)); |
||||
|
{ |
||||
|
// do checks, whether the interface - and the host meets the requirements
|
||||
|
FRI_PREPARE_CHECK_BYTE_ORDER; |
||||
|
if (!FRI_CHECK_BYTE_ORDER_OK) |
||||
|
{ |
||||
|
std::cerr << __FUNCTION__<<"Byte order on your system is not appropriate - expect deep trouble" << std::endl; |
||||
|
} |
||||
|
if (!FRI_CHECK_SIZES_OK) |
||||
|
{ |
||||
|
std::cout << __FUNCTION__<<"Sizes of datastructures not appropriate - expect even deeper trouble" << std::endl; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
friRemote::~friRemote() |
||||
|
{ |
||||
|
std::cout << __FUNCTION__ << " bye for now " << std::endl; |
||||
|
} |
||||
|
|
||||
|
int friRemote::doReceiveData() |
||||
|
{ |
||||
|
return remote.Recv(&msr); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
/** Data Exchanger -- normally update within access routine implicitely ... */ |
||||
|
int friRemote::doSendData() |
||||
|
{ |
||||
|
// received at least something
|
||||
|
seqCount++; |
||||
|
cmd.head.sendSeqCount = seqCount; |
||||
|
cmd.head.reflSeqCount = msr.head.sendSeqCount; |
||||
|
cmd.head.datagramId = FRI_DATAGRAM_ID_CMD; |
||||
|
cmd.head.packetSize = sizeof(tFriCmdData); |
||||
|
int rc=remote.Send(&cmd); |
||||
|
return rc; |
||||
|
} |
||||
|
|
||||
|
/** send commands based on last msr datagram and
|
||||
|
receives a new one |
||||
|
*/ |
||||
|
int friRemote::doDataExchange() |
||||
|
{ |
||||
|
doSendData(); |
||||
|
return doReceiveData(); |
||||
|
} |
||||
|
|
||||
|
/** automatically do data exchange, if not otherwise specified */ |
||||
|
int friRemote::doPositionControl(float newJntPosition[LBR_MNJ], bool flagDataExchange) |
||||
|
{ |
||||
|
// Helper, if not properly initialized or the like...
|
||||
|
|
||||
|
cmd.cmd.cmdFlags=FRI_CMD_JNTPOS; |
||||
|
// Note:: If the interface is not in Command mode,
|
||||
|
// The commands have to be "mirrored" to get in sync
|
||||
|
// Note:: If the interface is not in Command mode,
|
||||
|
// The commands have to be "mirrored" to get in sync
|
||||
|
if ((getState() != FRI_STATE_CMD) || (!isPowerOn())) |
||||
|
{ |
||||
|
for (int i = 0; i < LBR_MNJ; i++) |
||||
|
{ |
||||
|
cmd.cmd.jntPos[i]=msr.data.cmdJntPos[i]+msr.data.cmdJntPosFriOffset[i]; |
||||
|
} |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
// compute new values here ...
|
||||
|
for (int i = 0; i < LBR_MNJ; i++) |
||||
|
{ |
||||
|
cmd.cmd.jntPos[i]=newJntPosition[i]; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
if (flagDataExchange) |
||||
|
{ |
||||
|
return doDataExchange(); |
||||
|
} |
||||
|
return 1; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
/** automatically do data exchange, if not otherwise specified
|
||||
|
if flagDataExchange is set to false, call doDataExchange() |
||||
|
or doReceiveData()/doSendData() on your own |
||||
|
IN: newJntPosition - joint positions |
||||
|
newJntStiff - joint stiffness (Spring factor) |
||||
|
newJntDamp - joint damping (Damping factor) |
||||
|
newJntAddTorque - additional torque |
||||
|
|
||||
|
Note: If any of the pointers (newJntPosition, newJntStiff, newJntDamp, newJntAddTorque) is NULL, the |
||||
|
value is ignored -> the respective cmd.cmd.cmdFlags field is set properly |
||||
|
Note: It is possible to change cmd.cmd.cmdFlags in monitor mode only !! |
||||
|
*/ |
||||
|
int friRemote::doJntImpedanceControl(const float newJntPosition[LBR_MNJ], |
||||
|
const float newJntStiff[LBR_MNJ], |
||||
|
const float newJntDamp[LBR_MNJ], |
||||
|
const float newJntAddTorque[LBR_MNJ], |
||||
|
bool flagDataExchange) |
||||
|
|
||||
|
{ |
||||
|
// Helper, if not properly initialized or the like...
|
||||
|
cmd.cmd.cmdFlags=0; |
||||
|
if (newJntPosition) |
||||
|
{ |
||||
|
cmd.cmd.cmdFlags|=FRI_CMD_JNTPOS; |
||||
|
// Note:: If the interface is not in Command mode,
|
||||
|
// The commands have to be "mirrored" to get in sync
|
||||
|
if ((getState() != FRI_STATE_CMD) || (!isPowerOn())) |
||||
|
{ |
||||
|
for (int i = 0; i < LBR_MNJ; i++) |
||||
|
{ |
||||
|
cmd.cmd.jntPos[i]=msr.data.cmdJntPos[i]+msr.data.cmdJntPosFriOffset[i]; |
||||
|
} |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
// compute new values here ...
|
||||
|
for (int i = 0; i < LBR_MNJ; i++) |
||||
|
cmd.cmd.jntPos[i]=newJntPosition[i]; |
||||
|
} |
||||
|
} |
||||
|
if (newJntStiff) |
||||
|
{ |
||||
|
cmd.cmd.cmdFlags|=FRI_CMD_JNTSTIFF; |
||||
|
for (int i = 0; i < LBR_MNJ; i++) |
||||
|
cmd.cmd.jntStiffness[i]=newJntStiff[i]; |
||||
|
} |
||||
|
if (newJntDamp) |
||||
|
{ |
||||
|
cmd.cmd.cmdFlags|=FRI_CMD_JNTDAMP; |
||||
|
for (int i = 0; i < LBR_MNJ; i++) |
||||
|
cmd.cmd.jntDamping[i]=newJntDamp[i]; |
||||
|
} |
||||
|
if (newJntAddTorque) |
||||
|
{ |
||||
|
cmd.cmd.cmdFlags|=FRI_CMD_JNTTRQ; |
||||
|
for (int i = 0; i < LBR_MNJ; i++) |
||||
|
cmd.cmd.addJntTrq[i]=newJntAddTorque[i]; |
||||
|
} |
||||
|
|
||||
|
if (flagDataExchange) |
||||
|
{ |
||||
|
return doDataExchange(); |
||||
|
} |
||||
|
return 1; |
||||
|
} |
||||
|
|
||||
|
/** automatically do data exchange, if not otherwise specified
|
||||
|
if flagDataExchange is set to false, call doDataExchange() |
||||
|
or doReceiveData()/doSendData() on your own |
||||
|
IN: newJntPosition - joint positions |
||||
|
newJntStiff - joint stiffness (Spring factor) |
||||
|
newJntDamp - joint damping (Damping factor) |
||||
|
newJntAddTorque - additional torque |
||||
|
|
||||
|
Note: If any of the pointers (newJntPosition, newJntStiff, newJntDamp, newJntAddTorque) is NULL, the |
||||
|
value is ignored -> the respective cmd.cmd.cmdFlags field is set properly |
||||
|
Note: It is possible to change cmd.cmd.cmdFlags in monitor mode only !! |
||||
|
*/ |
||||
|
int friRemote::doCartesianImpedanceControl(const float newCartPosition[FRI_CART_FRM_DIM], |
||||
|
const float newCartStiff[FRI_CART_VEC], |
||||
|
const float newCartDamp[FRI_CART_VEC], |
||||
|
const float newAddTcpFT[FRI_CART_VEC], |
||||
|
const float newJntNullspace[LBR_MNJ], |
||||
|
bool flagDataExchange) |
||||
|
{ |
||||
|
|
||||
|
// Helper, if not properly initialized or the like...
|
||||
|
cmd.cmd.cmdFlags=0; |
||||
|
if ( newCartPosition ) |
||||
|
{ |
||||
|
cmd.cmd.cmdFlags|=FRI_CMD_CARTPOS; |
||||
|
for ( int i = 0; i < FRI_CART_FRM_DIM; i++) |
||||
|
{ |
||||
|
cmd.cmd.cartPos[i]=newCartPosition[i]; |
||||
|
|
||||
|
} |
||||
|
} |
||||
|
if ( newCartStiff) |
||||
|
{ |
||||
|
cmd.cmd.cmdFlags|=FRI_CMD_CARTSTIFF; |
||||
|
for ( int i = 0; i < FRI_CART_VEC; i++) |
||||
|
{ |
||||
|
cmd.cmd.cartStiffness[i]=newCartStiff[i]; |
||||
|
|
||||
|
} |
||||
|
|
||||
|
} |
||||
|
if ( newCartDamp) |
||||
|
{ |
||||
|
cmd.cmd.cmdFlags|=FRI_CMD_CARTDAMP; |
||||
|
; |
||||
|
for ( int i = 0; i < FRI_CART_VEC; i++) |
||||
|
{ |
||||
|
cmd.cmd.cartDamping[i]=newCartDamp[i]; |
||||
|
|
||||
|
} |
||||
|
} |
||||
|
if ( newAddTcpFT) |
||||
|
{ |
||||
|
cmd.cmd.cmdFlags|=FRI_CMD_TCPFT; |
||||
|
; |
||||
|
for ( int i = 0; i < FRI_CART_VEC; i++) |
||||
|
{ |
||||
|
cmd.cmd.addTcpFT[i]=newAddTcpFT[i]; |
||||
|
|
||||
|
} |
||||
|
} |
||||
|
|
||||
|
if (newJntNullspace) |
||||
|
{ |
||||
|
cmd.cmd.cmdFlags|=FRI_CMD_JNTPOS; |
||||
|
// Note:: If the interface is not in Command mode,
|
||||
|
// The commands have to be "mirrored" to get in sync
|
||||
|
|
||||
|
// compute new values here ...
|
||||
|
for (int i = 0; i < LBR_MNJ; i++) |
||||
|
cmd.cmd.jntPos[i]=newJntNullspace[i]; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
if (flagDataExchange) |
||||
|
{ |
||||
|
return doDataExchange(); |
||||
|
} |
||||
|
return 1; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
|
/* @} */ |
||||
|
|
@ -0,0 +1,194 @@ |
|||||
|
/* {{[PH] |
||||
|
**************************************************************************** |
||||
|
Project: FRI |
||||
|
|
||||
|
This material is the exclusive property of KUKA Roboter GmbH |
||||
|
and must be returned to KUKA Roboter GmbH immediately upon |
||||
|
request. This material and the information illustrated or |
||||
|
contained herein may not be used, reproduced, stored in a |
||||
|
retrieval system, or transmitted in whole or in part in any |
||||
|
way - electronic, mechanical, photocopying, recording, or |
||||
|
otherwise, without the prior written consent of KUKA Roboter GmbH. |
||||
|
|
||||
|
All Rights Reserved |
||||
|
Copyright (C) 2009 |
||||
|
KUKA Roboter GmbH |
||||
|
Augsburg, Germany |
||||
|
|
||||
|
[PH]}} |
||||
|
*/ |
||||
|
|
||||
|
/* |
||||
|
{{[FH] |
||||
|
**************************************************************************** |
||||
|
friFirstApp.cpp |
||||
|
|
||||
|
NOTE: This sample, as the corresponding FRI (Fast Research inteface) is subject to radical change |
||||
|
|
||||
|
|
||||
|
[FH]}} |
||||
|
*/ |
||||
|
/** |
||||
|
\defgroup friRemoteLib |
||||
|
\brief Library for FRI (FastResearchInterface) |
||||
|
*/ |
||||
|
/* @{ */ |
||||
|
|
||||
|
/** |
||||
|
\author (Guenter Schreiber) |
||||
|
\file |
||||
|
\brief Remote class for handshaking/dealing with udp datastructures |
||||
|
|
||||
|
This code is most important to understand the concepts behind data handshake |
||||
|
*/ |
||||
|
#ifndef FRIFRIREMOTE_H |
||||
|
#define FRIFRIREMOTE_H |
||||
|
|
||||
|
|
||||
|
#include "friudp.h" |
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
|
/** |
||||
|
@author Günter Schreiber <guenter@jacobus> |
||||
|
*/ |
||||
|
|
||||
|
class friRemote |
||||
|
{ |
||||
|
public: |
||||
|
friRemote(int port = FRI_DEFAULT_SERVER_PORT, char * hintToRemoteHost=NULL); |
||||
|
~friRemote(); |
||||
|
|
||||
|
/** Data Exchanger -- normally update within access routine implicitely |
||||
|
send commands based on last datagram and after waits on new measurement |
||||
|
calls doSendData() and doReceiveData(); |
||||
|
... */ |
||||
|
int doDataExchange(); |
||||
|
/** Receives data while calling friUdp::Recv() |
||||
|
The call will block.. |
||||
|
*/ |
||||
|
int doReceiveData(); |
||||
|
/** Sends the data */ |
||||
|
int doSendData(); |
||||
|
/* @{ */ |
||||
|
/** automatically do data exchange, if not otherwise specified |
||||
|
if flagDataExchange is set to false, call doDataExchange() |
||||
|
or doReceiveData()/doSendData() on your own |
||||
|
*/ |
||||
|
int doPositionControl(float newJntPosition[LBR_MNJ], bool flagDataExchange=true); |
||||
|
|
||||
|
/** automatically do data exchange, if not otherwise specified |
||||
|
if flagDataExchange is set to false, call doDataExchange() |
||||
|
or doReceiveData()/doSendData() on your own |
||||
|
IN: newJntPosition - joint positions |
||||
|
newJntStiff - joint stiffness (Spring factor) |
||||
|
newJntDamp - joint damping (Damping factor) |
||||
|
newJntAddTorque - additional torque |
||||
|
|
||||
|
Note: If any of the pointers (newJntPosition, newJntStiff, newJntDamp, newJntAddTorque) is NULL, the |
||||
|
value is ignored -> the respective cmd.cmd.cmdFlags field is set properly |
||||
|
Note: It is possible to change cmd.cmd.cmdFlags in monitor mode only !! |
||||
|
*/ |
||||
|
int doJntImpedanceControl(const float newJntPosition[LBR_MNJ], const float newJntStiff[LBR_MNJ] = NULL, const float newJntDamp[LBR_MNJ]=NULL, const float newJntAddTorque[LBR_MNJ]=NULL,bool flagDataExchange=true); |
||||
|
|
||||
|
|
||||
|
/** automatically do data exchange, if not otherwise specified |
||||
|
if flagDataExchange is set to false, call doDataExchange() |
||||
|
or doReceiveData()/doSendData() on your own |
||||
|
IN: newJntPosition - joint positions |
||||
|
newJntStiff - joint stiffness (Spring factor) |
||||
|
newJntDamp - joint damping (Damping factor) |
||||
|
newJntAddTorque - additional torque |
||||
|
|
||||
|
Note: If any of the pointers (newJntPosition, newJntStiff, newJntDamp, newJntAddTorque) is NULL, the |
||||
|
value is ignored -> the respective cmd.cmd.cmdFlags field is set properly |
||||
|
Note: It is possible to change cmd.cmd.cmdFlags in monitor mode only !! |
||||
|
*/ |
||||
|
int doCartesianImpedanceControl(const float newCartPosition[FRI_CART_FRM_DIM], |
||||
|
const float newCartStiff[FRI_CART_VEC]=NULL, |
||||
|
const float newCartDamp[FRI_CART_VEC]=NULL, |
||||
|
const float newAddTcpFT[FRI_CART_VEC]=NULL, |
||||
|
const float newJntNullspace[LBR_MNJ]=NULL, bool flagDataExchange=true); |
||||
|
/* @} */ |
||||
|
|
||||
|
/** measured Cartesian frame (in m) |
||||
|
KRL: $POS_ACT_MSR |
||||
|
Reference: Base and tool are specified by $stiffness.base, $stiffness.tool |
||||
|
*/ |
||||
|
float * getMsrCartPosition() { return msr.data.msrCartPos; } |
||||
|
/** commanded Cartesian frame (in m, before FRI) |
||||
|
KRL: $POS_ACT_CMD |
||||
|
Reference: Base and tool are specified by $stiffness.base, $stiffness.tool |
||||
|
*/ |
||||
|
float * getMsrCmdCartPosition() { return msr.data.cmdCartPos; } |
||||
|
|
||||
|
/** commanded Cartesian frame (in m, due to FRI) */ |
||||
|
float * getMsrCmdCartPosFriOffset() { return msr.data.cmdCartPosFriOffset; } |
||||
|
|
||||
|
/** Access to inner buffers for further manipulation */ |
||||
|
tFriMsrData & getMsrBuf() { return msr;} |
||||
|
tFriCmdData & getCmdBuf() { return cmd;} |
||||
|
/* @{ */ |
||||
|
/** interpretational access routines */ |
||||
|
FRI_STATE getState() { return (FRI_STATE)msr.intf.state; } |
||||
|
FRI_QUALITY getQuality() { return (FRI_QUALITY)msr.intf.quality; } |
||||
|
FRI_CTRL getCurrentControlScheme (){ return (FRI_CTRL)msr.robot.control; } |
||||
|
|
||||
|
bool isPowerOn() { return msr.robot.power!=0; } |
||||
|
/* @} */ |
||||
|
|
||||
|
/* @{ */ |
||||
|
/** Important value for superposition - and during poweroff stages, to become command mode */ |
||||
|
float * getMsrCmdJntPosition() { return msr.data.cmdJntPos; } |
||||
|
/** returns the offset, which is commanded by FRI Remote side |
||||
|
* Complete desired position inside LBR Kernel is the sum of cmdJntPos and cmdJntPosFriOffset */ |
||||
|
float * getMsrCmdJntPositionOffset() { return msr.data.cmdJntPosFriOffset; } |
||||
|
|
||||
|
void getCurrentCmdJntPosition( float jntVec[LBR_MNJ] ) { for ( int i = 0; i < LBR_MNJ; i++) jntVec[i]= msr.data.cmdJntPos[i]+msr.data.cmdJntPosFriOffset[i];} |
||||
|
/** Current measured jnt position of the robot */ |
||||
|
float * getMsrMsrJntPosition() { return msr.data.msrJntPos; } |
||||
|
float * getMsrEstExtJntTrq() { return msr.data.estExtJntTrq; } |
||||
|
float * getMsrJntTrq() { return msr.data.msrJntTrq; } |
||||
|
/* @} */ |
||||
|
|
||||
|
float getSampleTime() { return msr.intf.desiredCmdSampleTime; } |
||||
|
int getSequenceCount() { return seqCount; } |
||||
|
|
||||
|
/* @{ */ |
||||
|
/** KRL Interaction -- Corresponds to $FRI_TO_REA */ |
||||
|
float getFrmKRLReal(int index) { return msr.krl.realData[index]; } |
||||
|
/** KRL Interaction -- Corresponds to $FRI_FRM_REA */ |
||||
|
void setToKRLReal(int index, float val) { cmd.krl.realData[index]=val; } |
||||
|
/** KRL Interaction -- Corresponds to $FRI_TO_INT */ |
||||
|
int getFrmKRLInt(int index) { return msr.krl.intData[index]; } |
||||
|
/** KRL Interaction -- Corresponds to $FRI_FRM_INT */ |
||||
|
void setToKRLInt(int index, int val) { cmd.krl.intData[index]=val; } |
||||
|
/** KRL Interaction -- Corresponds to $FRI_TO_BOOL */ |
||||
|
bool getFrmKRLBool(int index) { return ((msr.krl.boolData & (1<<index)) != 0);} |
||||
|
/** KRL Interaction -- Corresponds to $FRI_FRM_BOOL */ |
||||
|
fri_uint16_t getFrmKRLBool() { return msr.krl.boolData; } |
||||
|
/** KRL Interaction -- Corresponds to $FRI_FRM_BOOL */ |
||||
|
void setToKRLBool(int index, bool val) |
||||
|
{ if ( val) { cmd.krl.boolData |= (1<<index);} |
||||
|
else {cmd.krl.boolData &= (~(1<<index));}} |
||||
|
void setToKRLBool(fri_uint16_t val) { cmd.krl.boolData = val; } |
||||
|
/* @} */ |
||||
|
/** Get Jacobian Matrix |
||||
|
*/ |
||||
|
float * getJacobian() { return msr.data.jacobian; } |
||||
|
float * getFTTcp() {return msr.data.estExtTcpFT;} |
||||
|
|
||||
|
protected: |
||||
|
tFriMsrData msr; |
||||
|
tFriCmdData cmd; |
||||
|
private: |
||||
|
friUdp remote; |
||||
|
int seqCount; |
||||
|
}; |
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
|
#endif |
||||
|
/* @} */ |
@ -0,0 +1,543 @@ |
|||||
|
/*{{[PH]
|
||||
|
**************************************************************************** |
||||
|
Project: FRI |
||||
|
|
||||
|
This material is the exclusive property of KUKA Roboter GmbH |
||||
|
and must be returned to KUKA Roboter GmbH immediately upon |
||||
|
request. This material and the information illustrated or |
||||
|
contained herein may not be used, reproduced, stored in a |
||||
|
retrieval system, or transmitted in whole or in part in any |
||||
|
way - electronic, mechanical, photocopying, recording, or |
||||
|
otherwise, without the prior written consent of KUKA Roboter GmbH. |
||||
|
|
||||
|
All Rights Reserved |
||||
|
Copyright (C) 2009 |
||||
|
KUKA Roboter GmbH |
||||
|
Augsburg, Germany |
||||
|
|
||||
|
[PH]}} |
||||
|
*/ |
||||
|
|
||||
|
/*
|
||||
|
{{[FH] |
||||
|
**************************************************************************** |
||||
|
friUdp.cpp |
||||
|
|
||||
|
NOTE: This sample, as the corresponding FRI (Fast Research inteface) is subject to radical change |
||||
|
|
||||
|
|
||||
|
[FH]}} |
||||
|
*/ |
||||
|
/**
|
||||
|
\addtogroup friRemoteLib |
||||
|
\brief Library for FRI (FastResearchInterface) |
||||
|
*/ |
||||
|
/* @{ */ |
||||
|
|
||||
|
/** *************************************************************************
|
||||
|
\author (Guenter Schreiber) |
||||
|
\file |
||||
|
\brief Implementation of a UDP socket |
||||
|
* * |
||||
|
***************************************************************************/ |
||||
|
#include "friudp.h"
|
||||
|
|
||||
|
#ifdef WIN32
|
||||
|
#include "SocketObject.h"
|
||||
|
//#pragma comment(lib, "ws2_32.lib")
|
||||
|
#endif // WIN32
|
||||
|
|
||||
|
|
||||
|
friUdp::friUdp(int port, char * remoteHost) : serverPort(port) |
||||
|
{ |
||||
|
/* check struct sizes */ |
||||
|
if (!FRI_CHECK_SIZES_OK) |
||||
|
{ |
||||
|
printf("data structure size error!\n"); |
||||
|
exit(1); |
||||
|
} |
||||
|
|
||||
|
m_timestamp=0; |
||||
|
// Make shure, that e.g. simulink uses no stupid standard definition - e.g. 0
|
||||
|
if ( serverPort < 10 ) |
||||
|
{ |
||||
|
serverPort=FRI_DEFAULT_SERVER_PORT; |
||||
|
} |
||||
|
|
||||
|
#ifdef WIN32
|
||||
|
StartWinsock(); |
||||
|
#endif
|
||||
|
Init(remoteHost); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
friUdp::~friUdp() |
||||
|
{ |
||||
|
Close(); |
||||
|
} |
||||
|
|
||||
|
#ifdef WIN32
|
||||
|
int friUdp::StartWinsock(void) |
||||
|
{ |
||||
|
WSADATA WSAData; |
||||
|
return WSAStartup(MAKEWORD(2,0), &WSAData); |
||||
|
} |
||||
|
#endif// WIN32
|
||||
|
|
||||
|
void friUdp::Init(char * remoteHost) |
||||
|
{ |
||||
|
struct sockaddr_in servAddr; |
||||
|
m_timestamp = 0; |
||||
|
memset(&servAddr, 0, sizeof(servAddr)); |
||||
|
memset(&krcAddr, 0, sizeof(krcAddr)); |
||||
|
|
||||
|
/* socket creation */ |
||||
|
udpSock = socket(PF_INET, SOCK_DGRAM, 0); |
||||
|
if (udpSock < 0) |
||||
|
{ |
||||
|
printf("opening socket failed!\n"); |
||||
|
exit(1); |
||||
|
} |
||||
|
|
||||
|
#ifdef HAVE_TIME_STAMP_RECEIVE
|
||||
|
{ |
||||
|
int temp = 1; |
||||
|
if (setsockopt(udpSock, SOL_SOCKET, SO_TIMESTAMP, &temp, sizeof(int)) < 0) |
||||
|
{ |
||||
|
printf("failed to enable receive time stamps\n"); |
||||
|
exit(1); |
||||
|
} |
||||
|
} |
||||
|
#endif
|
||||
|
|
||||
|
/* bind local server port */ |
||||
|
servAddr.sin_family = AF_INET; |
||||
|
servAddr.sin_addr.s_addr = htonl(INADDR_ANY); |
||||
|
servAddr.sin_port = htons(serverPort); |
||||
|
|
||||
|
if (bind(udpSock, (struct sockaddr *) &servAddr, sizeof(servAddr)) < 0) |
||||
|
{ |
||||
|
printf("binding port number %d failed!\n", serverPort); |
||||
|
Close(); |
||||
|
exit(1); |
||||
|
} |
||||
|
|
||||
|
// if the remote host is specified,
|
||||
|
// preinitialize the socket properly
|
||||
|
if ( remoteHost ) |
||||
|
{ |
||||
|
printf("preinitialized remote host to %s\n",remoteHost); |
||||
|
krcAddr.sin_addr.s_addr = inet_addr(remoteHost); |
||||
|
krcAddr.sin_family = AF_INET; |
||||
|
krcAddr.sin_port=htons(serverPort); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
#ifdef HAVE_GETHOSTNAME
|
||||
|
/* get IP(s) and port number and display them (just for
|
||||
|
convenience, so debugging friOpen is easier) */ |
||||
|
{ |
||||
|
char hostname[100]; |
||||
|
struct hostent * host; |
||||
|
int i; |
||||
|
|
||||
|
gethostname(hostname, sizeof(hostname)); |
||||
|
host = gethostbyname(hostname); |
||||
|
for (i=0; host->h_addr_list[i]!=0; i++) |
||||
|
{ |
||||
|
struct in_addr addr; |
||||
|
memcpy(&addr, host->h_addr_list[i], sizeof(addr)); |
||||
|
//printf("helloIP %s - Port %d\n", inet_ntoa(addr), serverPort);
|
||||
|
} |
||||
|
} |
||||
|
#endif //
|
||||
|
|
||||
|
|
||||
|
} |
||||
|
|
||||
|
/* reveive one packet from KRC (blocking!) */ |
||||
|
int friUdp::Recv(tFriMsrData *packet) |
||||
|
{ |
||||
|
if (udpSock >= 0) |
||||
|
{ |
||||
|
int received; |
||||
|
struct timeval ts; |
||||
|
|
||||
|
received = RecvPacket(udpSock, packet, &ts, &krcAddr); |
||||
|
|
||||
|
if (received == sizeof(tFriMsrData)) |
||||
|
{ |
||||
|
#ifdef HAVE_TIME_STAMP_RECEIVE
|
||||
|
|
||||
|
/* FIXME: need another #ifdef for VxWorks */ |
||||
|
#ifdef QNX
|
||||
|
struct timespec ts; |
||||
|
clock_gettime(CLOCK_REALTIME, &ts); |
||||
|
m_timestamp = (double)ts.tv_sec + (double)ts.tv_nsec/1.0e9; |
||||
|
#else
|
||||
|
m_timestamp = (double)ts.tv_sec + (double)ts.tv_usec/1.0e6; |
||||
|
#endif // QNX
|
||||
|
#endif // HAVE_TIME_STAMP
|
||||
|
return 0; |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
printf("received something, but wrong size %d (expected %d)...\n",received,(int) sizeof(tFriMsrData)); |
||||
|
fflush(stdout); |
||||
|
} |
||||
|
} |
||||
|
memset(packet, 0, sizeof(tFriMsrData)); |
||||
|
return -1; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
|
||||
|
/* send one answer packet to KRC */ |
||||
|
int friUdp::Send(tFriCmdData *data) |
||||
|
{ |
||||
|
krcAddr.sin_family = AF_INET; |
||||
|
#ifdef KRC_IP_ADDRESS
|
||||
|
krcAddr.sin_addr.s_addr = inet_addr(KRC_IP_ADDRESS); |
||||
|
#endif
|
||||
|
#ifdef KRC_RECEIVE_PORT
|
||||
|
krcAddr.sin_port = htons(KRC_RECEIVE_PORT); |
||||
|
#endif
|
||||
|
|
||||
|
if ((udpSock >= 0) && (ntohs(krcAddr.sin_port) != 0)) |
||||
|
{ |
||||
|
int sent; |
||||
|
sent = sendto(udpSock, (char *) data, sizeof(tFriCmdData), 0, |
||||
|
(struct sockaddr *)&krcAddr, sizeof(krcAddr)); |
||||
|
if (sent == sizeof(tFriCmdData)) |
||||
|
{ |
||||
|
return 0; |
||||
|
} |
||||
|
} |
||||
|
return -1; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
|
/* close the socket */ |
||||
|
void friUdp::Close(void) |
||||
|
{ |
||||
|
if (udpSock >= 0) |
||||
|
{ |
||||
|
#ifdef WIN32
|
||||
|
closesocket(udpSock); |
||||
|
WSACleanup(); |
||||
|
#else
|
||||
|
close(udpSock); |
||||
|
#endif
|
||||
|
} |
||||
|
udpSock = -1; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
#ifdef HAVE_TIME_STAMP_RECEIVE
|
||||
|
// Socket option SO_TIMESTAMP is supported
|
||||
|
/* receive with timestamp */ |
||||
|
int friUdp::RecvPacket(int fd, tFriMsrData* p, struct timeval* ts, struct sockaddr_in* client) |
||||
|
{ |
||||
|
struct msghdr msg; |
||||
|
struct iovec vec[1]; |
||||
|
union { |
||||
|
struct cmsghdr cm; |
||||
|
char control[20]; |
||||
|
} cmsg_un; |
||||
|
struct cmsghdr *cmsg; |
||||
|
struct timeval *tv = NULL; |
||||
|
int n; |
||||
|
|
||||
|
vec[0].iov_base = p; |
||||
|
vec[0].iov_len = sizeof(*p); |
||||
|
|
||||
|
memset(&msg, 0, sizeof(msg)); |
||||
|
memset(&cmsg_un, 0, sizeof(cmsg_un)); |
||||
|
|
||||
|
msg.msg_name = (caddr_t)client; |
||||
|
if(client) |
||||
|
msg.msg_namelen = sizeof(*client); |
||||
|
else |
||||
|
msg.msg_namelen = 0; |
||||
|
|
||||
|
msg.msg_iov = vec; |
||||
|
msg.msg_iovlen = 1; |
||||
|
msg.msg_control = cmsg_un.control; |
||||
|
msg.msg_controllen = sizeof(cmsg_un.control); |
||||
|
msg.msg_flags = 0; |
||||
|
|
||||
|
n = recvmsg(fd, &msg, 0); // MSG_DONTWAIT
|
||||
|
if(n < 0) |
||||
|
{ |
||||
|
perror("recvmsg"); |
||||
|
return -1; |
||||
|
} |
||||
|
if(msg.msg_flags & MSG_TRUNC) |
||||
|
{ |
||||
|
printf("received truncated message\n"); |
||||
|
return -1; |
||||
|
} |
||||
|
if(!ts) |
||||
|
return n; |
||||
|
|
||||
|
/* get time stamp of packet */ |
||||
|
if(msg.msg_flags & MSG_CTRUNC) |
||||
|
{ |
||||
|
printf("received truncated ancillary data\n"); |
||||
|
return -1; |
||||
|
} |
||||
|
if(msg.msg_controllen < sizeof(cmsg_un.control)) |
||||
|
{ |
||||
|
printf("received short ancillary data (%d/%d)\n", msg.msg_controllen, (int)sizeof(cmsg_un.control)); |
||||
|
return -1; |
||||
|
} |
||||
|
for(cmsg = CMSG_FIRSTHDR(&msg); cmsg != NULL; cmsg = CMSG_NXTHDR(&msg, cmsg)) |
||||
|
{ |
||||
|
if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_TIMESTAMP) |
||||
|
tv = (struct timeval *)CMSG_DATA(cmsg); |
||||
|
} |
||||
|
if(tv) |
||||
|
{ |
||||
|
ts->tv_sec = tv->tv_sec; |
||||
|
ts->tv_usec = tv->tv_usec; |
||||
|
} |
||||
|
return n; |
||||
|
} |
||||
|
|
||||
|
#else
|
||||
|
/* receive with timestamp */ |
||||
|
int friUdp::RecvPacket(int udpSock, tFriMsrData* data, struct timeval* ts, struct sockaddr_in* client) |
||||
|
{ |
||||
|
|
||||
|
if (udpSock >= 0) |
||||
|
{ |
||||
|
/** HAVE_SOCKLEN_T
|
||||
|
Yes - unbelieavble: There are differences in standard calling parameters (types) to recvfrom |
||||
|
Windows winsock, VxWorks and QNX use int |
||||
|
newer Posix (most Linuxes) use socklen_t |
||||
|
*/ |
||||
|
|
||||
|
#ifdef HAVE_SOCKLEN_T
|
||||
|
socklen_t sockAddrSize; |
||||
|
#else
|
||||
|
int sockAddrSize; |
||||
|
#endif
|
||||
|
int received; |
||||
|
|
||||
|
sockAddrSize = sizeof(struct sockaddr_in); |
||||
|
|
||||
|
received = recvfrom(udpSock, (char *) data, sizeof(tFriMsrData), 0, |
||||
|
(struct sockaddr *)&krcAddr, &sockAddrSize); |
||||
|
|
||||
|
return received; |
||||
|
} |
||||
|
return -1; |
||||
|
} |
||||
|
|
||||
|
#endif // HAVE_TIME_STAMP_RECEIVE
|
||||
|
|
||||
|
|
||||
|
#ifdef VXWORKS //USE_BERKELEY_PACKAGE_FILTER_VXWORKS
|
||||
|
#define DEBUG_BPF_READ
|
||||
|
|
||||
|
#include "vxworks.h"
|
||||
|
#include "bpfDrv.h"
|
||||
|
#include "ioLib.h"
|
||||
|
#include <logLib.h>
|
||||
|
#include <sys/ioctl.h>
|
||||
|
//#include "drv/netif/smNetLib.h"
|
||||
|
#include <wrn/coreip/net/ethernet.h>
|
||||
|
#include <wrn/coreip/net/if.h>
|
||||
|
#include <wrn/coreip/netinet/ip.h>
|
||||
|
#include <wrn/coreip/netinet/udp.h>
|
||||
|
|
||||
|
#ifdef DEBUG_BPF_READ
|
||||
|
#include <iostream>
|
||||
|
#include "friremote.h"
|
||||
|
|
||||
|
#endif
|
||||
|
|
||||
|
|
||||
|
/*
|
||||
|
* Packet filter program... |
||||
|
* |
||||
|
* XXX: Changes to the filter program may require changes to the |
||||
|
* constant offsets used in if_register_send to patch the BPF program! |
||||
|
*/ |
||||
|
struct bpf_insn friUpdSock_bpf_filter[] = |
||||
|
{ |
||||
|
/* Make sure this is an IP packet... */ |
||||
|
BPF_STMT(BPF_LD + BPF_H + BPF_ABS, 12), |
||||
|
BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, ETHERTYPE_IP, 0, 8), |
||||
|
|
||||
|
/* Make sure it's a UDP packet... */ |
||||
|
BPF_STMT(BPF_LD + BPF_B + BPF_ABS, 23), |
||||
|
BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, IPPROTO_UDP, 0, 6), |
||||
|
|
||||
|
/* Make sure this isn't a fragment... */ |
||||
|
BPF_STMT(BPF_LD + BPF_H + BPF_ABS, 20), |
||||
|
BPF_JUMP(BPF_JMP + BPF_JSET + BPF_K, 0x1fff, 4, 0), |
||||
|
|
||||
|
/* Get the IP header length... */ |
||||
|
BPF_STMT(BPF_LDX + BPF_B + BPF_MSH, 14), |
||||
|
|
||||
|
/* Make sure it's to the right port... */ |
||||
|
BPF_STMT(BPF_LD + BPF_H + BPF_IND, 16), |
||||
|
BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, 67, 0, 1), /* patch */ |
||||
|
|
||||
|
/* If we passed all the tests, ask for the whole packet. */ |
||||
|
BPF_STMT(BPF_RET+BPF_K, (u_int)-1), |
||||
|
|
||||
|
/* Otherwise, drop it. */ |
||||
|
BPF_STMT(BPF_RET+BPF_K, 0), |
||||
|
}; |
||||
|
|
||||
|
int friUpdSock_bpf_filter_len = sizeof(friUpdSock_bpf_filter) / sizeof(struct bpf_insn); |
||||
|
struct bpf_program mybpf; |
||||
|
|
||||
|
|
||||
|
void testBPF1(int socketPort, char * devName) |
||||
|
{ |
||||
|
int bpffd = 0; |
||||
|
struct bpf_hdr * buf = NULL; |
||||
|
char * pbuffer = NULL; |
||||
|
int buflen; |
||||
|
int len,i; |
||||
|
///int j=10;
|
||||
|
char dev[8] = "gei0"; |
||||
|
struct ifreq ifr; |
||||
|
int trueValue=1; |
||||
|
int Rcvlen; |
||||
|
|
||||
|
if ( socketPort <= 10) |
||||
|
socketPort = 12345; |
||||
|
|
||||
|
if ( devName != NULL ) |
||||
|
{ |
||||
|
strncpy(dev,devName,8); |
||||
|
dev[8]=0; |
||||
|
} |
||||
|
mybpf.bf_len = friUpdSock_bpf_filter_len; |
||||
|
mybpf.bf_insns = friUpdSock_bpf_filter; |
||||
|
|
||||
|
/* Patch the server port into the BPF program...
|
||||
|
* |
||||
|
* XXX: changes to filter program may require changes to the |
||||
|
* insn number(s) used below! |
||||
|
*/ |
||||
|
friUpdSock_bpf_filter[8].k = socketPort; |
||||
|
|
||||
|
bpfDrv(); |
||||
|
|
||||
|
if ( bpfDevCreate("/dev/bpf",2,4096) == ERROR) |
||||
|
{ |
||||
|
printf("bpfDevCreate failed \n"); |
||||
|
return; |
||||
|
} |
||||
|
bpffd = open( "/dev/bpf0",0,0); |
||||
|
if ( bpffd <= 0) |
||||
|
{ |
||||
|
printf("open /dev/bpf0 failed\n"); |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
memset(&ifr, sizeof(struct ifreq), 0); |
||||
|
strncpy(ifr.ifr_name, dev, sizeof(ifr.ifr_name)); |
||||
|
|
||||
|
#define IOCTRL_CAST_THIRD_ARG (int)
|
||||
|
|
||||
|
if (ioctl(bpffd,BIOCIMMEDIATE, IOCTRL_CAST_THIRD_ARG &trueValue) < 0) |
||||
|
{ |
||||
|
printf("Error BIOCIMMEDIATE \n"); |
||||
|
} |
||||
|
|
||||
|
if (ioctl(bpffd,(BIOCSETF),IOCTRL_CAST_THIRD_ARG (caddr_t)(&mybpf)) < 0) |
||||
|
{ |
||||
|
perror("Error BIOCSETF \n"); |
||||
|
goto errorMark; |
||||
|
} |
||||
|
|
||||
|
if (ioctl(bpffd,(BIOCSETIF),IOCTRL_CAST_THIRD_ARG (caddr_t)&ifr) < 0) |
||||
|
{ |
||||
|
printf("ERROR BIOCSETIF %s \n",dev); |
||||
|
goto errorMark; |
||||
|
} |
||||
|
|
||||
|
if (ioctl(bpffd,BIOCGBLEN, IOCTRL_CAST_THIRD_ARG &buflen) < 0) |
||||
|
{ |
||||
|
printf("Error BIOCGBLEN \n"); |
||||
|
} |
||||
|
|
||||
|
if (buflen > 4096) |
||||
|
buflen=4096; |
||||
|
|
||||
|
buf = (struct bpf_hdr *)malloc(buflen); |
||||
|
//bzero(buf,buflen);
|
||||
|
memset(buf,0x0,buflen); |
||||
|
|
||||
|
while ((len = read(bpffd,(char *)buf,buflen)) != 0) |
||||
|
{ |
||||
|
// im bpf header steht noch ein Timestamp -- waere gut fuer Timing thematik
|
||||
|
//
|
||||
|
|
||||
|
// Empfangene Rohdaten ohne bpf Header
|
||||
|
pbuffer = (char *)buf + buf->bh_hdrlen; |
||||
|
|
||||
|
// Empfangene Rohdatenlaenge ohne bpf Header
|
||||
|
Rcvlen = len - (buf->bh_hdrlen); |
||||
|
//
|
||||
|
// Wie trennt man nun die "Nutzdaten" von den Verwaltungsdaten??
|
||||
|
//
|
||||
|
|
||||
|
struct ip * iph = (struct ip *) ((char *) buf + buf->bh_hdrlen + sizeof(struct ether_header)); |
||||
|
struct udphdr * udph = (struct udphdr *) ((char *) iph + sizeof(struct ip)); |
||||
|
char * userData = ((char *) udph) + sizeof( struct udphdr); |
||||
|
|
||||
|
tFriCmdData * cmd = ( tFriCmdData * ) userData; |
||||
|
#ifdef DEBUG_BPF_READ
|
||||
|
printf("recvLen %d\n",Rcvlen); |
||||
|
printf("IP SRC:\t\t%s\n", inet_ntoa(iph->ip_src)); |
||||
|
printf("IP DST:\t\t%s\n", inet_ntoa(iph->ip_dst)); |
||||
|
printf("UDP SRC:\t%u\n", ntohs(udph->uh_sport)); |
||||
|
printf("UDP DST:\t%u\n", ntohs(udph->uh_dport)); |
||||
|
printf("Len #:\t\t%u\n", ntohs(udph->uh_ulen)); |
||||
|
#endif
|
||||
|
|
||||
|
logMsg("BUF LEN = 0x%x\n",Rcvlen,0,0,0,0,0); |
||||
|
|
||||
|
std::cout << (*cmd) << std::endl; |
||||
|
for (i=0;i< ntohs(udph->uh_ulen);i++) |
||||
|
{ |
||||
|
printf(" %2x", userData[i]); |
||||
|
if ((i % 10) == 9) |
||||
|
{ |
||||
|
printf("\n");//,0,0,0,0,0,0);
|
||||
|
} |
||||
|
} |
||||
|
printf("\nFull packet \n"); |
||||
|
for (i=0; i < Rcvlen; i++) |
||||
|
{ |
||||
|
printf(" %2x(%4d)", pbuffer[i],pbuffer[i]); |
||||
|
if ((i % 10) == 9) |
||||
|
{ |
||||
|
printf("\n");//,0,0,0,0,0,0);
|
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
errorMark: |
||||
|
printf("leaving %s\n",__PRETTY_FUNCTION__); |
||||
|
if ( buf != NULL ) |
||||
|
free(buf); |
||||
|
if ( bpffd > 0 ) |
||||
|
close (bpffd); |
||||
|
bpfDevDelete("/dev/bpf"); |
||||
|
} |
||||
|
#endif
|
||||
|
|
||||
|
|
||||
|
/*****************************************************************************
|
||||
|
$Log: $ |
||||
|
*****************************************************************************/ |
||||
|
/* @} */ |
@ -0,0 +1,257 @@ |
|||||
|
/*{{[PH] |
||||
|
**************************************************************************** |
||||
|
Project: FRI |
||||
|
|
||||
|
This material is the exclusive property of KUKA Roboter GmbH |
||||
|
and must be returned to KUKA Roboter GmbH immediately upon |
||||
|
request. This material and the information illustrated or |
||||
|
contained herein may not be used, reproduced, stored in a |
||||
|
retrieval system, or transmitted in whole or in part in any |
||||
|
way - electronic, mechanical, photocopying, recording, or |
||||
|
otherwise, without the prior written consent of KUKA Roboter GmbH. |
||||
|
|
||||
|
All Rights Reserved |
||||
|
Copyright (C) 2009 |
||||
|
KUKA Roboter GmbH |
||||
|
Augsburg, Germany |
||||
|
|
||||
|
[PH]}} |
||||
|
*/ |
||||
|
|
||||
|
/* |
||||
|
{{[FH] |
||||
|
**************************************************************************** |
||||
|
friUdp.h |
||||
|
|
||||
|
NOTE: This sample, as the corresponding FRI (Fast Research inteface) is subject to radical change |
||||
|
|
||||
|
|
||||
|
[FH]}} |
||||
|
*/ |
||||
|
/** |
||||
|
\addtogroup friRemoteLib |
||||
|
\brief Library for FRI (FastResearchInterface) |
||||
|
*/ |
||||
|
/* @{ */ |
||||
|
/** ************************************************************************* |
||||
|
\author (Guenter Schreiber) |
||||
|
\file |
||||
|
\brief header for udp Communications |
||||
|
* * |
||||
|
***************************************************************************/ |
||||
|
#ifndef FRIFRIUDP_H |
||||
|
#define FRIFRIUDP_H |
||||
|
|
||||
|
#ifdef VXWORKS |
||||
|
#else |
||||
|
#define HAVE_GETHOSTNAME |
||||
|
#endif |
||||
|
|
||||
|
#include <stdio.h> |
||||
|
#include <stdlib.h> |
||||
|
|
||||
|
#ifdef _MSC_VER |
||||
|
#include "SocketObject.h" |
||||
|
#else |
||||
|
#include <sys/socket.h> |
||||
|
#include <netinet/in.h> |
||||
|
#include <arpa/inet.h> |
||||
|
#include <unistd.h> |
||||
|
#include <netdb.h> |
||||
|
#include <string.h> |
||||
|
#ifndef _WRS_KERNEL |
||||
|
#include <sys/time.h> |
||||
|
#endif |
||||
|
#include <time.h> |
||||
|
#endif |
||||
|
#include "friComm.h" |
||||
|
|
||||
|
#include <iostream> |
||||
|
|
||||
|
#ifdef VXWORKS // VxWorks Kernel |
||||
|
|
||||
|
#include <sockLib.h> |
||||
|
#endif |
||||
|
|
||||
|
|
||||
|
#define FRI_DEFAULT_SERVER_PORT 49938 |
||||
|
|
||||
|
#ifdef QNX |
||||
|
#define HAVE_TIME_STAMP_RECEIVE |
||||
|
#endif |
||||
|
|
||||
|
|
||||
|
#ifdef HAVE_TIME_STAMP_RECEIVE |
||||
|
/** Receive Timestamp -- mechanism works under |
||||
|
QNX, Linux? |
||||
|
|
||||
|
Not under Windows - and under VxWorks |
||||
|
*/ |
||||
|
|
||||
|
typedef struct |
||||
|
{ |
||||
|
tFriMsrData load; |
||||
|
/* add a received-timestamp */ |
||||
|
double timestamp; |
||||
|
} tFriMsrPacket; |
||||
|
|
||||
|
#endif |
||||
|
|
||||
|
/** |
||||
|
FRI Remote Sample Implementation |
||||
|
|
||||
|
@author Günter Schreiber <guenter@jacobus> |
||||
|
*/ |
||||
|
class friUdp |
||||
|
{ |
||||
|
public: |
||||
|
friUdp(int port=FRI_DEFAULT_SERVER_PORT, char *remoteHost = NULL); |
||||
|
~friUdp(); |
||||
|
|
||||
|
protected: |
||||
|
/// Note: Remote host need not to be specified - if NULL, wait for the |
||||
|
/// incoming packages |
||||
|
void Init(char * remoteHost=NULL); |
||||
|
void Close(void); |
||||
|
#ifdef WIN32 |
||||
|
int StartWinsock(void); |
||||
|
#endif |
||||
|
public: |
||||
|
int Send(tFriCmdData *data); |
||||
|
int Recv(tFriMsrData *packet); |
||||
|
private: |
||||
|
int RecvPacket(int fd, tFriMsrData* p, struct timeval* ts, struct sockaddr_in* client); |
||||
|
int udpSock ; |
||||
|
int serverPort; |
||||
|
struct sockaddr_in krcAddr; |
||||
|
/// if timestamp on receive is available, last received value can be inquired here |
||||
|
double m_timestamp; |
||||
|
public: |
||||
|
/// This feature will be available only for systems, which support |
||||
|
/// SO_TIMESTAMP in the socket options, e.g. qnx |
||||
|
double getLastTimestamp() { return m_timestamp; } |
||||
|
}; |
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
|
inline std::ostream & operator<<(std::ostream &out , tFriHeader & head) |
||||
|
{ |
||||
|
out << "sendSeqCount " << head.sendSeqCount << "\n"; |
||||
|
out << "reflSeqCount " << head.reflSeqCount << "\n"; |
||||
|
out << "packetSize " << head.packetSize << "\n"; |
||||
|
out << "datagramId " << std::hex << head.datagramId << std::dec ; |
||||
|
switch (head.datagramId ) |
||||
|
{ |
||||
|
case FRI_DATAGRAM_ID_CMD: |
||||
|
out << " FRI_DATAGRAM_ID_CMD \n" ; |
||||
|
break; |
||||
|
case FRI_DATAGRAM_ID_MSR: |
||||
|
out << " FRI_DATAGRAM_ID_MSR \n" ; |
||||
|
break; |
||||
|
default: |
||||
|
out <<" Unkown \n"; |
||||
|
} |
||||
|
return out; |
||||
|
} |
||||
|
inline std::ostream & operator<<(std::ostream &out , tFriKrlData& krl) |
||||
|
{ |
||||
|
out << "krl_real "; |
||||
|
for ( int i = 0; i < FRI_USER_SIZE; i++) |
||||
|
out << " " << krl.realData[i]; |
||||
|
out << "\n"; |
||||
|
out << "krl_int "; |
||||
|
for ( int i = 0; i < FRI_USER_SIZE; i++) |
||||
|
out << " " << krl.intData[i]; |
||||
|
out << "\n"; |
||||
|
out << "krl_bool "; |
||||
|
out << std::hex << krl.boolData << std::dec << "\n"; |
||||
|
return out; |
||||
|
} |
||||
|
|
||||
|
inline std::ostream & operator<<(std::ostream &out , tFriIntfStatistics & stat) |
||||
|
{ |
||||
|
out << "answerRate " << stat.answerRate << "\n"; |
||||
|
out << "latency " << stat.latency << "\n"; |
||||
|
out << "jitter " << stat.jitter << "\n"; |
||||
|
out << "missRate " << stat.missRate << "\n"; |
||||
|
out << "missCounter " << stat.missCounter << "\n"; |
||||
|
return out; |
||||
|
} |
||||
|
|
||||
|
inline std::ostream & operator<<(std::ostream &out , tFriIntfState & state) |
||||
|
{ |
||||
|
out << "timestamp " << state.timestamp<< "\n"; |
||||
|
out << "state " << state.state<< "\n"; |
||||
|
out << "quality " << state.quality << "\n"; |
||||
|
out << "desiredMsrSampleTime " << state.desiredMsrSampleTime << "\n"; |
||||
|
out << "desiredCmdSampleTiintfme " << state.desiredCmdSampleTime << "\n"; |
||||
|
out << "safetyLimits " << state.safetyLimits << "\n"; |
||||
|
out << "statistics " << state.stat << "\n"; |
||||
|
return out; |
||||
|
} |
||||
|
|
||||
|
inline std::ostream & operator<< (std::ostream & out, tFriRobotState & robot) |
||||
|
{ |
||||
|
out << "power " << robot.power<< "\n"; |
||||
|
out << "control " << robot.control << "\n"; |
||||
|
out << "error " << robot.error << "\n"; |
||||
|
out << "warning " << robot.warning << "\n"; |
||||
|
out << "temperature " ; |
||||
|
for (int i = 0; i < LBR_MNJ; i++) |
||||
|
out << robot.temperature[i] << " " ; |
||||
|
out << "\n"; |
||||
|
return out; |
||||
|
|
||||
|
} |
||||
|
|
||||
|
#define WRITE_JNT_VEC(field) \ |
||||
|
out << ""#field; \ |
||||
|
for ( int i = 0; i < LBR_MNJ; i++) \ |
||||
|
out << " " << robot.field[i]; \ |
||||
|
out << "\n"; |
||||
|
inline std::ostream & operator<<(std::ostream &out, tFriRobotData & robot) |
||||
|
{ |
||||
|
WRITE_JNT_VEC(msrJntPos); |
||||
|
WRITE_JNT_VEC(cmdJntPos); |
||||
|
WRITE_JNT_VEC(msrJntTrq); |
||||
|
WRITE_JNT_VEC(estExtJntTrq); |
||||
|
return out; |
||||
|
|
||||
|
} |
||||
|
|
||||
|
inline std::ostream & operator<<(std::ostream &out, tFriRobotCommand & robot) |
||||
|
{ |
||||
|
out << std::hex << robot.cmdFlags << std::dec << "\n"; |
||||
|
WRITE_JNT_VEC(jntPos); |
||||
|
return out; |
||||
|
|
||||
|
} |
||||
|
|
||||
|
|
||||
|
inline std::ostream & operator<<(std::ostream &out, tFriMsrData & msr) |
||||
|
{ |
||||
|
out << "head " << msr.head; |
||||
|
out << "krl " << msr.krl; |
||||
|
out << "intf " << msr.intf; |
||||
|
out << "robot " << msr.robot; |
||||
|
out << "data " << msr.data; |
||||
|
return out; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
|
inline std::ostream & operator<<(std::ostream &out, tFriCmdData & cmd) |
||||
|
{ |
||||
|
out << "head " << cmd.head; |
||||
|
out << "krl " << cmd.krl; |
||||
|
out << "cmd " << cmd.cmd; |
||||
|
return out; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
|
#endif |
||||
|
/* @} */ |
@ -0,0 +1,36 @@ |
|||||
|
bool __SVR_CURRENT_JOB = false; |
||||
|
bool __MSRMSRJNTPOS = false; |
||||
|
bool __MSRCMDJNTPOS = false; |
||||
|
bool __MSRCMDPOSE = false; |
||||
|
bool __SETVELOCITY = false; |
||||
|
bool __SETACCEL = false; |
||||
|
bool __DEBUG = false; |
||||
|
bool __POTFIELDMODE = false; |
||||
|
bool __MSRSTARTPOTFIELD = false; |
||||
|
bool __MSRSTOPPOTFIELD = false; |
||||
|
bool __MSRSETPOS = false; |
||||
|
bool __CARTMOVE = false; |
||||
|
bool __DOUS = false; |
||||
|
bool __DOUS2 = false; |
||||
|
|
||||
|
int globi = 0; |
||||
|
|
||||
|
float MSRMSRJNTPOS[7]; |
||||
|
double MSRCMDJNTPOS[7]; |
||||
|
double MSRMSRCARTPOS[12]; |
||||
|
float MSRCMDCARTPOS[12]; |
||||
|
double MSRMSRJACOBIAN[42]; |
||||
|
double MSRMSRFTTCP[6]; |
||||
|
double MSRCMDPOSE[3][4]; |
||||
|
float USTarget[12]; |
||||
|
float USApproach[12]; |
||||
|
double VELOCITY = 20; |
||||
|
double ACCELARATION = 10; |
||||
|
double maxVelJnt[] = {110.0,110.0,128.0,128.0,204.0,184.0,184.0}; |
||||
|
double maxAccJnt[] = {1.0,1.0,1.0,1.0,2.0,1.0,1.0}; |
||||
|
double maxTrqJnt[] = {176.0,176.0,100.0,100.0,100.0,38.0,38.0}; |
||||
|
double maxRangeJnt[] = {170.0,120.0,170.0,120.0,170.0,120.0,170.0}; |
||||
|
|
||||
|
|
||||
|
|
||||
|
|
@ -0,0 +1,32 @@ |
|||||
|
extern bool __SVR_CURRENT_JOB; |
||||
|
extern bool __MSRMSRJNTPOS; |
||||
|
extern bool __MSRCMDJNTPOS; |
||||
|
extern bool __MSRCMDPOSE; |
||||
|
extern bool __SETVELOCITY; |
||||
|
extern bool __SETACCEL; |
||||
|
extern bool __DEBUG; |
||||
|
extern bool __POTFIELDMODE; |
||||
|
extern bool __MSRSTARTPOTFIELD; |
||||
|
extern bool __MSRSTOPPOTFIELD; |
||||
|
extern bool __MSRSETPOS; |
||||
|
extern bool __CARTMOVE; |
||||
|
extern bool __DOUS; |
||||
|
extern bool __DOUS2; |
||||
|
|
||||
|
extern int globi; |
||||
|
|
||||
|
extern float MSRMSRJNTPOS[7]; |
||||
|
extern double MSRMSRCARTPOS[12]; |
||||
|
extern float MSRCMDCARTPOS[12]; |
||||
|
extern double MSRMSRJACOBIAN[42]; |
||||
|
extern double MSRMSRFTTCP[6]; |
||||
|
extern double MSRCMDJNTPOS[7]; |
||||
|
extern double MSRCMDPOSE[3][4]; |
||||
|
extern float USTarget[12]; |
||||
|
extern float USApproach[12]; |
||||
|
extern double VELOCITY; |
||||
|
extern double ACCELARATION; |
||||
|
extern double maxVelJnt[LBR_MNJ]; |
||||
|
extern double maxAccJnt[LBR_MNJ]; |
||||
|
extern double maxTrqJnt[LBR_MNJ]; |
||||
|
extern double maxRangeJnt[LBR_MNJ]; |
@ -0,0 +1,24 @@ |
|||||
|
#include <iostream> |
||||
|
#include <sstream> |
||||
|
#include "defines.h" |
||||
|
#include "SocketObject.h" |
||||
|
#include "SvrHandling.h" |
||||
|
#include "StringTool.h" |
||||
|
#include <string> |
||||
|
#include "pthread.h" |
||||
|
#include "friremote.h" |
||||
|
#include "math.h" |
||||
|
#include <cmath> |
||||
|
#include "mat.h" |
||||
|
#include "vec.h" |
||||
|
//#include "opencv2\opencv.hpp" |
||||
|
//#pragma comment (lib, "opencv_core248d.lib") |
||||
|
|
||||
|
|
||||
|
//debug |
||||
|
#include <algorithm> |
||||
|
//end debug |
||||
|
|
||||
|
using namespace std; |
||||
|
//using namespace cv; |
||||
|
|
@ -0,0 +1,354 @@ |
|||||
|
#ifndef _MAT_H_ |
||||
|
#define _MAT_H_ |
||||
|
#include <iostream> |
||||
|
#include "vec.h" |
||||
|
|
||||
|
template <class T, unsigned SIZE> class CVector; |
||||
|
|
||||
|
// template square matrix class for SIMPLE data types |
||||
|
template <class T, unsigned SIZE> class Mat |
||||
|
{ |
||||
|
public: |
||||
|
|
||||
|
Mat<T, SIZE> () |
||||
|
{ |
||||
|
for (unsigned int j=0; j<SIZE; j++) |
||||
|
{ |
||||
|
for (unsigned int i=0; i<SIZE; i++) |
||||
|
{ |
||||
|
m_aatData[i][j] = T(0); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
~Mat<T, SIZE> () |
||||
|
{ |
||||
|
// nothing to do here ... |
||||
|
} |
||||
|
|
||||
|
Mat<T, SIZE> (const T aatData[SIZE][SIZE]) |
||||
|
{ |
||||
|
for (unsigned int j=0; j<SIZE; j++) |
||||
|
{ |
||||
|
for (unsigned int i=0; i<SIZE; i++) |
||||
|
{ |
||||
|
m_aatData[i][j] = aatData[i][j]; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
Mat<T, SIZE> (const Mat<T, SIZE> &mat) |
||||
|
{ |
||||
|
for (unsigned int j=0; j<SIZE; j++) |
||||
|
{ |
||||
|
for (unsigned int i=0; i<SIZE; i++) |
||||
|
{ |
||||
|
m_aatData[i][j] = mat.m_aatData[i][j]; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
T &operator () (unsigned i, unsigned j) |
||||
|
{ |
||||
|
if (i>=SIZE) |
||||
|
i = SIZE-1; |
||||
|
if (j>=SIZE) |
||||
|
j = SIZE-1; |
||||
|
return m_aatData[i][j]; |
||||
|
} |
||||
|
|
||||
|
T operator () (unsigned i, unsigned j) const |
||||
|
{ |
||||
|
if (i>=SIZE) |
||||
|
i = SIZE-1; |
||||
|
if (j>=SIZE) |
||||
|
j = SIZE-1; |
||||
|
return m_aatData[i][j]; |
||||
|
} |
||||
|
|
||||
|
// CMatrix<T, SIZE>operator + (const Matrix<T, SIZE> &mat) |
||||
|
// CMatrix<T, SIZE>operator - (const Matrix<T, SIZE> &mat) |
||||
|
// ... |
||||
|
|
||||
|
Mat<T, SIZE> operator * (const Mat<T, SIZE> &mat) |
||||
|
{ |
||||
|
Mat<T, SIZE> buf; |
||||
|
for (unsigned int i=0; i<SIZE; i++) // ZEILE i |
||||
|
for (unsigned int j=0; j<SIZE; j++) // Spalte j |
||||
|
for (unsigned int a=0; a<SIZE; a++) // a |
||||
|
buf(i,j) += m_aatData[i][a] * mat(a,j); |
||||
|
return buf; |
||||
|
} |
||||
|
|
||||
|
Vec<T, SIZE> operator * (const Vec<T, SIZE> &vec) |
||||
|
{ |
||||
|
Vec<T, SIZE> buf; |
||||
|
for (unsigned int j=0; j<SIZE; j++) // SPALTE j |
||||
|
for (unsigned int i=0; i<SIZE; i++) // ZEILE i |
||||
|
buf(i) += m_aatData[i][j]*vec(j); |
||||
|
return buf; |
||||
|
} |
||||
|
Mat<float, 4> inv() |
||||
|
{ |
||||
|
Mat<float,4> invOut; |
||||
|
|
||||
|
long indxc[4], indxr[4], ipiv[4]; |
||||
|
long i, icol, irow, j, ir, ic; |
||||
|
long big, dum, pivinv,temp, bb; |
||||
|
|
||||
|
ipiv[0] = -1; |
||||
|
ipiv[1] = -1; |
||||
|
ipiv[2] = -1; |
||||
|
ipiv[3] = -1; |
||||
|
|
||||
|
invOut = *this; |
||||
|
|
||||
|
|
||||
|
for (i =0; i < 4 ; i++) { |
||||
|
big =0.0f; |
||||
|
for (j =0; j < 4 ; j++) { |
||||
|
if (ipiv[j] != 0) { |
||||
|
if (ipiv[0] == - 1) { |
||||
|
if ((bb = (float) fabs(invOut(j,0))) > big) { |
||||
|
big = bb; |
||||
|
irow = j; |
||||
|
icol = 0; |
||||
|
} |
||||
|
} else if (ipiv[0] > 0) { |
||||
|
goto end; |
||||
|
} |
||||
|
|
||||
|
if (ipiv[1] == - 1) { |
||||
|
if ((bb = (float) fabs(invOut(j,1))) > big) { |
||||
|
big = bb; |
||||
|
irow = j; |
||||
|
icol = 1; |
||||
|
} |
||||
|
} else if (ipiv[1] > 0) { |
||||
|
goto end; |
||||
|
} |
||||
|
|
||||
|
if (ipiv[2] == - 1) { |
||||
|
if ((bb = (float) fabs(invOut(j,2))) > big) { |
||||
|
big = bb; |
||||
|
irow = j; |
||||
|
icol = 2; |
||||
|
} |
||||
|
} else if (ipiv[2] > 0) { |
||||
|
goto end; |
||||
|
} |
||||
|
|
||||
|
if (ipiv[3] == - 1) { |
||||
|
if ((bb = (float) fabs(invOut(j,3))) > big) { |
||||
|
big = bb; |
||||
|
irow = j; |
||||
|
icol = 3; |
||||
|
} |
||||
|
} else if (ipiv[3] > 0) { |
||||
|
goto end; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
++(ipiv[icol]); |
||||
|
|
||||
|
if (irow != icol) { |
||||
|
temp = invOut(irow,0); |
||||
|
invOut(irow, 0) = invOut(icol, 0); |
||||
|
invOut(icol, 0) = temp; |
||||
|
|
||||
|
temp = invOut(irow,1); |
||||
|
invOut(irow, 1) = invOut(icol, 1); |
||||
|
invOut(icol,1) = temp; |
||||
|
|
||||
|
temp = invOut(irow,2); |
||||
|
invOut(irow,2) = invOut(icol,2); |
||||
|
invOut(icol,2) = temp; |
||||
|
|
||||
|
temp = invOut(irow,3); |
||||
|
invOut(irow,3) = invOut(icol,3); |
||||
|
invOut(icol,3) = temp; |
||||
|
} |
||||
|
|
||||
|
indxr[i] = irow; |
||||
|
indxc[i] = icol; |
||||
|
|
||||
|
if (invOut(icol,icol) ==0.0) { |
||||
|
goto end; |
||||
|
} |
||||
|
|
||||
|
pivinv =1.0f / invOut(icol,icol); |
||||
|
invOut(icol,icol) =1.0f; |
||||
|
invOut(icol,0) *= pivinv; |
||||
|
invOut(icol,1) *= pivinv; |
||||
|
invOut(icol,2) *= pivinv; |
||||
|
invOut(icol,3) *= pivinv; |
||||
|
|
||||
|
if (icol != 0) { |
||||
|
dum = invOut(0,icol); |
||||
|
invOut(0,icol) =0.0f; |
||||
|
invOut(0,0) -= invOut(icol,0) * dum; |
||||
|
invOut(0,1) -= invOut(icol,1) * dum; |
||||
|
invOut(0,2) -= invOut(icol,2) * dum; |
||||
|
invOut(0,3) -= invOut(icol,3) * dum; |
||||
|
} |
||||
|
|
||||
|
if (icol != 1) { |
||||
|
dum = invOut(1,icol); |
||||
|
invOut(1,icol) =0.0f; |
||||
|
invOut(1,0) -= invOut(icol,0) * dum; |
||||
|
invOut(1,1) -= invOut(icol,1) * dum; |
||||
|
invOut(1,2) -= invOut(icol,2) * dum; |
||||
|
invOut(1,3) -= invOut(icol,3) * dum; |
||||
|
} |
||||
|
|
||||
|
if (icol != 2) { |
||||
|
dum = invOut(2,icol); |
||||
|
invOut(2,icol) =0.0f; |
||||
|
invOut(2,0) -= invOut(icol,0) * dum; |
||||
|
invOut(2,1) -= invOut(icol,1) * dum; |
||||
|
invOut(2,2) -= invOut(icol,2) * dum; |
||||
|
invOut(2,3) -= invOut(icol,3) * dum; |
||||
|
} |
||||
|
|
||||
|
if (icol != 3) { |
||||
|
dum = invOut(3,icol); |
||||
|
invOut(3,icol) =0.0f; |
||||
|
invOut(3,0) -= invOut(icol,0) * dum; |
||||
|
invOut(3,1) -= invOut(icol,1) * dum; |
||||
|
invOut(3,2) -= invOut(icol,2) * dum; |
||||
|
invOut(3,3) -= invOut(icol,3) * dum; |
||||
|
} |
||||
|
} |
||||
|
if (indxr[3] != indxc[3]) { |
||||
|
ir = indxr[3]; |
||||
|
ic = indxc[3]; |
||||
|
temp = invOut(0,ir); |
||||
|
invOut(0,ir) = invOut(0,ic); |
||||
|
invOut(0,ic) = temp; |
||||
|
temp = invOut(1,ir); |
||||
|
invOut(1,ir) = invOut(1,ic); |
||||
|
invOut(1,ic) = temp; |
||||
|
temp = invOut(2,ir); |
||||
|
invOut(2,ir) = invOut(2,ic); |
||||
|
invOut(2,ic) = temp; |
||||
|
temp = invOut(3,ir); |
||||
|
invOut(3,ir) = invOut(3,ic); |
||||
|
invOut(3,ic) = temp; |
||||
|
} |
||||
|
if (indxr[2] != indxc[2]) { |
||||
|
ir = indxr[2]; |
||||
|
ic = indxc[2]; |
||||
|
|
||||
|
temp = invOut(0,ir); |
||||
|
invOut(0,ir) = invOut(0,ic); |
||||
|
invOut(0,ic) = temp; |
||||
|
|
||||
|
temp = invOut(1,ir); |
||||
|
invOut(1,ir) = invOut(1,ic); |
||||
|
invOut(1,ic) = temp; |
||||
|
|
||||
|
temp = invOut(2,ir); |
||||
|
invOut(2,ir) = invOut(2,ic); |
||||
|
invOut(2,ic) = temp; |
||||
|
|
||||
|
temp = invOut(3,ir); |
||||
|
invOut(3,ir) = invOut(3,ic); |
||||
|
invOut(3,ic) = temp; |
||||
|
} |
||||
|
if (indxr[1] != indxc[1]) { |
||||
|
ir = indxr[1]; |
||||
|
ic = indxc[1]; |
||||
|
temp = invOut(0,ir); |
||||
|
invOut(0,ir) = invOut(0,ic); |
||||
|
invOut(0,ic) = temp; |
||||
|
temp = invOut(1,ir); |
||||
|
invOut(1,ir) = invOut(1,ic); |
||||
|
invOut(1,ic) = temp; |
||||
|
temp = invOut(2,ir); |
||||
|
invOut(2,ir) = invOut(2,ic); |
||||
|
invOut(2,ic) = temp; |
||||
|
temp = invOut(3,ir); |
||||
|
invOut(3,ir) = invOut(3,ic); |
||||
|
invOut(3,ic) = temp; |
||||
|
} |
||||
|
if (indxr[0] != indxc[0]) { |
||||
|
ir = indxr[0]; |
||||
|
ic = indxc[0]; |
||||
|
temp = invOut(0,ir); |
||||
|
invOut(0,ir) = invOut(0,ic); |
||||
|
invOut(0,ic) = temp; |
||||
|
temp = invOut(1,ir); |
||||
|
invOut(1,ir) = invOut(1,ic); |
||||
|
invOut(1,ic) = temp; |
||||
|
temp = invOut(2,ir); |
||||
|
invOut(2,ir) = invOut(2,ic); |
||||
|
invOut(2,ic) = temp; |
||||
|
temp = invOut(3,ir); |
||||
|
invOut(3,ir) = invOut(3,ic); |
||||
|
invOut(3,ic) = temp; |
||||
|
} |
||||
|
end: |
||||
|
return invOut; |
||||
|
} |
||||
|
|
||||
|
private: |
||||
|
T m_aatData[SIZE][SIZE]; |
||||
|
}; |
||||
|
// some common vector classes (abbr. names) |
||||
|
typedef Mat<float, 2> Mat2f; |
||||
|
typedef Mat<float, 3> Mat3f; |
||||
|
typedef Mat<float, 4> Mat4f; |
||||
|
|
||||
|
typedef Mat<double, 2> Mat2d; |
||||
|
typedef Mat<double, 3> Mat3d; |
||||
|
typedef Mat<double, 4> Mat4d; |
||||
|
|
||||
|
|
||||
|
template <class T, unsigned SIZE> |
||||
|
static std::ostream& operator<< (std::ostream& output,const Mat<T,SIZE> &mat) |
||||
|
{ |
||||
|
output << "( "; |
||||
|
for(unsigned int j =0; j< SIZE; ++j) |
||||
|
{ |
||||
|
output << "( "; |
||||
|
for(unsigned int i =0; i< SIZE; ++i) |
||||
|
{ |
||||
|
output << mat(j,i); |
||||
|
if (i<4-1) |
||||
|
output << " , "; |
||||
|
else |
||||
|
output << " )"; |
||||
|
} |
||||
|
if (j<SIZE-1) |
||||
|
output << " ) ; "; |
||||
|
else |
||||
|
output << " ) )"; |
||||
|
} |
||||
|
return output; |
||||
|
} |
||||
|
static Mat<float, 4> getRotationMatrix(float x_angle,float y_angle, float z_angle) |
||||
|
{ |
||||
|
Mat<float,4> tempx,tempy,tempz; |
||||
|
float temp_x[4][4] = { { 1, 0, 0, 0}, |
||||
|
{ 0, cos(x_angle), -sin(x_angle), 0}, |
||||
|
{ 0, sin(x_angle), cos(x_angle), 0}, |
||||
|
{ 0, 0, 0, 1} |
||||
|
}; |
||||
|
|
||||
|
float temp_y[4][4] = { { cos(y_angle), 0, -sin(y_angle), 0}, |
||||
|
{ 0, 1, 0, 0}, |
||||
|
{ sin(y_angle), 0, cos(y_angle), 0}, |
||||
|
{ 0, 0, 0, 1} |
||||
|
}; |
||||
|
float temp_z[4][4] = { { cos(z_angle), -sin(z_angle), 0, 0}, |
||||
|
{ sin(z_angle), cos(z_angle), 0, 0}, |
||||
|
{ 0, 0, 1, 0}, |
||||
|
{ 0, 0, 0, 1} |
||||
|
}; |
||||
|
|
||||
|
tempx=temp_x; |
||||
|
tempy=temp_y; |
||||
|
tempz=temp_z; |
||||
|
return tempz*tempy*tempx; |
||||
|
} |
||||
|
#endif |
@ -0,0 +1,520 @@ |
|||||
|
#include "header.h"
|
||||
|
#include "global.h"
|
||||
|
#include "sgn.h"
|
||||
|
#include <error.h>
|
||||
|
#include <errno.h>
|
||||
|
|
||||
|
void printMat(Mat4f M) |
||||
|
{ |
||||
|
#if 0
|
||||
|
for (int i=0;i<M.rows;i++) |
||||
|
{ |
||||
|
for (int j=0;j<M.cols;j++) |
||||
|
{ |
||||
|
cout << M.at<float>(i,j) << " "; |
||||
|
} |
||||
|
cout << "\n\r"; |
||||
|
} |
||||
|
cout << "\n\r\n\r"; |
||||
|
#else
|
||||
|
cout << M << endl; |
||||
|
#endif
|
||||
|
} |
||||
|
|
||||
|
float* abctomat(float a, float b, float c) |
||||
|
{ |
||||
|
Mat4f rx; |
||||
|
float ca = cos(c); |
||||
|
float sa = sin(c); |
||||
|
|
||||
|
rx(0,0) = 1; |
||||
|
rx(1,1) = ca; |
||||
|
rx(1,2) = -sa; |
||||
|
rx(2,1) = sa; |
||||
|
rx(2,2) = ca; |
||||
|
rx(3,3) = 1; |
||||
|
|
||||
|
Mat4f ry; |
||||
|
float cb = cos(b); |
||||
|
float sb = sin(b); |
||||
|
ry(0,0) = cb; |
||||
|
ry(0,2) = sb; |
||||
|
ry(1,1) = 1; |
||||
|
ry(2,0) = -sb; |
||||
|
ry(2,2) = cb; |
||||
|
ry(3,3) = 1; |
||||
|
|
||||
|
Mat4f rz; |
||||
|
float cc = cos(a); |
||||
|
float sc = sin(a); |
||||
|
rz(0,0) = cc; |
||||
|
rz(0,1) = -sc; |
||||
|
rz(1,0) = sc; |
||||
|
rz(1,1) = cc; |
||||
|
rz(2,2) = 1; |
||||
|
rz(3,3) = 1; |
||||
|
|
||||
|
Mat4f result; |
||||
|
Mat4f temp; |
||||
|
temp = rz * ry; |
||||
|
result = temp * rx; |
||||
|
|
||||
|
#ifdef __DEBUG__
|
||||
|
printMat(rx); |
||||
|
printMat(ry); |
||||
|
printMat(rz); |
||||
|
printMat(result); |
||||
|
#endif
|
||||
|
|
||||
|
float *res = new float[12]; |
||||
|
//TODO simple converter for mat
|
||||
|
for (int j=0;j<3;j++) |
||||
|
{ |
||||
|
for (int k=0;k<4;k++) |
||||
|
{ |
||||
|
res[j*4+k] = result(j,k); |
||||
|
} |
||||
|
} |
||||
|
return res; |
||||
|
} |
||||
|
|
||||
|
float* mattoabc(float M[12]) |
||||
|
{ |
||||
|
float norm; |
||||
|
float sa; |
||||
|
float ca; |
||||
|
float *abc = new float[3]; |
||||
|
|
||||
|
norm = sqrt((M[0]*M[0])+(M[4]*M[4])); |
||||
|
|
||||
|
if (norm>1e-5) |
||||
|
{ |
||||
|
sa = M[4]/norm; |
||||
|
ca = M[0]/norm; |
||||
|
abc[0] = atan2(sa,ca); |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
sa = 0; |
||||
|
ca = 1; |
||||
|
abc[0] = 0; |
||||
|
} |
||||
|
abc[1] = atan2(-M[8],ca*M[0]+sa*M[4]); |
||||
|
abc[2] = atan2(sa*M[2]-ca*M[6],-sa*M[1]+ca*M[5]); |
||||
|
return abc; |
||||
|
} |
||||
|
|
||||
|
void doRalf() |
||||
|
{ |
||||
|
// Global definitions
|
||||
|
float lowStiff[6] = { 0.01f, 0.01f, 0.01f, 0.01f, 0.01f, 0.01f}; |
||||
|
float highStiff[6] = {1000.0f, 1000.0f, 1000.0f, 10.0f, 10.0f, 10.0f}; |
||||
|
float slowDamp[6] = { 0.007f, 0.007f, 0.007f, 0.007f, 0.007f, 0.007f}; |
||||
|
float fastDamp[6] = { 0.7f, 0.7f, 0.7f, 0.7f, 0.7f, 0.7f}; |
||||
|
|
||||
|
float pos1[12] = { |
||||
|
1.0f, 0.0f, 0.0f, 500.0f, |
||||
|
0.0f, 1.0f, 0.0f, 0.0f, |
||||
|
0.0f, 0.0f, 1.0f, 500.0f |
||||
|
}; |
||||
|
float pos2[12] = { |
||||
|
1.0f, 0.0f, 0.0f , 500.0f, |
||||
|
0.0f, 1.0f, 0.0f , 0.0f, |
||||
|
0.0f, 0.0f ,1.0f , 500.0f |
||||
|
}; |
||||
|
|
||||
|
friRemote friInst; |
||||
|
double timeCounter=0; |
||||
|
friInst.doDataExchange(); |
||||
|
|
||||
|
float* cartPos; |
||||
|
while(true) |
||||
|
{ |
||||
|
// Time
|
||||
|
timeCounter+=friInst.getSampleTime(); |
||||
|
|
||||
|
friInst.doReceiveData(); |
||||
|
|
||||
|
// Get all variables from FRI
|
||||
|
float* jntPos = friInst.getMsrMsrJntPosition(); |
||||
|
float* jacobian = friInst.getJacobian(); |
||||
|
float* ftTcp = friInst.getFTTcp(); |
||||
|
|
||||
|
if (timeCounter < 20) |
||||
|
cartPos = friInst.getMsrCartPosition(); |
||||
|
//friInst.doDataExchange();
|
||||
|
//friInst.doCartesianImpedanceControl(cartPos, highStiff, fastDamp, NULL, NULL, true);
|
||||
|
#if 0
|
||||
|
if (timeCounter>10 && timeCounter<10) |
||||
|
{ |
||||
|
friInst.doCartesianImpedanceControl(cartPos, highStiff, fastDamp, NULL, NULL, false); |
||||
|
} else |
||||
|
{ |
||||
|
friInst.doCartesianImpedanceControl(cartPos, highStiff, fastDamp, NULL, NULL, false); |
||||
|
} |
||||
|
#endif
|
||||
|
float npos[12]; |
||||
|
memcpy(npos,cartPos,12); |
||||
|
friInst.doCartesianImpedanceControl(npos, highStiff, fastDamp, NULL, NULL, false); |
||||
|
|
||||
|
#if 0
|
||||
|
if (timeCounter<20) |
||||
|
{ |
||||
|
friInst.doCartesianImpedanceControl(Test, highStiff, fastDamp, NULL, NULL, true); |
||||
|
} else if (timeCounter<30) |
||||
|
{ |
||||
|
friInst.doCartesianImpedanceControl(cartPos, highStiff, fastDamp, NULL, NULL, true); |
||||
|
} else if (timeCounter<40) |
||||
|
{ |
||||
|
friInst.doCartesianImpedanceControl(cartPos , highStiff, fastDamp, NULL, NULL, true); |
||||
|
} else |
||||
|
{ |
||||
|
friInst.doDataExchange(); |
||||
|
} |
||||
|
#endif
|
||||
|
friInst.doSendData(); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
Mat4f vecToMat2(float vec[12]) |
||||
|
{ |
||||
|
Mat4f result; |
||||
|
for (int i=0; i<3; i++) |
||||
|
{ |
||||
|
for (int j=0; j<4; j++) |
||||
|
{ |
||||
|
result(i,j) = (float)vec[i*4+j]; |
||||
|
} |
||||
|
} |
||||
|
result(3,3)=(float)1; |
||||
|
return result; |
||||
|
} |
||||
|
|
||||
|
float* matToVec2(Mat4f mat) |
||||
|
{ |
||||
|
float* vec = new float[12]; |
||||
|
for (int j=0;j<3;j++) |
||||
|
{ |
||||
|
for (int k=0;k<4;k++) |
||||
|
{ |
||||
|
vec[j*4+k] = mat(j,k); |
||||
|
} |
||||
|
} |
||||
|
return vec; |
||||
|
} |
||||
|
|
||||
|
float* vectoquat(float vec[12]) |
||||
|
{ |
||||
|
float *quat = new float[4]; |
||||
|
float diag[3]; |
||||
|
int v; int w; int u; |
||||
|
diag[0] = vec[0]; |
||||
|
diag[1] = vec[5]; |
||||
|
diag[2] = vec[10]; |
||||
|
float u_ = *std::max_element(diag,diag+2); |
||||
|
|
||||
|
if (u_==diag[0]) |
||||
|
{ |
||||
|
u = 1; |
||||
|
v = 2; |
||||
|
w = 3; |
||||
|
} else if (u_==diag[1]) |
||||
|
{ |
||||
|
u = 2; |
||||
|
v = 3; |
||||
|
w = 1; |
||||
|
} else |
||||
|
{ |
||||
|
u = 3; |
||||
|
v = 1; |
||||
|
w = 2; |
||||
|
} |
||||
|
float r = sqrt(1+vec[(u-1)*4+(u-1)] - vec[(v-1)*4+(v-1)] - vec[(w-1)*4+(w-1)]); |
||||
|
quat[0] = (vec[(w-1)*4+(v-1)] - vec[(v-1)*4+(w-1)]) / (2*r); |
||||
|
quat[u] = r/2; |
||||
|
quat[v] = (vec[(u-1)*4+(v-1)] + vec[(v-1)*4+(u-1)]) / (2*r); |
||||
|
quat[w] = (vec[(w-1)*4+(u-1)] + vec[(u-1)*4+(w-1)]) / (2*r); |
||||
|
|
||||
|
return quat; |
||||
|
} |
||||
|
|
||||
|
float* quattovec(float quat[4]) |
||||
|
{ |
||||
|
float *vec = new float[12]; |
||||
|
vec[0] = quat[0]*quat[0]+quat[1]*quat[1]-quat[2]*quat[2]-quat[3]*quat[3]; |
||||
|
vec[4] = 2*(quat[1]*quat[2]+quat[0]*quat[3]); |
||||
|
vec[8] = 2*(quat[1]*quat[3]-quat[0]*quat[2]); |
||||
|
|
||||
|
vec[1] = 2*(quat[1]*quat[2]-quat[0]*quat[3]); |
||||
|
vec[5] = quat[0]*quat[0]-quat[1]*quat[1]+quat[2]*quat[2]-quat[3]*quat[3]; |
||||
|
vec[9] = 2*(quat[2]*quat[3]+quat[0]*quat[1]); |
||||
|
|
||||
|
vec[2] = 2*(quat[1]*quat[3]+quat[0]*quat[2]); |
||||
|
vec[6] = 2*(quat[2]*quat[3]-quat[0]*quat[1]); |
||||
|
vec[10] = quat[0]*quat[0]-quat[1]*quat[1]-quat[2]*quat[2]+quat[3]*quat[3]; |
||||
|
|
||||
|
return vec; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
void *threadFriDataExchange(void *arg) |
||||
|
{ |
||||
|
//doRalf();
|
||||
|
|
||||
|
friRemote friInst; |
||||
|
|
||||
|
while (1) |
||||
|
{ |
||||
|
//#######################################
|
||||
|
// Communication loop
|
||||
|
|
||||
|
// get current joint positions
|
||||
|
for ( int i= 0; i < LBR_MNJ; i++) |
||||
|
{ |
||||
|
MSRMSRJNTPOS[i] = friInst.getMsrCmdJntPosition()[i] + friInst.getMsrCmdJntPositionOffset()[i]; |
||||
|
//MSRMSRJNTPOS[i] = friInst.getMsrMsrJntPosition()[i];
|
||||
|
} |
||||
|
|
||||
|
// get current jacobian
|
||||
|
float* friJacobian = friInst.getJacobian(); |
||||
|
if ( friJacobian == NULL) |
||||
|
{ |
||||
|
fprintf(stderr,"Failed: could not get jacobian\n"); |
||||
|
break; |
||||
|
} |
||||
|
for (int i = 0; i < FRI_CART_VEC*LBR_MNJ ; i++) |
||||
|
{ |
||||
|
MSRMSRJACOBIAN[i] = friJacobian[i]; |
||||
|
} |
||||
|
|
||||
|
// get current messured carthesian position
|
||||
|
float* friMsrCartPosition = friInst.getMsrCartPosition(); |
||||
|
if ( friMsrCartPosition == NULL) |
||||
|
{ |
||||
|
fprintf(stderr,"Failed: could not get Messurement in Carthesian Position\n"); |
||||
|
break; |
||||
|
} |
||||
|
for ( int i =0; i < FRI_CART_FRM_DIM; i++) |
||||
|
{ |
||||
|
MSRMSRCARTPOS[i] = friMsrCartPosition[i]; |
||||
|
} |
||||
|
|
||||
|
// get current force and torque
|
||||
|
float* friFTTcp = friInst.getFTTcp(); |
||||
|
for ( int i = 0; i < FRI_CART_VEC; i++) |
||||
|
{ |
||||
|
MSRMSRFTTCP[i] = friFTTcp[i]; |
||||
|
} |
||||
|
|
||||
|
//#########################################################
|
||||
|
// PTP Joint Movement
|
||||
|
if (__MSRCMDJNTPOS) |
||||
|
{ |
||||
|
double maxVelJntLocal[LBR_MNJ]; |
||||
|
double maxAccJntLocal[LBR_MNJ]; |
||||
|
double delta[LBR_MNJ]; |
||||
|
double sampleTime = (double)0.005; |
||||
|
double deltaAbs[LBR_MNJ]; |
||||
|
double dMaxSpeed[LBR_MNJ]; |
||||
|
double lMaxSpeed[LBR_MNJ]; |
||||
|
double dGesamt[LBR_MNJ]; |
||||
|
|
||||
|
double currentInk[LBR_MNJ] = {0}; |
||||
|
double currentInkLast[LBR_MNJ] = {0}; |
||||
|
double currentDist [LBR_MNJ] = {0}; |
||||
|
double currentDistLast [LBR_MNJ] = {0}; |
||||
|
|
||||
|
// calculate delta positions of movement
|
||||
|
for ( int i= 0; i < LBR_MNJ; i++) |
||||
|
{ |
||||
|
delta[i] = MSRCMDJNTPOS[i]-(MSRMSRJNTPOS[i]*180/M_PI); |
||||
|
deltaAbs[i] = fabs(MSRCMDJNTPOS[i]-(MSRMSRJNTPOS[i]*180/M_PI)); |
||||
|
maxVelJntLocal[i] = maxVelJnt[i]*sampleTime*(VELOCITY/100.0); |
||||
|
maxAccJntLocal[i] = maxAccJnt[i]*sampleTime*(ACCELARATION/100.0); |
||||
|
} |
||||
|
|
||||
|
// calculate movement steps
|
||||
|
for (int j=0; j<LBR_MNJ; j++) |
||||
|
{ |
||||
|
dMaxSpeed[j] = maxVelJntLocal[j]/maxAccJntLocal[j]; |
||||
|
lMaxSpeed[j] = dMaxSpeed[j]*dMaxSpeed[j]*maxAccJntLocal[j]*0.5; |
||||
|
if (lMaxSpeed[j] > deltaAbs[j]/(double)2.0) |
||||
|
{ |
||||
|
dGesamt[j] = sqrt(deltaAbs[j]/maxAccJntLocal[j])*2.0; |
||||
|
} else |
||||
|
{ |
||||
|
dGesamt[j] = dMaxSpeed[j]*2 + (deltaAbs[j]-lMaxSpeed[j]*2.0)/maxVelJntLocal[j]; |
||||
|
} |
||||
|
} |
||||
|
int maxSteps =ceil(*max_element(dGesamt,(dGesamt+LBR_MNJ-1))); |
||||
|
|
||||
|
if (maxSteps == 0 || maxSteps == 1) |
||||
|
goto end; |
||||
|
|
||||
|
for (int j=0; j<LBR_MNJ; j++) |
||||
|
{ |
||||
|
dMaxSpeed[j] = ceil(maxSteps/(double)2 - sqrt((maxSteps/(double)2)*(maxSteps/(double)2) - deltaAbs[j]/maxAccJntLocal[j])); |
||||
|
double temp = maxSteps/(double)2 - sqrt((maxSteps/(double)2)*(maxSteps/(double)2) - deltaAbs[j]/maxAccJntLocal[j]); |
||||
|
if (dMaxSpeed[j]==0) |
||||
|
{ |
||||
|
maxAccJntLocal[j] = 0; |
||||
|
} else |
||||
|
{ |
||||
|
maxAccJntLocal[j] = -deltaAbs[j]/(dMaxSpeed[j]*dMaxSpeed[j]-maxSteps*dMaxSpeed[j]); |
||||
|
} |
||||
|
maxVelJntLocal[j] = dMaxSpeed[j]*maxAccJntLocal[j]; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
for (int i=0;i<maxSteps;i++) |
||||
|
{ |
||||
|
for (int j=0;j<LBR_MNJ;j++) |
||||
|
{ |
||||
|
if (i+1 <= maxSteps/(double)2) |
||||
|
{ |
||||
|
currentInk[j] = min(currentInkLast[j]+maxAccJntLocal[j],maxVelJntLocal[j]); |
||||
|
}else if (i+1 > maxSteps-dMaxSpeed[j]) |
||||
|
{ |
||||
|
currentInk[j] = max(currentInkLast[j]-maxAccJntLocal[j],(double)0); |
||||
|
}else |
||||
|
{ |
||||
|
currentInk[j] = currentInkLast[j]; |
||||
|
} |
||||
|
currentDist[j] = currentDistLast[j] + sgn(delta[j])*currentInk[j]; |
||||
|
currentInkLast[j] = currentInk[j]; |
||||
|
currentDistLast[j] = currentDist[j]; |
||||
|
MSRMSRJNTPOS[j]+= sgn(delta[j])*currentInk[j]*(1./180*M_PI); |
||||
|
} |
||||
|
friInst.doPositionControl(MSRMSRJNTPOS); |
||||
|
} |
||||
|
end: |
||||
|
__MSRCMDJNTPOS = false; |
||||
|
|
||||
|
} else if (__CARTMOVE) |
||||
|
{ |
||||
|
//##########################################################
|
||||
|
//Cartesian Movement
|
||||
|
|
||||
|
const float Stiff[6] = {1000.0, 1000.0, 1000.0, 150.0, 150.0, 150.0}; |
||||
|
const float Damp[6] = {0.7, 0.7, 0.7, 0.7, 0.7, 0.7}; |
||||
|
float th = 0.000; |
||||
|
float deltaCart[12]; |
||||
|
float Pos[12]; |
||||
|
float dist; |
||||
|
float rot; |
||||
|
float sum; |
||||
|
float b; |
||||
|
float c; |
||||
|
float t_fact = 1; |
||||
|
float t_outerT = 0.007; |
||||
|
float t_innerT = 0.000; |
||||
|
float t_outerR = 0.007; |
||||
|
float t_innerR = 0.000; |
||||
|
|
||||
|
while (true) |
||||
|
{ |
||||
|
for ( int i =0; i < FRI_CART_FRM_DIM; i++) |
||||
|
{ |
||||
|
Pos[i] = friInst.getMsrCartPosition()[i]; |
||||
|
MSRMSRCARTPOS[i] = friInst.getMsrCartPosition()[i]; |
||||
|
deltaCart[i] = MSRCMDCARTPOS[i]-Pos[i]; |
||||
|
} |
||||
|
sum = 0; |
||||
|
for (int i=0; i<3 ; i++) |
||||
|
{ |
||||
|
sum = sum + (deltaCart[(i*4)+3]*deltaCart[(i*4)+3]); |
||||
|
} |
||||
|
dist = sqrt(sum); |
||||
|
sum = 0; |
||||
|
for (int i=0;i<12;i++) |
||||
|
{ |
||||
|
if (i != 3 && i != 7 && i != 11) |
||||
|
{ |
||||
|
sum = sum + deltaCart[i]*deltaCart[i]; |
||||
|
} |
||||
|
} |
||||
|
rot = sqrt(sum); |
||||
|
b = t_fact*max((float)0.0,(float)min((float)1.0,(t_outerT-dist+(t_innerT-t_outerT))*(1/(t_innerT-t_outerT)))); |
||||
|
c = t_fact*max((float)0.0,(float)min((float)1.0,(float)(t_outerR-rot+(t_innerR-t_outerR))*(float)(1/(t_innerR-t_outerR)))); |
||||
|
|
||||
|
if (dist < th) |
||||
|
{ |
||||
|
for (int i=0; i<3; i++) |
||||
|
{ |
||||
|
deltaCart[(i*4)+3] = 0; |
||||
|
} |
||||
|
}else |
||||
|
{ |
||||
|
for (int i=0; i<3; i++) |
||||
|
{ |
||||
|
deltaCart[(i*4)+3] = (deltaCart[(i*4)+3] / dist)*b; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
// check offset to point
|
||||
|
if (rot < th) |
||||
|
{ |
||||
|
for (int i=0;i<12;i++) |
||||
|
{ |
||||
|
if (i != 3 && i != 7 && i != 11) |
||||
|
{ |
||||
|
deltaCart[i] = 0; |
||||
|
} |
||||
|
} |
||||
|
}else |
||||
|
{ |
||||
|
for (int i=0;i<12;i++) |
||||
|
{ |
||||
|
if (i != 3 && i != 7 && i != 11) |
||||
|
{ |
||||
|
deltaCart[i] = (deltaCart[i] / rot)*c; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
for (int i=0;i<12;i++) |
||||
|
{ |
||||
|
Pos[i]+= deltaCart[i]*0.02; |
||||
|
} |
||||
|
friInst.doCartesianImpedanceControl(Pos, Stiff,Damp,NULL,NULL, true); |
||||
|
|
||||
|
} |
||||
|
} |
||||
|
//float Stiff[6] = {1000.0, 1000.0, 1000.0, 10.0, 10.0, 10.0};
|
||||
|
//float Damp[6] = {0.7, 0.7, 0.7, 0.7, 0.7, 0.7};
|
||||
|
//float Test[12] = {MSRMSRCARTPOS[0],MSRMSRCARTPOS[1],MSRMSRCARTPOS[2],MSRMSRCARTPOS[3],MSRMSRCARTPOS[4],MSRMSRCARTPOS[5],MSRMSRCARTPOS[6],MSRMSRCARTPOS[7],MSRMSRCARTPOS[8],MSRMSRCARTPOS[9],MSRMSRCARTPOS[10],MSRMSRCARTPOS[11]};
|
||||
|
//friInst.doCartesianImpedanceControl(Test,Stiff, Damp, NULL, NULL, true);
|
||||
|
|
||||
|
friInst.doPositionControl(MSRMSRJNTPOS); |
||||
|
|
||||
|
//i = 0;
|
||||
|
//}
|
||||
|
//friInst.doCartesianImpedanceControl(Test,Stiff, Damp, NULL, NULL, true);
|
||||
|
} |
||||
|
return NULL; |
||||
|
} |
||||
|
|
||||
|
int main() |
||||
|
{ |
||||
|
int err = 0; |
||||
|
//Setting pthread for FRI interface
|
||||
|
pthread_t fri_t; |
||||
|
//Start fri_thread
|
||||
|
err = pthread_create(&fri_t,NULL,&threadFriDataExchange,NULL); |
||||
|
if (err > 0 ) |
||||
|
{ |
||||
|
cerr << "Failed: could not create thread\n" << endl; |
||||
|
return err; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
//Start client handling
|
||||
|
SvrHandling *svr = new SvrHandling(); |
||||
|
if (svr == NULL) |
||||
|
{ |
||||
|
cerr << "Failed: could not create server \n" << endl; |
||||
|
return -ENOMEM; |
||||
|
} |
||||
|
svr->run(SVR_DEFAULT_PORT); |
||||
|
|
||||
|
return 0; |
||||
|
} |
1368
lwrserv/pthread/pthread.h
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
@ -0,0 +1,183 @@ |
|||||
|
/* |
||||
|
* Module: sched.h |
||||
|
* |
||||
|
* Purpose: |
||||
|
* Provides an implementation of POSIX realtime extensions |
||||
|
* as defined in |
||||
|
* |
||||
|
* POSIX 1003.1b-1993 (POSIX.1b) |
||||
|
* |
||||
|
* -------------------------------------------------------------------------- |
||||
|
* |
||||
|
* Pthreads-win32 - POSIX Threads Library for Win32 |
||||
|
* Copyright(C) 1998 John E. Bossom |
||||
|
* Copyright(C) 1999,2005 Pthreads-win32 contributors |
||||
|
* |
||||
|
* Contact Email: rpj@callisto.canberra.edu.au |
||||
|
* |
||||
|
* The current list of contributors is contained |
||||
|
* in the file CONTRIBUTORS included with the source |
||||
|
* code distribution. The list can also be seen at the |
||||
|
* following World Wide Web location: |
||||
|
* http://sources.redhat.com/pthreads-win32/contributors.html |
||||
|
* |
||||
|
* This library is free software; you can redistribute it and/or |
||||
|
* modify it under the terms of the GNU Lesser General Public |
||||
|
* License as published by the Free Software Foundation; either |
||||
|
* version 2 of the License, or (at your option) any later version. |
||||
|
* |
||||
|
* This library 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 |
||||
|
* Lesser General Public License for more details. |
||||
|
* |
||||
|
* You should have received a copy of the GNU Lesser General Public |
||||
|
* License along with this library in the file COPYING.LIB; |
||||
|
* if not, write to the Free Software Foundation, Inc., |
||||
|
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA |
||||
|
*/ |
||||
|
#if !defined(_SCHED_H) |
||||
|
#define _SCHED_H |
||||
|
|
||||
|
#undef PTW32_SCHED_LEVEL |
||||
|
|
||||
|
#if defined(_POSIX_SOURCE) |
||||
|
#define PTW32_SCHED_LEVEL 0 |
||||
|
/* Early POSIX */ |
||||
|
#endif |
||||
|
|
||||
|
#if defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 199309 |
||||
|
#undef PTW32_SCHED_LEVEL |
||||
|
#define PTW32_SCHED_LEVEL 1 |
||||
|
/* Include 1b, 1c and 1d */ |
||||
|
#endif |
||||
|
|
||||
|
#if defined(INCLUDE_NP) |
||||
|
#undef PTW32_SCHED_LEVEL |
||||
|
#define PTW32_SCHED_LEVEL 2 |
||||
|
/* Include Non-Portable extensions */ |
||||
|
#endif |
||||
|
|
||||
|
#define PTW32_SCHED_LEVEL_MAX 3 |
||||
|
|
||||
|
#if ( defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 200112 ) || !defined(PTW32_SCHED_LEVEL) |
||||
|
#define PTW32_SCHED_LEVEL PTW32_SCHED_LEVEL_MAX |
||||
|
/* Include everything */ |
||||
|
#endif |
||||
|
|
||||
|
|
||||
|
#if defined(__GNUC__) && !defined(__declspec) |
||||
|
# error Please upgrade your GNU compiler to one that supports __declspec. |
||||
|
#endif |
||||
|
|
||||
|
/* |
||||
|
* When building the library, you should define PTW32_BUILD so that |
||||
|
* the variables/functions are exported correctly. When using the library, |
||||
|
* do NOT define PTW32_BUILD, and then the variables/functions will |
||||
|
* be imported correctly. |
||||
|
*/ |
||||
|
#if !defined(PTW32_STATIC_LIB) |
||||
|
# if defined(PTW32_BUILD) |
||||
|
# define PTW32_DLLPORT __declspec (dllexport) |
||||
|
# else |
||||
|
# define PTW32_DLLPORT __declspec (dllimport) |
||||
|
# endif |
||||
|
#else |
||||
|
# define PTW32_DLLPORT |
||||
|
#endif |
||||
|
|
||||
|
/* |
||||
|
* This is a duplicate of what is in the autoconf config.h, |
||||
|
* which is only used when building the pthread-win32 libraries. |
||||
|
*/ |
||||
|
|
||||
|
#if !defined(PTW32_CONFIG_H) |
||||
|
# if defined(WINCE) |
||||
|
# define NEED_ERRNO |
||||
|
# define NEED_SEM |
||||
|
# endif |
||||
|
# if defined(__MINGW64__) |
||||
|
# define HAVE_STRUCT_TIMESPEC |
||||
|
# define HAVE_MODE_T |
||||
|
# elif defined(_UWIN) || defined(__MINGW32__) |
||||
|
# define HAVE_MODE_T |
||||
|
# endif |
||||
|
#endif |
||||
|
|
||||
|
/* |
||||
|
* |
||||
|
*/ |
||||
|
|
||||
|
#if PTW32_SCHED_LEVEL >= PTW32_SCHED_LEVEL_MAX |
||||
|
#if defined(NEED_ERRNO) |
||||
|
#include "need_errno.h" |
||||
|
#else |
||||
|
#include <errno.h> |
||||
|
#endif |
||||
|
#endif /* PTW32_SCHED_LEVEL >= PTW32_SCHED_LEVEL_MAX */ |
||||
|
|
||||
|
#if (defined(__MINGW64__) || defined(__MINGW32__)) || defined(_UWIN) |
||||
|
# if PTW32_SCHED_LEVEL >= PTW32_SCHED_LEVEL_MAX |
||||
|
/* For pid_t */ |
||||
|
# include <sys/types.h> |
||||
|
/* Required by Unix 98 */ |
||||
|
# include <time.h> |
||||
|
# else |
||||
|
typedef int pid_t; |
||||
|
# endif |
||||
|
#else |
||||
|
typedef int pid_t; |
||||
|
#endif |
||||
|
|
||||
|
/* Thread scheduling policies */ |
||||
|
|
||||
|
enum { |
||||
|
SCHED_OTHER = 0, |
||||
|
SCHED_FIFO, |
||||
|
SCHED_RR, |
||||
|
SCHED_MIN = SCHED_OTHER, |
||||
|
SCHED_MAX = SCHED_RR |
||||
|
}; |
||||
|
|
||||
|
struct sched_param { |
||||
|
int sched_priority; |
||||
|
}; |
||||
|
|
||||
|
#if defined(__cplusplus) |
||||
|
extern "C" |
||||
|
{ |
||||
|
#endif /* __cplusplus */ |
||||
|
|
||||
|
PTW32_DLLPORT int __cdecl sched_yield (void); |
||||
|
|
||||
|
PTW32_DLLPORT int __cdecl sched_get_priority_min (int policy); |
||||
|
|
||||
|
PTW32_DLLPORT int __cdecl sched_get_priority_max (int policy); |
||||
|
|
||||
|
PTW32_DLLPORT int __cdecl sched_setscheduler (pid_t pid, int policy); |
||||
|
|
||||
|
PTW32_DLLPORT int __cdecl sched_getscheduler (pid_t pid); |
||||
|
|
||||
|
/* |
||||
|
* Note that this macro returns ENOTSUP rather than |
||||
|
* ENOSYS as might be expected. However, returning ENOSYS |
||||
|
* should mean that sched_get_priority_{min,max} are |
||||
|
* not implemented as well as sched_rr_get_interval. |
||||
|
* This is not the case, since we just don't support |
||||
|
* round-robin scheduling. Therefore I have chosen to |
||||
|
* return the same value as sched_setscheduler when |
||||
|
* SCHED_RR is passed to it. |
||||
|
*/ |
||||
|
#define sched_rr_get_interval(_pid, _interval) \ |
||||
|
( errno = ENOTSUP, (int) -1 ) |
||||
|
|
||||
|
|
||||
|
#if defined(__cplusplus) |
||||
|
} /* End of extern "C" */ |
||||
|
#endif /* __cplusplus */ |
||||
|
|
||||
|
#undef PTW32_SCHED_LEVEL |
||||
|
#undef PTW32_SCHED_LEVEL_MAX |
||||
|
|
||||
|
#endif /* !_SCHED_H */ |
||||
|
|
@ -0,0 +1,169 @@ |
|||||
|
/* |
||||
|
* Module: semaphore.h |
||||
|
* |
||||
|
* Purpose: |
||||
|
* Semaphores aren't actually part of the PThreads standard. |
||||
|
* They are defined by the POSIX Standard: |
||||
|
* |
||||
|
* POSIX 1003.1b-1993 (POSIX.1b) |
||||
|
* |
||||
|
* -------------------------------------------------------------------------- |
||||
|
* |
||||
|
* Pthreads-win32 - POSIX Threads Library for Win32 |
||||
|
* Copyright(C) 1998 John E. Bossom |
||||
|
* Copyright(C) 1999,2005 Pthreads-win32 contributors |
||||
|
* |
||||
|
* Contact Email: rpj@callisto.canberra.edu.au |
||||
|
* |
||||
|
* The current list of contributors is contained |
||||
|
* in the file CONTRIBUTORS included with the source |
||||
|
* code distribution. The list can also be seen at the |
||||
|
* following World Wide Web location: |
||||
|
* http://sources.redhat.com/pthreads-win32/contributors.html |
||||
|
* |
||||
|
* This library is free software; you can redistribute it and/or |
||||
|
* modify it under the terms of the GNU Lesser General Public |
||||
|
* License as published by the Free Software Foundation; either |
||||
|
* version 2 of the License, or (at your option) any later version. |
||||
|
* |
||||
|
* This library 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 |
||||
|
* Lesser General Public License for more details. |
||||
|
* |
||||
|
* You should have received a copy of the GNU Lesser General Public |
||||
|
* License along with this library in the file COPYING.LIB; |
||||
|
* if not, write to the Free Software Foundation, Inc., |
||||
|
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA |
||||
|
*/ |
||||
|
#if !defined( SEMAPHORE_H ) |
||||
|
#define SEMAPHORE_H |
||||
|
|
||||
|
#undef PTW32_SEMAPHORE_LEVEL |
||||
|
|
||||
|
#if defined(_POSIX_SOURCE) |
||||
|
#define PTW32_SEMAPHORE_LEVEL 0 |
||||
|
/* Early POSIX */ |
||||
|
#endif |
||||
|
|
||||
|
#if defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 199309 |
||||
|
#undef PTW32_SEMAPHORE_LEVEL |
||||
|
#define PTW32_SEMAPHORE_LEVEL 1 |
||||
|
/* Include 1b, 1c and 1d */ |
||||
|
#endif |
||||
|
|
||||
|
#if defined(INCLUDE_NP) |
||||
|
#undef PTW32_SEMAPHORE_LEVEL |
||||
|
#define PTW32_SEMAPHORE_LEVEL 2 |
||||
|
/* Include Non-Portable extensions */ |
||||
|
#endif |
||||
|
|
||||
|
#define PTW32_SEMAPHORE_LEVEL_MAX 3 |
||||
|
|
||||
|
#if !defined(PTW32_SEMAPHORE_LEVEL) |
||||
|
#define PTW32_SEMAPHORE_LEVEL PTW32_SEMAPHORE_LEVEL_MAX |
||||
|
/* Include everything */ |
||||
|
#endif |
||||
|
|
||||
|
#if defined(__GNUC__) && ! defined (__declspec) |
||||
|
# error Please upgrade your GNU compiler to one that supports __declspec. |
||||
|
#endif |
||||
|
|
||||
|
/* |
||||
|
* When building the library, you should define PTW32_BUILD so that |
||||
|
* the variables/functions are exported correctly. When using the library, |
||||
|
* do NOT define PTW32_BUILD, and then the variables/functions will |
||||
|
* be imported correctly. |
||||
|
*/ |
||||
|
#if !defined(PTW32_STATIC_LIB) |
||||
|
# if defined(PTW32_BUILD) |
||||
|
# define PTW32_DLLPORT __declspec (dllexport) |
||||
|
# else |
||||
|
# define PTW32_DLLPORT __declspec (dllimport) |
||||
|
# endif |
||||
|
#else |
||||
|
# define PTW32_DLLPORT |
||||
|
#endif |
||||
|
|
||||
|
/* |
||||
|
* This is a duplicate of what is in the autoconf config.h, |
||||
|
* which is only used when building the pthread-win32 libraries. |
||||
|
*/ |
||||
|
|
||||
|
#if !defined(PTW32_CONFIG_H) |
||||
|
# if defined(WINCE) |
||||
|
# define NEED_ERRNO |
||||
|
# define NEED_SEM |
||||
|
# endif |
||||
|
# if defined(__MINGW64__) |
||||
|
# define HAVE_STRUCT_TIMESPEC |
||||
|
# define HAVE_MODE_T |
||||
|
# elif defined(_UWIN) || defined(__MINGW32__) |
||||
|
# define HAVE_MODE_T |
||||
|
# endif |
||||
|
#endif |
||||
|
|
||||
|
/* |
||||
|
* |
||||
|
*/ |
||||
|
|
||||
|
#if PTW32_SEMAPHORE_LEVEL >= PTW32_SEMAPHORE_LEVEL_MAX |
||||
|
#if defined(NEED_ERRNO) |
||||
|
#include "need_errno.h" |
||||
|
#else |
||||
|
#include <errno.h> |
||||
|
#endif |
||||
|
#endif /* PTW32_SEMAPHORE_LEVEL >= PTW32_SEMAPHORE_LEVEL_MAX */ |
||||
|
|
||||
|
#define _POSIX_SEMAPHORES |
||||
|
|
||||
|
#if defined(__cplusplus) |
||||
|
extern "C" |
||||
|
{ |
||||
|
#endif /* __cplusplus */ |
||||
|
|
||||
|
#if !defined(HAVE_MODE_T) |
||||
|
typedef unsigned int mode_t; |
||||
|
#endif |
||||
|
|
||||
|
|
||||
|
typedef struct sem_t_ * sem_t; |
||||
|
|
||||
|
PTW32_DLLPORT int __cdecl sem_init (sem_t * sem, |
||||
|
int pshared, |
||||
|
unsigned int value); |
||||
|
|
||||
|
PTW32_DLLPORT int __cdecl sem_destroy (sem_t * sem); |
||||
|
|
||||
|
PTW32_DLLPORT int __cdecl sem_trywait (sem_t * sem); |
||||
|
|
||||
|
PTW32_DLLPORT int __cdecl sem_wait (sem_t * sem); |
||||
|
|
||||
|
PTW32_DLLPORT int __cdecl sem_timedwait (sem_t * sem, |
||||
|
const struct timespec * abstime); |
||||
|
|
||||
|
PTW32_DLLPORT int __cdecl sem_post (sem_t * sem); |
||||
|
|
||||
|
PTW32_DLLPORT int __cdecl sem_post_multiple (sem_t * sem, |
||||
|
int count); |
||||
|
|
||||
|
PTW32_DLLPORT int __cdecl sem_open (const char * name, |
||||
|
int oflag, |
||||
|
mode_t mode, |
||||
|
unsigned int value); |
||||
|
|
||||
|
PTW32_DLLPORT int __cdecl sem_close (sem_t * sem); |
||||
|
|
||||
|
PTW32_DLLPORT int __cdecl sem_unlink (const char * name); |
||||
|
|
||||
|
PTW32_DLLPORT int __cdecl sem_getvalue (sem_t * sem, |
||||
|
int * sval); |
||||
|
|
||||
|
#if defined(__cplusplus) |
||||
|
} /* End of extern "C" */ |
||||
|
#endif /* __cplusplus */ |
||||
|
|
||||
|
#undef PTW32_SEMAPHORE_LEVEL |
||||
|
#undef PTW32_SEMAPHORE_LEVEL_MAX |
||||
|
|
||||
|
#endif /* !SEMAPHORE_H */ |
@ -0,0 +1,14 @@ |
|||||
|
//{{NO_DEPENDENCIES}} |
||||
|
// Microsoft Visual C++ generated include file. |
||||
|
// Used by lwrserv.rc |
||||
|
|
||||
|
// Nächste Standardwerte für neue Objekte |
||||
|
// |
||||
|
#ifdef APSTUDIO_INVOKED |
||||
|
#ifndef APSTUDIO_READONLY_SYMBOLS |
||||
|
#define _APS_NEXT_RESOURCE_VALUE 101 |
||||
|
#define _APS_NEXT_COMMAND_VALUE 40001 |
||||
|
#define _APS_NEXT_CONTROL_VALUE 1001 |
||||
|
#define _APS_NEXT_SYMED_VALUE 101 |
||||
|
#endif |
||||
|
#endif |
@ -0,0 +1,13 @@ |
|||||
|
#ifndef __SGN_H__ |
||||
|
#define __SGN_H__ |
||||
|
inline float sgn(float x) |
||||
|
{ |
||||
|
if ( x == 0 ) |
||||
|
return 0.0f; |
||||
|
|
||||
|
if ( x > 0) |
||||
|
return 1.0f; |
||||
|
else |
||||
|
return -1.0f; |
||||
|
} |
||||
|
#endif |
@ -0,0 +1,234 @@ |
|||||
|
#ifndef _VEC_H_ |
||||
|
#define _VEC_H_ |
||||
|
#include <math.h> |
||||
|
#include "mat.h" |
||||
|
#include <ostream> |
||||
|
|
||||
|
template<class T, unsigned SIZE> class Mat; |
||||
|
template<class T, unsigned SIZE> class Vec; |
||||
|
|
||||
|
// Vector class for SIMPLE data types |
||||
|
template <class T, unsigned SIZE> class Vec |
||||
|
{ |
||||
|
public: |
||||
|
|
||||
|
// standard constructor |
||||
|
Vec<T,SIZE> () |
||||
|
{ // initialize all elements with zero |
||||
|
for (unsigned int i=0; i<SIZE; i++) |
||||
|
m_atData[i] = T(0); |
||||
|
} |
||||
|
|
||||
|
// construction with data array |
||||
|
Vec<T, SIZE> (const T atData[SIZE]) |
||||
|
{ |
||||
|
for (unsigned int i=0; i<SIZE; i++) |
||||
|
m_atData[i] = atData[i]; |
||||
|
} |
||||
|
|
||||
|
// copy constructor |
||||
|
Vec<T, SIZE> (const Vec<T, SIZE> &vec) |
||||
|
{ |
||||
|
if (this==&vec) |
||||
|
return; // nothing to do, it's me |
||||
|
for (unsigned int i=0; i<SIZE; i++) |
||||
|
m_atData[i] = vec.m_atData[i]; |
||||
|
} |
||||
|
|
||||
|
// destructor |
||||
|
~Vec () |
||||
|
{ // nothing to do here ... |
||||
|
} |
||||
|
|
||||
|
void setData (const T atData[SIZE]) |
||||
|
{ |
||||
|
for (unsigned int i=0; i<SIZE; i++) |
||||
|
m_atData[i] = atData[i]; |
||||
|
} |
||||
|
|
||||
|
void getData (const T atData[SIZE]) |
||||
|
{ |
||||
|
for (unsigned int i=0; i<SIZE; i++) |
||||
|
atData[i] = m_atData[i]; |
||||
|
} |
||||
|
|
||||
|
unsigned getDimension () |
||||
|
{ |
||||
|
return SIZE; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
Vec<T, SIZE> &operator = (const Vec<T, SIZE> &vec) |
||||
|
{ |
||||
|
if (this==&vec) |
||||
|
return (*this); // ok, it's me, so no L-value action |
||||
|
for (unsigned int i=0; i<SIZE; i++) // not me, so L-Value action: copy data |
||||
|
m_atData[i] = vec.m_atData[i]; |
||||
|
|
||||
|
return (*this); // also an R-value in e.g |
||||
|
// vec1 = vec2 = vec3; |
||||
|
// L-Value = R-Value/L-Value = R-Value |
||||
|
} |
||||
|
|
||||
|
Vec<T, SIZE> &operator = (const T atData[SIZE]) |
||||
|
{ |
||||
|
for (unsigned int i=0; i<SIZE; i++) // not me, so L-Value action: copy data |
||||
|
m_atData[i] = atData[i]; |
||||
|
|
||||
|
return (*this); // also an R-value in e.g. |
||||
|
// vec1 = vec2 + (vec2=atData); // parenthesis () needed to evaluate expression vec2=atData |
||||
|
// L-Val = R-Val + R-Val |
||||
|
// " = " + (L-Val = R-Val) |
||||
|
} |
||||
|
|
||||
|
// usage of operator: |
||||
|
// vec(i) = var; // 0 <= i <= SIZE-1 |
||||
|
// var = vec(i); |
||||
|
// vec1(i) = vec2(j); |
||||
|
T &operator () (unsigned i) |
||||
|
{ |
||||
|
if (i>=SIZE) |
||||
|
i = SIZE-1; // !!! operator clips index ... |
||||
|
return m_atData[i]; // ... so we can safely return a reference |
||||
|
} |
||||
|
|
||||
|
T operator () (unsigned i) const |
||||
|
{ |
||||
|
if (i>=SIZE) |
||||
|
i = SIZE-1; |
||||
|
return m_atData[i]; |
||||
|
} |
||||
|
|
||||
|
void operator += (const Vec<T, SIZE> &vec) |
||||
|
{ |
||||
|
for (int i=0; i<SIZE; i++) |
||||
|
m_atData[i] += vec.m_atData[i]; |
||||
|
} |
||||
|
|
||||
|
Vec<T, SIZE> operator + (const Vec<T, SIZE> &vec) |
||||
|
{ |
||||
|
Vec<T, SIZE> buf (m_atData); |
||||
|
for (unsigned int i=0; i<SIZE; i++) |
||||
|
buf.m_atData[i] += vec.m_atData[i]; |
||||
|
return buf; |
||||
|
} |
||||
|
|
||||
|
void operator -= (const Vec<T, SIZE> &vec) |
||||
|
{ |
||||
|
for (unsigned int i=0; i<SIZE; i++) |
||||
|
m_atData[i] -= vec.m_atData[i]; |
||||
|
} |
||||
|
|
||||
|
// binary - |
||||
|
// vec1 - vec2 i.e. (*this) - vec |
||||
|
Vec<T, SIZE> operator - (const Vec<T, SIZE> &vec) |
||||
|
{ |
||||
|
Vec<T, SIZE> buf (m_atData); |
||||
|
for (unsigned int i=0; i<SIZE; i++) |
||||
|
buf.m_atData[i] -= vec.m_atData[i]; |
||||
|
return buf; |
||||
|
} |
||||
|
|
||||
|
// unary - |
||||
|
// -vec i.e. -(*this) |
||||
|
Vec<T, SIZE> operator - () |
||||
|
{ |
||||
|
T atBuffer[SIZE]; |
||||
|
for (int i=0; i<SIZE; i++) |
||||
|
atBuffer[i] = -m_atData[i]; |
||||
|
return Vec<T, SIZE> (atBuffer); |
||||
|
} |
||||
|
|
||||
|
T operator * (const Vec<T, SIZE> & vec) |
||||
|
{ |
||||
|
T dp = T(0); |
||||
|
for (int i=0; i<SIZE; i++) |
||||
|
dp += m_atData[i]*vec.m_atData[i]; |
||||
|
return dp; |
||||
|
} |
||||
|
|
||||
|
void operator *= (T tScale) |
||||
|
{ |
||||
|
for (unsigned int i=0; i<SIZE; i++) |
||||
|
m_atData[i] *= tScale; |
||||
|
} |
||||
|
|
||||
|
Vec<T, SIZE> operator * (T tScale) |
||||
|
{ |
||||
|
T atBuffer[SIZE]; |
||||
|
for (unsigned int i=0; i<SIZE; i++) |
||||
|
atBuffer[i] = m_atData[i]*tScale; |
||||
|
return Vec<T, SIZE> (atBuffer); |
||||
|
} |
||||
|
|
||||
|
Vec<T, SIZE> operator * (const Mat<T, SIZE> &mat) |
||||
|
{ |
||||
|
Vec<T, SIZE> vec; |
||||
|
for (unsigned int j=0; j<SIZE; j++) |
||||
|
for (unsigned int i=0; i<SIZE; i++) |
||||
|
vec(j) += m_atData[i]*mat(i,j); |
||||
|
return vec; |
||||
|
} |
||||
|
|
||||
|
T norm () |
||||
|
{ |
||||
|
T retval = 0; |
||||
|
|
||||
|
// this * this |
||||
|
for (int i=0; i<SIZE; i++) |
||||
|
retval += m_atData[i] * m_atData[i]; |
||||
|
sqrt(retval); |
||||
|
return retval; |
||||
|
} |
||||
|
|
||||
|
Vec<T, SIZE> x(const Vec<T, SIZE> &vec) |
||||
|
{ |
||||
|
T temp[SIZE]; |
||||
|
temp[0] = m_atData[1]*vec(2) - m_atData[2]*vec(1); |
||||
|
temp[1] = m_atData[2]*vec(0) - m_atData[0]*vec(2); |
||||
|
temp[2] = m_atData[0]*vec(1) - m_atData[1]*vec(0); |
||||
|
temp[3] = vec(3); |
||||
|
return Vec<T, SIZE> (temp); |
||||
|
} |
||||
|
|
||||
|
private: |
||||
|
|
||||
|
T m_atData[SIZE]; |
||||
|
|
||||
|
}; // class Vec |
||||
|
|
||||
|
|
||||
|
// some common vector classes (abbr. names) |
||||
|
typedef Vec<float, 2> Vec2f; |
||||
|
typedef Vec<float, 3> Vec3f; |
||||
|
typedef Vec<float, 4> Vec4f; |
||||
|
|
||||
|
typedef Vec<double, 2> Vec2d; |
||||
|
typedef Vec<double, 3> Vec3d; |
||||
|
typedef Vec<double, 4> Vec4d; |
||||
|
|
||||
|
typedef Vec<int, 2> Vec2i; |
||||
|
typedef Vec<int, 3> Vec3i; |
||||
|
typedef Vec<int, 4> Vec4i; |
||||
|
|
||||
|
typedef Vec<bool, 2> Vec2b; |
||||
|
typedef Vec<bool, 3> Vec3b; |
||||
|
typedef Vec<bool, 4> Vec4b; |
||||
|
|
||||
|
|
||||
|
template <class T, unsigned SIZE> |
||||
|
static std::ostream& operator<< (std::ostream& output,const Vec<T,SIZE> &vec) |
||||
|
{ |
||||
|
output << "( "; |
||||
|
for(unsigned int i = 0 ; i< SIZE; ++i) |
||||
|
{ |
||||
|
output << vec(i); |
||||
|
if (i<SIZE-1) |
||||
|
output << " , "; |
||||
|
else |
||||
|
output << " )"; |
||||
|
} |
||||
|
return output; |
||||
|
} |
||||
|
|
||||
|
#endif |
Write
Preview
Loading…
Cancel
Save
Reference in new issue