- Fix bug with car category in Shadow's driver

- Update mpa12-murasama by Julien

git-svn-id: https://svn.code.sf.net/p/speed-dreams/code/trunk@6067 30fe4595-0a0c-4342-8851-515496e4dcbd

Former-commit-id: 4feb17425ab399bf8a5cb46df7e0d257e909e107
Former-commit-id: da0cd853da78bcde300754c3a51e92316fa683e6
This commit is contained in:
torcs-ng 2015-08-11 21:07:04 +00:00
parent 8f1467784d
commit c91116454f
9 changed files with 51 additions and 83 deletions

View file

@ -20,7 +20,7 @@
#include "CarModel.h" #include "CarModel.h"
#include "Quadratic.h" #include "Quadratic.h"
#include "Utils.h" #include "Utils.h"
#include "Driver.h" //#include "Driver.h"
////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////
// Construction/Destruction // Construction/Destruction
@ -45,6 +45,7 @@ CarModel::CarModel()
BRAKESCALE(0), BRAKESCALE(0),
BRAKEFORCE(0), BRAKEFORCE(0),
BRAKELIMIT(0.0),
CA(0), CA(0),
CA_FW(0), CA_FW(0),
@ -288,11 +289,11 @@ double CarModel::CalcBreaking(double k0, double kz0, double k1, double kz1, doub
acc = BRAKESCALE * Ftanroad / (MASS * ( 3 + SKILL) / 4); acc = BRAKESCALE * Ftanroad / (MASS * ( 3 + SKILL) / 4);
if (TDriver::UseBrakeLimit) if (BRAKELIMIT)
{ {
double Radius = 1.0 / fabs(Kz); double Radius = 1.0 / fabs(Kz);
double factor = MIN(1.0,MAX(0.39, (Radius - 190.0) / 100.0)); double factor = MIN(1.0,MAX(0.39, (Radius - 190.0) / 100.0));
acc = MAX(acc, TDriver::BrakeLimit * factor); acc = MAX(acc, BRAKELIMIT * factor);
} }
double inner = MX(0, v * v - 2 * acc * dist ); double inner = MX(0, v * v - 2 * acc * dist );

View file

@ -55,6 +55,7 @@ public:
double BRAKESCALE; // Scaling of Brake double BRAKESCALE; // Scaling of Brake
double BRAKEFORCE; // Brake force max double BRAKEFORCE; // Brake force max
float BRAKELIMIT; // BrakeLimit
double CA; // aerodynamic downforce constant -- total. double CA; // aerodynamic downforce constant -- total.
double CA_FW; // aerodynamic downforce constant -- front wing. double CA_FW; // aerodynamic downforce constant -- front wing.

View file

@ -47,6 +47,7 @@
//int TDriver::NBBOTS = MAX_NBBOTS; // Nbr of drivers/robots //int TDriver::NBBOTS = MAX_NBBOTS; // Nbr of drivers/robots
//const char* TDriver::ROBOT_DIR = "drivers/shadow"; // Sub path to dll //const char* TDriver::ROBOT_DIR = "drivers/shadow"; // Sub path to dll
//const char* TDriver::DEFAULTCARTYPE = "car1-trb1"; // Default car type //const char* TDriver::DEFAULTCARTYPE = "car1-trb1"; // Default car type
const char* TDriver::robot_name="shadow_trb1";
int TDriver::RobotType = 0; int TDriver::RobotType = 0;
bool TDriver::AdvancedParameters = false; // Advanced parameters bool TDriver::AdvancedParameters = false; // Advanced parameters
bool TDriver::UseOldSkilling = false; // Use old skilling bool TDriver::UseOldSkilling = false; // Use old skilling

View file

@ -39,7 +39,6 @@
#include "LinearRegression.h" #include "LinearRegression.h"
#include "PtInfo.h" #include "PtInfo.h"
#include "Strategy.h" #include "Strategy.h"
#include "teammanager.h" #include "teammanager.h"
#define SECT_PRIV "private" #define SECT_PRIV "private"
@ -197,7 +196,7 @@ public:
static int NBBOTS; // Nbr of cars static int NBBOTS; // Nbr of cars
double CurrSimTime; // Current simulation time double CurrSimTime; // Current simulation time
const char *robot_name; static const char *robot_name;
double Frc; // Friction coefficient double Frc; // Friction coefficient
//bool UseBrakeLimit; // Enable/disable brakelimit //bool UseBrakeLimit; // Enable/disable brakelimit

View file

@ -38,7 +38,7 @@ private:
PIT_BEFORE, PIT_BEFORE,
PIT_ENTER, PIT_ENTER,
PIT_ASKED, PIT_ASKED,
PIT_EXIT, PIT_EXIT
}; };
private: private:
@ -46,7 +46,6 @@ private:
const PitPath& m_pitPath; const PitPath& m_pitPath;
int m_state; int m_state;
double m_lastFuel; double m_lastFuel;
double m_totalFuel; double m_totalFuel;
double m_lastDamage; double m_lastDamage;

View file

@ -117,8 +117,7 @@ static void setRobotName(const char *name)
void* getFileHandle() void* getFileHandle()
{ {
// First we try to use the directories relative to the installation path // First we try to use the directories relative to the installation path
snprintf(pathBuffer, BUFSIZE, "%sdrivers/%s/%s.xml", snprintf(pathBuffer, BUFSIZE, "%sdrivers/%s/%s.xml", GetLocalDir(), robot_name, robot_name);
GetLocalDir(), robot_name, robot_name);
// Test local installation path // Test local installation path
void *robot_settings = GfParmReadFile(xml_path, GFPARM_RMODE_STD); void *robot_settings = GfParmReadFile(xml_path, GFPARM_RMODE_STD);
@ -126,15 +125,13 @@ void* getFileHandle()
if (!robot_settings) if (!robot_settings)
{ {
// If not found, use global installation path // If not found, use global installation path
snprintf(pathBuffer, BUFSIZE, "%sdrivers/%s/%s.xml", snprintf(pathBuffer, BUFSIZE, "%sdrivers/%s/%s.xml", GetDataDir(), robot_name, robot_name);
GetDataDir(), robot_name, robot_name);
robot_settings = GfParmReadFile(xml_path, GFPARM_RMODE_STD); robot_settings = GfParmReadFile(xml_path, GFPARM_RMODE_STD);
} }
return robot_settings; return robot_settings;
} }
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
// Carset specific init functions // Carset specific init functions
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
@ -208,7 +205,7 @@ void SetupSHADOW_mpa1()
// Schismatic init for shadow_mpa11 // Schismatic init for shadow_mpa11
void SetupSHADOW_mpa11() void SetupSHADOW_mpa11()
{ {
// Add shadow_mpa1 specific initialization here // Add shadow_mpa11 specific initialization here
robot_type = SHADOW_MPA11; robot_type = SHADOW_MPA11;
}; };
@ -413,12 +410,10 @@ extern "C" int moduleWelcome(const tModWelcomeIn* welcomeIn,
{ {
char section_buf[BUFSIZE]; char section_buf[BUFSIZE];
const char *section = section_buf; const char *section = section_buf;
snprintf(section_buf, BUFSIZE, "%s/%s/%d", snprintf(section_buf, BUFSIZE, "%s/%s/%d", ROB_SECT_ROBOTS, ROB_LIST_INDEX, 0);
ROB_SECT_ROBOTS, ROB_LIST_INDEX, 0);
// Try to get first driver from index 0 // Try to get first driver from index 0
const char *driver_name = GfParmGetStrNC(robot_settings, section, const char *driver_name = GfParmGetStrNC(robot_settings, section, ROB_ATTR_NAME, undefined);
ROB_ATTR_NAME, undefined);
// Check whether index 0 is used as start index // Check whether index 0 is used as start index
if (strncmp(driver_name, undefined, strlen(undefined)) != 0) if (strncmp(driver_name, undefined, strlen(undefined)) != 0)
@ -441,21 +436,17 @@ extern "C" int moduleWelcome(const tModWelcomeIn* welcomeIn,
memset(&DriverDescs[i * DRIVERLEN], 0, DRIVERLEN); memset(&DriverDescs[i * DRIVERLEN], 0, DRIVERLEN);
memset(&CarNames[i * DRIVERLEN], 0, DRIVERLEN); memset(&CarNames[i * DRIVERLEN], 0, DRIVERLEN);
snprintf(section_buf, BUFSIZE, "%s/%s/%d", snprintf(section_buf, BUFSIZE, "%s/%s/%d", ROB_SECT_ROBOTS, ROB_LIST_INDEX, i + indexOffset);
ROB_SECT_ROBOTS, ROB_LIST_INDEX, i + indexOffset); const char *driver_name = GfParmGetStr(robot_settings, section, ROB_ATTR_NAME, undefined);
const char *driver_name = GfParmGetStr(robot_settings, section,
ROB_ATTR_NAME, undefined);
if (strncmp(driver_name, undefined, strlen(undefined)) != 0) if (strncmp(driver_name, undefined, strlen(undefined)) != 0)
{ {
// This driver is defined in robot's xml-file // This driver is defined in robot's xml-file
strncpy(&DriverNames[i * DRIVERLEN], driver_name, DRIVERLEN - 1); strncpy(&DriverNames[i * DRIVERLEN], driver_name, DRIVERLEN - 1);
const char *driver_desc = GfParmGetStr(robot_settings, section, const char *driver_desc = GfParmGetStr(robot_settings, section, ROB_ATTR_DESC, defaultBotDesc[i]);
ROB_ATTR_DESC, defaultBotDesc[i]);
strncpy(&DriverDescs[i * DRIVERLEN], driver_desc, DRIVERLEN - 1); strncpy(&DriverDescs[i * DRIVERLEN], driver_desc, DRIVERLEN - 1);
const char *car_name = const char *car_name = GfParmGetStr(robot_settings, section, ROB_ATTR_CAR, "nocar");
GfParmGetStr(robot_settings, section, ROB_ATTR_CAR, "nocar");
strncpy(&CarNames[i * DRIVERLEN], car_name, DRIVERLEN - 1); strncpy(&CarNames[i * DRIVERLEN], car_name, DRIVERLEN - 1);
NBBOTS = i + 1; NBBOTS = i + 1;
@ -471,9 +462,7 @@ extern "C" int moduleWelcome(const tModWelcomeIn* welcomeIn,
} }
LogSHADOW.debug("NBBOTS: %d (of %d)\n", NBBOTS, MAXNBBOTS); LogSHADOW.debug("NBBOTS: %d (of %d)\n", NBBOTS, MAXNBBOTS);
if (strncmp(robot_name, "shadow_trb1", strlen("shadow_trb1")) == 0) if (strncmp(robot_name,"shadow_sc", strlen("shadow_sc")) == 0)
SetupSHADOW_trb1();
else if (strncmp(robot_name,"shadow_sc", strlen("shadow_sc")) == 0)
SetupSHADOW_sc(); SetupSHADOW_sc();
else if (strncmp(robot_name,"shadow_srw", strlen("shadow_srw")) == 0) else if (strncmp(robot_name,"shadow_srw", strlen("shadow_srw")) == 0)
SetupSHADOW_srw(); SetupSHADOW_srw();
@ -487,12 +476,14 @@ extern "C" int moduleWelcome(const tModWelcomeIn* welcomeIn,
SetupSHADOW_rs(); SetupSHADOW_rs();
else if (strncmp(robot_name,"shadow_lp1", strlen("shadow_lp1")) == 0) else if (strncmp(robot_name,"shadow_lp1", strlen("shadow_lp1")) == 0)
SetupSHADOW_lp1(); SetupSHADOW_lp1();
else if (strncmp(robot_name,"shadow_mpa1", strlen("shadow_mpa1")) == 0)
SetupSHADOW_mpa1();
else if (strncmp(robot_name,"shadow_mpa11", strlen("shadow_mpa11")) == 0) else if (strncmp(robot_name,"shadow_mpa11", strlen("shadow_mpa11")) == 0)
SetupSHADOW_mpa11(); SetupSHADOW_mpa11();
else if (strncmp(robot_name,"shadow_mpa12", strlen("shadow_mpa12")) == 0) else if (strncmp(robot_name,"shadow_mpa12", strlen("shadow_mpa12")) == 0)
SetupSHADOW_mpa12(); SetupSHADOW_mpa12();
else if (strncmp(robot_name, "shadow_mpa1", strlen("shadow_mpa1")) == 0)
SetupSHADOW_mpa1();
else
SetupSHADOW_trb1();
// Set max nb of interfaces to return. // Set max nb of interfaces to return.
@ -621,19 +612,18 @@ extern "C" int shadow(tModInfo *modInfo)
char SectionBuf[BUFSIZE]; char SectionBuf[BUFSIZE];
char *Section = SectionBuf; char *Section = SectionBuf;
snprintf(SectionBuf, BUFSIZE, "%s/%s/%d", snprintf(SectionBuf, BUFSIZE, "%s/%s/%d", ROB_SECT_ROBOTS, ROB_LIST_INDEX, 0);
ROB_SECT_ROBOTS, ROB_LIST_INDEX, 0);
for (int i = 0; i < NBBOTS; ++i) for (int i = 0; i < NBBOTS; ++i)
{ {
const char *DriverName = GfParmGetStr(robot_settings, Section, const char *DriverName = GfParmGetStr(robot_settings, Section, ROB_ATTR_NAME, defaultBotName[i]);
ROB_ATTR_NAME, defaultBotName[i]);
strncpy(&DriverNames[i * DRIVERLEN], DriverName, DRIVERLEN - 1); strncpy(&DriverNames[i * DRIVERLEN], DriverName, DRIVERLEN - 1);
const char *DriverDesc = GfParmGetStr(robot_settings, Section,
ROB_ATTR_DESC, defaultBotDesc[i]); const char *DriverDesc = GfParmGetStr(robot_settings, Section, ROB_ATTR_DESC, defaultBotDesc[i]);
strncpy(&DriverDescs[i * DRIVERLEN], DriverDesc, DRIVERLEN - 1); strncpy(&DriverDescs[i * DRIVERLEN], DriverDesc, DRIVERLEN - 1);
} }
} }
return moduleInitialize(modInfo); return moduleInitialize(modInfo);
} }

View file

@ -66,13 +66,13 @@ void SimpleStrategy::setFuelAtRaceStart(tTrack* t, void **carParmHandle, tSituat
/* Trivial strategy: fill in as much fuel as required for the whole race, or if the tank is /* Trivial strategy: fill in as much fuel as required for the whole race, or if the tank is
too small fill the tank completely. */ too small fill the tank completely. */
// Load and set parameters. // Load and set parameters.
maxFuel = GfParmGetNum(*carParmHandle, SECT_CAR, PRM_TANK, (char*)NULL, MAX_FUEL_TANK); maxFuel = (tdble)(GfParmGetNum(*carParmHandle, SECT_CAR, PRM_TANK, (char*)NULL, MAX_FUEL_TANK));
fuelPerMeter = GfParmGetNum(*carParmHandle, SECT_PRIV, PRV_FUELPERMETERS, (char*)NULL, MAX_FUEL_PER_METER); fuelPerMeter = GfParmGetNum(*carParmHandle, SECT_PRIV, PRV_FUELPERMETERS, (char*)NULL, MAX_FUEL_PER_METER);
fuelPerLap = GfParmGetNum(*carParmHandle, SECT_PRIV, PRV_FUELPERLAPS, (char*)NULL, t->length * fuelPerMeter); fuelPerLap = GfParmGetNum(*carParmHandle, SECT_PRIV, PRV_FUELPERLAPS, (char*)NULL, t->length * fuelPerMeter);
fullfuel = GfParmGetNum(*carParmHandle, SECT_PRIV, PRV_FULL_FUEL, (char*)NULL, 0.0); fullfuel = GfParmGetNum(*carParmHandle, SECT_PRIV, PRV_FULL_FUEL, (char*)NULL, 0.0);
fuel_Strat = (int)GfParmGetNum(*carParmHandle, SECT_PRIV, PRV_PITSTRAT, (char*)NULL, 0.0); fuel_Strat = (int)GfParmGetNum(*carParmHandle, SECT_PRIV, PRV_PITSTRAT, (char*)NULL, 0.0);
test_Pitstop = GfParmGetNum(*carParmHandle, SECT_PRIV, PRV_PITSTOP, (char*)NULL, 0.0); test_Pitstop = (bool)(GfParmGetNum(*carParmHandle, SECT_PRIV, PRV_PITSTOP, (char*)NULL, 0.0));
test_qualifTime = GfParmGetNum(*carParmHandle, SECT_PRIV, PRV_CHKQUALIF, (char*)NULL, 0.0); test_qualifTime = (bool)(GfParmGetNum(*carParmHandle, SECT_PRIV, PRV_CHKQUALIF, (char*)NULL, 0.0));
strategy_verbose = (int)GfParmGetNum(*carParmHandle, SECT_PRIV, PRV_VERBOSE, (char*)NULL, 0.0); strategy_verbose = (int)GfParmGetNum(*carParmHandle, SECT_PRIV, PRV_VERBOSE, (char*)NULL, 0.0);
if ( fuel_Strat < 1 ) if ( fuel_Strat < 1 )
@ -368,7 +368,7 @@ float SimpleStrategy::pitRefuel(tCarElt* car, tSituation *s)
fuelToEnd = MIN(getRefuel1(lapsToEnd), getRefuel2(lapsToEnd)); fuelToEnd = MIN(getRefuel1(lapsToEnd), getRefuel2(lapsToEnd));
//m_remainingstops = int(floor(fuelToEnd / car->_tank)); //m_remainingstops = int(floor(fuelToEnd / car->_tank));
m_remainingstops = fabs(fuelToEnd / car->_tank); m_remainingstops = (int)(fabs(fuelToEnd / car->_tank));
int num_remStops = m_remainingstops + 1; int num_remStops = m_remainingstops + 1;
m_fuelperstint = car->_tank - car->_fuel; m_fuelperstint = car->_tank - car->_fuel;
fuel = m_fuelperstint * 0.90; fuel = m_fuelperstint * 0.90;
@ -483,7 +483,7 @@ float SimpleStrategy::calcFuel(double totalFuel)
nb_pitstop = 1 + fabs(totalFuel / maxFuel); nb_pitstop = 1 + fabs(totalFuel / maxFuel);
m_lastfuel = totalFuel / nb_pitstop; //Max refuel per pit stop m_lastfuel = totalFuel / nb_pitstop; //Max refuel per pit stop
nb_laps = 1 + floor( m_lastfuel / fuelPerLap); nb_laps = (int)(1 + floor( m_lastfuel / fuelPerLap));
fuelAtStart = nb_laps * fuelPerLap; fuelAtStart = nb_laps * fuelPerLap;
return fuelAtStart; return fuelAtStart;

View file

@ -33,13 +33,7 @@ Utils::~Utils()
{ {
} }
double Utils::ClosestPtOnLine( double Utils::ClosestPtOnLine( double ptx, double pty, double px, double py, double vx, double vy )
double ptx,
double pty,
double px,
double py,
double vx,
double vy )
{ {
// P from AB // P from AB
// Q is closest pt on AB // Q is closest pt on AB
@ -58,6 +52,7 @@ double Utils::ClosestPtOnLine(
double num = pax * vx + pay * vy; double num = pax * vx + pay * vy;
double t = num / den; double t = num / den;
return t; return t;
} }
@ -85,36 +80,17 @@ bool Utils::LineCrossesLine( double p0x, double p0y, double v0x, double v0y, dou
return true; return true;
} }
bool Utils::LineCrossesLine( bool Utils::LineCrossesLine( const Vec2d& p0, const Vec2d& v0, const Vec2d& p1, const Vec2d& v1, double& t )
const Vec2d& p0,
const Vec2d& v0,
const Vec2d& p1,
const Vec2d& v1,
double& t )
{ {
return LineCrossesLine(p0.x, p0.y, v0.x, v0.y, p1.x, p1.y, v1.x, v1.y, t); return LineCrossesLine(p0.x, p0.y, v0.x, v0.y, p1.x, p1.y, v1.x, v1.y, t);
} }
bool Utils::LineCrossesLineXY( bool Utils::LineCrossesLineXY(const Vec3d& p0, const Vec3d& v0, const Vec3d& p1, const Vec3d& v1, double& t )
const Vec3d& p0,
const Vec3d& v0,
const Vec3d& p1,
const Vec3d& v1,
double& t )
{ {
return LineCrossesLine(p0.x, p0.y, v0.x, v0.y, p1.x, p1.y, v1.x, v1.y, t); return LineCrossesLine(p0.x, p0.y, v0.x, v0.y, p1.x, p1.y, v1.x, v1.y, t);
} }
bool Utils::LineCrossesLine( bool Utils::LineCrossesLine(const Vec2d& p0, const Vec2d& v0, const Vec2d& p1, const Vec2d& v1, double& t0, double& t1 )
const Vec2d& p0,
const Vec2d& v0,
const Vec2d& p1,
const Vec2d& v1,
double& t0,
double& t1 )
{ {
double denom = v0.x * v1.y - v0.y * v1.x; double denom = v0.x * v1.y - v0.y * v1.x;
if( denom == 0 ) if( denom == 0 )
@ -129,10 +105,7 @@ bool Utils::LineCrossesLine(
return true; return true;
} }
double Utils::CalcCurvature( double Utils::CalcCurvature( double p1x, double p1y, double p2x, double p2y, double p3x, double p3y )
double p1x, double p1y,
double p2x, double p2y,
double p3x, double p3y )
{ {
double px = p1x - p2x; double px = p1x - p2x;
double py = p1y - p2y; double py = p1y - p2y;
@ -141,10 +114,8 @@ double Utils::CalcCurvature(
double sx = p3x - p1x; double sx = p3x - p1x;
double sy = p3y - p1y; double sy = p3y - p1y;
double K = (2 * (px * qy - py * qx)) / double K = (2 * (px * qy - py * qx)) / sqrt((px * px + py * py) * (qx * qx + qy * qy) * (sx * sx + sy * sy));
sqrt((px * px + py * py) *
(qx * qx + qy * qy) *
(sx * sx + sy * sy));
return K; return K;
} }
@ -159,6 +130,7 @@ double Utils::CalcCurvatureTan( const Vec2d& p1, const Vec2d& tangent, const Vec
Vec2d u = VecNorm(p2 - p1); Vec2d u = VecNorm(p2 - p1);
Vec2d q = (p1 + p2) * 0.5; Vec2d q = (p1 + p2) * 0.5;
double radius; double radius;
if( !LineCrossesLine(p1, v, q, u, radius) ) if( !LineCrossesLine(p1, v, q, u, radius) )
return 0; return 0;
else else
@ -175,6 +147,7 @@ double Utils::CalcCurvatureZ( const Vec3d& p1, const Vec3d& p2, const Vec3d& p3
double x1 = 0; double x1 = 0;
double x2 = (p1 - p2).len(); double x2 = (p1 - p2).len();
double x3 = x2 + (p2 - p3).len(); double x3 = x2 + (p2 - p3).len();
return CalcCurvature(x1, p1.z, x2, p2.z, x3, p3.z); return CalcCurvature(x1, p1.z, x2, p2.z, x3, p3.z);
} }
@ -191,6 +164,7 @@ bool Utils::CalcTangent( const Vec2d& p1, const Vec2d& p2, const Vec2d& p3, Vec2
if( p1 != p3 ) if( p1 != p3 )
{ {
tangent = VecUnit(p3 - p1); tangent = VecUnit(p3 - p1);
return true; return true;
} }
@ -201,8 +175,10 @@ bool Utils::CalcTangent( const Vec2d& p1, const Vec2d& p2, const Vec2d& p3, Vec2
// tangent = p2 - centre; // tangent = p2 - centre;
// tangent = VecNorm(p2 - centre); // tangent = VecNorm(p2 - centre);
tangent = VecUnit(VecNorm(p2 - centre)); tangent = VecUnit(VecNorm(p2 - centre));
if( norm1 * (p3 - p1) < 0 ) if( norm1 * (p3 - p1) < 0 )
tangent = -tangent; tangent = -tangent;
return true; return true;
} }
@ -220,14 +196,15 @@ double Utils::InterpCurvatureRad( double k0, double k1, double t )
// k = (k0 * k1) / (k1 + (k0 - k1) * t) // k = (k0 * k1) / (k1 + (k0 - k1) * t)
// //
double den = k1 + (k0 - k1) * t; double den = k1 + (k0 - k1) * t;
if( fabs(den) < 0.000001 ) if( fabs(den) < 0.000001 )
den = 0.000001; den = 0.000001;
return k0 * k1 / den; return k0 * k1 / den;
} }
double Utils::InterpCurvature( double k0, double k1, double t ) double Utils::InterpCurvature( double k0, double k1, double t )
{ {
// return InterpCurvatureRad(k0, k1, t);
return InterpCurvatureLin(k0, k1, t); return InterpCurvatureLin(k0, k1, t);
} }